You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
proxysql/lib/MySQL_Logger.cpp

990 lines
24 KiB

#include <fstream>
#include "proxysql.h"
#include "cpp.h"
#include "MySQL_PreparedStatement.h"
#include "MySQL_Logger.hpp"
#include <dirent.h>
#include <libgen.h>
#include "../deps/json/json.hpp"
using json = nlohmann::json;
#ifdef DEBUG
#define DEB "_DEBUG"
#else
#define DEB ""
#endif /* DEBUG */
#define PROXYSQL_MYSQL_LOGGER_VERSION "2.0.0714" DEB
extern MySQL_Logger *GloMyLogger;
static uint8_t mysql_encode_length(uint64_t len, unsigned char *hd) {
if (len < 251) return 1;
if (len < 65536) { if (hd) { *hd=0xfc; }; return 3; }
if (len < 16777216) { if (hd) { *hd=0xfd; }; return 4; }
if (hd) { *hd=0xfe; }
return 9;
}
static inline int write_encoded_length(unsigned char *p, uint64_t val, uint8_t len, char prefix) {
if (len==1) {
*p=(char)val;
return 1;
}
*p=prefix;
p++;
memcpy(p,&val,len-1);
return len;
}
MySQL_Event::MySQL_Event (log_event_type _et, uint32_t _thread_id, char * _username, char * _schemaname , uint64_t _start_time , uint64_t _end_time , uint64_t _query_digest, char *_client, size_t _client_len) {
thread_id=_thread_id;
username=_username;
schemaname=_schemaname;
start_time=_start_time;
end_time=_end_time;
query_digest=_query_digest;
client=_client;
client_len=_client_len;
et=_et;
hid=UINT64_MAX;
server=NULL;
extra_info = NULL;
have_affected_rows=false;
affected_rows=0;
have_rows_sent=false;
rows_sent=0;
}
void MySQL_Event::set_affected_rows(uint64_t ar) {
have_affected_rows=true;
affected_rows=ar;
}
void MySQL_Event::set_rows_sent(uint64_t rs) {
have_rows_sent=true;
rows_sent=rs;
}
void MySQL_Event::set_extra_info(char *_err) {
extra_info = _err;
}
void MySQL_Event::set_query(const char *ptr, int len) {
query_ptr=(char *)ptr;
query_len=len;
}
void MySQL_Event::set_server(int _hid, const char *ptr, int len) {
server=(char *)ptr;
server_len=len;
hid=_hid;
}
uint64_t MySQL_Event::write(std::fstream *f, MySQL_Session *sess) {
uint64_t total_bytes=0;
switch (et) {
case PROXYSQL_COM_QUERY:
case PROXYSQL_COM_STMT_EXECUTE:
case PROXYSQL_COM_STMT_PREPARE:
if (mysql_thread___eventslog_format==1) { // format 1 , binary
total_bytes=write_query_format_1(f);
} else { // format 2 , json
total_bytes=write_query_format_2_json(f);
}
break;
case PROXYSQL_MYSQL_AUTH_OK:
case PROXYSQL_MYSQL_AUTH_ERR:
case PROXYSQL_MYSQL_AUTH_CLOSE:
case PROXYSQL_MYSQL_AUTH_QUIT:
case PROXYSQL_MYSQL_INITDB:
case PROXYSQL_ADMIN_AUTH_OK:
case PROXYSQL_ADMIN_AUTH_ERR:
case PROXYSQL_ADMIN_AUTH_CLOSE:
case PROXYSQL_ADMIN_AUTH_QUIT:
case PROXYSQL_SQLITE_AUTH_OK:
case PROXYSQL_SQLITE_AUTH_ERR:
case PROXYSQL_SQLITE_AUTH_CLOSE:
case PROXYSQL_SQLITE_AUTH_QUIT:
write_auth(f, sess);
break;
default:
break;
}
return total_bytes;
}
void MySQL_Event::write_auth(std::fstream *f, MySQL_Session *sess) {
json j;
j["timestamp"] = start_time/1000;
{
time_t timer=start_time/1000/1000;
struct tm* tm_info;
tm_info = localtime(&timer);
char buffer1[64];
char buffer2[64];
strftime(buffer1, 32, "%Y-%m-%d %H:%M:%S", tm_info);
sprintf(buffer2,"%s.%03u", buffer1, (unsigned)(start_time%1000000)/1000);
j["time"] = buffer2;
}
j["thread_id"] = thread_id;
if (username) {
j["username"] = username;
} else {
j["username"] = "";
}
if (schemaname) {
j["schemaname"] = schemaname;
} else {
j["schemaname"] = "";
}
if (client) {
j["client_addr"] = client;
} else {
j["client_addr"] = "";
}
if (server) {
j["server_addr"] = server;
}
if (extra_info) {
j["extra_info"] = extra_info;
}
switch (et) {
case PROXYSQL_MYSQL_AUTH_OK:
j["event"]="MySQL_Client_Connect_OK";
break;
case PROXYSQL_MYSQL_AUTH_ERR:
j["event"]="MySQL_Client_Connect_ERR";
break;
case PROXYSQL_MYSQL_AUTH_CLOSE:
j["event"]="MySQL_Client_Close";
break;
case PROXYSQL_MYSQL_AUTH_QUIT:
j["event"]="MySQL_Client_Quit";
break;
case PROXYSQL_MYSQL_INITDB:
j["event"]="MySQL_Client_Init_DB";
break;
case PROXYSQL_ADMIN_AUTH_OK:
j["event"]="Admin_Connect_OK";
break;
case PROXYSQL_ADMIN_AUTH_ERR:
j["event"]="Admin_Connect_ERR";
break;
case PROXYSQL_ADMIN_AUTH_CLOSE:
j["event"]="Admin_Close";
break;
case PROXYSQL_ADMIN_AUTH_QUIT:
j["event"]="Admin_Quit";
break;
case PROXYSQL_SQLITE_AUTH_OK:
j["event"]="SQLite3_Connect_OK";
break;
case PROXYSQL_SQLITE_AUTH_ERR:
j["event"]="SQLite3_Connect_ERR";
break;
case PROXYSQL_SQLITE_AUTH_CLOSE:
j["event"]="SQLite3_Close";
break;
case PROXYSQL_SQLITE_AUTH_QUIT:
j["event"]="SQLite3_Quit";
break;
default:
break;
}
switch (et) {
case PROXYSQL_MYSQL_AUTH_CLOSE:
case PROXYSQL_ADMIN_AUTH_CLOSE:
case PROXYSQL_SQLITE_AUTH_CLOSE:
{
uint64_t curtime_real=realtime_time();
uint64_t curtime_mono=sess->thread->curtime;
uint64_t timediff = curtime_mono - sess->start_time;
uint64_t orig_time = curtime_real - timediff;
time_t timer= (orig_time)/1000/1000;
struct tm* tm_info;
tm_info = localtime(&timer);
char buffer1[64];
char buffer2[64];
strftime(buffer1, 32, "%Y-%m-%d %H:%M:%S", tm_info);
sprintf(buffer2,"%s.%03u", buffer1, (unsigned)(orig_time%1000000)/1000);
j["creation_time"] = buffer2;
//unsigned long long life = sess->thread->curtime - sess->start_time;
//life/=1000;
float f = timediff;
f /= 1000;
sprintf(buffer1, "%.3fms", f);
j["duration"] = buffer1;
}
break;
default:
break;
}
if (sess->client_myds) {
if (sess->client_myds->proxy_addr.addr) {
std::string s = sess->client_myds->proxy_addr.addr;
s += ":" + std::to_string(sess->client_myds->proxy_addr.port);
j["proxy_addr"] = s;
}
j["ssl"] = sess->client_myds->encrypted;
}
// for performance reason, we are moving the write lock
// right before the write to disk
GloMyLogger->wrlock();
*f << j.dump(-1, ' ', false, json::error_handler_t::replace) << std::endl;
}
uint64_t MySQL_Event::write_query_format_1(std::fstream *f) {
uint64_t total_bytes=0;
total_bytes+=1; // et
total_bytes+=mysql_encode_length(thread_id, NULL);
username_len=strlen(username);
total_bytes+=mysql_encode_length(username_len,NULL)+username_len;
schemaname_len=strlen(schemaname);
total_bytes+=mysql_encode_length(schemaname_len,NULL)+schemaname_len;
total_bytes+=mysql_encode_length(client_len,NULL)+client_len;
total_bytes+=mysql_encode_length(hid, NULL);
if (hid!=UINT64_MAX) {
total_bytes+=mysql_encode_length(server_len,NULL)+server_len;
}
total_bytes+=mysql_encode_length(start_time,NULL);
total_bytes+=mysql_encode_length(end_time,NULL);
total_bytes+=mysql_encode_length(affected_rows,NULL);
total_bytes+=mysql_encode_length(rows_sent,NULL);
total_bytes+=mysql_encode_length(query_digest,NULL);
total_bytes+=mysql_encode_length(query_len,NULL)+query_len;
// for performance reason, we are moving the write lock
// right before the write to disk
GloMyLogger->wrlock();
// write total length , fixed size
f->write((const char *)&total_bytes,sizeof(uint64_t));
//char prefix;
uint8_t len;
f->write((char *)&et,1);
len=mysql_encode_length(thread_id,buf);
write_encoded_length(buf,thread_id,len,buf[0]);
f->write((char *)buf,len);
len=mysql_encode_length(username_len,buf);
write_encoded_length(buf,username_len,len,buf[0]);
f->write((char *)buf,len);
f->write(username,username_len);
len=mysql_encode_length(schemaname_len,buf);
write_encoded_length(buf,schemaname_len,len,buf[0]);
f->write((char *)buf,len);
f->write(schemaname,schemaname_len);
len=mysql_encode_length(client_len,buf);
write_encoded_length(buf,client_len,len,buf[0]);
f->write((char *)buf,len);
f->write(client,client_len);
len=mysql_encode_length(hid,buf);
write_encoded_length(buf,hid,len,buf[0]);
f->write((char *)buf,len);
if (hid!=UINT64_MAX) {
len=mysql_encode_length(server_len,buf);
write_encoded_length(buf,server_len,len,buf[0]);
f->write((char *)buf,len);
f->write(server,server_len);
}
len=mysql_encode_length(start_time,buf);
write_encoded_length(buf,start_time,len,buf[0]);
f->write((char *)buf,len);
len=mysql_encode_length(end_time,buf);
write_encoded_length(buf,end_time,len,buf[0]);
f->write((char *)buf,len);
len=mysql_encode_length(affected_rows,buf);
write_encoded_length(buf,affected_rows,len,buf[0]);
f->write((char *)buf,len);
len=mysql_encode_length(rows_sent,buf);
write_encoded_length(buf,rows_sent,len,buf[0]);
f->write((char *)buf,len);
len=mysql_encode_length(query_digest,buf);
write_encoded_length(buf,query_digest,len,buf[0]);
f->write((char *)buf,len);
len=mysql_encode_length(query_len,buf);
write_encoded_length(buf,query_len,len,buf[0]);
f->write((char *)buf,len);
if (query_len) {
f->write(query_ptr,query_len);
}
return total_bytes;
}
uint64_t MySQL_Event::write_query_format_2_json(std::fstream *f) {
json j;
uint64_t total_bytes=0;
if (hid!=UINT64_MAX) {
j["hostgroup_id"] = hid;
} else {
j["hostgroup_id"] = -1;
}
j["thread_id"] = thread_id;
switch (et) {
case PROXYSQL_COM_STMT_EXECUTE:
j["event"]="COM_STMT_EXECUTE";
break;
case PROXYSQL_COM_STMT_PREPARE:
j["event"]="COM_STMT_PREPARE";
break;
default:
j["event"]="COM_QUERY";
break;
}
if (username) {
j["username"] = username;
} else {
j["username"] = "";
}
if (schemaname) {
j["schemaname"] = schemaname;
} else {
j["schemaname"] = "";
}
if (client) {
j["client"] = client;
} else {
j["client"] = "";
}
if (hid!=UINT64_MAX) {
if (server) {
j["server"] = server;
}
}
j["rows_affected"] = affected_rows;
j["rows_sent"] = rows_sent;
j["query"] = string(query_ptr,query_len);
j["starttime_timestamp_us"] = start_time;
{
time_t timer=start_time/1000/1000;
struct tm* tm_info;
tm_info = localtime(&timer);
char buffer1[64];
char buffer2[64];
strftime(buffer1, 32, "%Y-%m-%d %H:%M:%S", tm_info);
sprintf(buffer2,"%s.%06u", buffer1, (unsigned)(start_time%1000000));
j["starttime"] = buffer2;
}
j["endtime_timestamp_us"] = end_time;
{
time_t timer=end_time/1000/1000;
struct tm* tm_info;
tm_info = localtime(&timer);
char buffer1[64];
char buffer2[64];
strftime(buffer1, 32, "%Y-%m-%d %H:%M:%S", tm_info);
sprintf(buffer2,"%s.%06u", buffer1, (unsigned)(end_time%1000000));
j["endtime"] = buffer2;
}
j["duration_us"] = end_time-start_time;
char digest_hex[20];
sprintf(digest_hex,"0x%016llX", (long long unsigned int)query_digest);
j["digest"] = digest_hex;
// for performance reason, we are moving the write lock
// right before the write to disk
GloMyLogger->wrlock();
*f << j.dump(-1, ' ', false, json::error_handler_t::replace) << std::endl;
return total_bytes; // always 0
}
extern Query_Processor *GloQPro;
MySQL_Logger::MySQL_Logger() {
events.enabled=false;
events.base_filename=NULL;
events.datadir=NULL;
events.base_filename=strdup((char *)"");
audit.enabled=false;
audit.base_filename=NULL;
audit.datadir=NULL;
audit.base_filename=strdup((char *)"");
#ifdef PROXYSQL_LOGGER_PTHREAD_MUTEX
pthread_mutex_init(&wmutex,NULL);
#else
spinlock_rwlock_init(&rwlock);
#endif
events.logfile=NULL;
events.log_file_id=0;
events.max_log_file_size=100*1024*1024;
audit.logfile=NULL;
audit.log_file_id=0;
audit.max_log_file_size=100*1024*1024;
};
MySQL_Logger::~MySQL_Logger() {
if (events.datadir) {
free(events.datadir);
}
free(events.base_filename);
if (audit.datadir) {
free(audit.datadir);
}
free(audit.base_filename);
};
void MySQL_Logger::wrlock() {
#ifdef PROXYSQL_LOGGER_PTHREAD_MUTEX
pthread_mutex_lock(&wmutex);
#else
spin_wrlock(&rwlock);
#endif
};
void MySQL_Logger::wrunlock() {
#ifdef PROXYSQL_LOGGER_PTHREAD_MUTEX
pthread_mutex_unlock(&wmutex);
#else
spin_wrunlock(&rwlock);
#endif
};
void MySQL_Logger::flush_log() {
if (audit.enabled==false && events.enabled==false) return;
wrlock();
events_flush_log_unlocked();
audit_flush_log_unlocked();
wrunlock();
}
void MySQL_Logger::events_close_log_unlocked() {
if (events.logfile) {
events.logfile->flush();
events.logfile->close();
delete events.logfile;
events.logfile=NULL;
}
}
void MySQL_Logger::audit_close_log_unlocked() {
if (audit.logfile) {
audit.logfile->flush();
audit.logfile->close();
delete audit.logfile;
audit.logfile=NULL;
}
}
void MySQL_Logger::events_flush_log_unlocked() {
if (events.enabled==false) return;
events_close_log_unlocked();
events_open_log_unlocked();
}
void MySQL_Logger::audit_flush_log_unlocked() {
if (audit.enabled==false) return;
audit_close_log_unlocked();
audit_open_log_unlocked();
}
void MySQL_Logger::events_open_log_unlocked() {
events.log_file_id=events_find_next_id();
if (events.log_file_id!=0) {
events.log_file_id=events_find_next_id()+1;
} else {
events.log_file_id++;
}
char *filen=NULL;
if (events.base_filename[0]=='/') { // absolute path
filen=(char *)malloc(strlen(events.base_filename)+10);
sprintf(filen,"%s.%08d",events.base_filename,events.log_file_id);
} else { // relative path
filen=(char *)malloc(strlen(events.datadir)+strlen(events.base_filename)+10);
sprintf(filen,"%s/%s.%08d",events.datadir,events.base_filename,events.log_file_id);
}
events.logfile=new std::fstream();
events.logfile->exceptions ( std::ofstream::failbit | std::ofstream::badbit );
try {
events.logfile->open(filen , std::ios::out | std::ios::binary);
proxy_info("Starting new mysql event log file %s\n", filen);
}
catch (std::ofstream::failure e) {
proxy_error("Error creating new mysql event log file %s\n", filen);
delete events.logfile;
events.logfile=NULL;
}
free(filen);
};
void MySQL_Logger::audit_open_log_unlocked() {
audit.log_file_id=audit_find_next_id();
if (audit.log_file_id!=0) {
audit.log_file_id=audit_find_next_id()+1;
} else {
audit.log_file_id++;
}
char *filen=NULL;
if (audit.base_filename[0]=='/') { // absolute path
filen=(char *)malloc(strlen(audit.base_filename)+10);
sprintf(filen,"%s.%08d",audit.base_filename,audit.log_file_id);
} else { // relative path
filen=(char *)malloc(strlen(audit.datadir)+strlen(audit.base_filename)+10);
sprintf(filen,"%s/%s.%08d",audit.datadir,audit.base_filename,audit.log_file_id);
}
audit.logfile=new std::fstream();
audit.logfile->exceptions ( std::ofstream::failbit | std::ofstream::badbit );
try {
audit.logfile->open(filen , std::ios::out | std::ios::binary);
proxy_info("Starting new audit log file %s\n", filen);
}
catch (std::ofstream::failure e) {
proxy_error("Error creating new audit log file %s\n", filen);
delete audit.logfile;
audit.logfile=NULL;
}
free(filen);
};
void MySQL_Logger::events_set_base_filename() {
// if filename is the same, return
wrlock();
events.max_log_file_size=mysql_thread___eventslog_filesize;
if (strcmp(events.base_filename,mysql_thread___eventslog_filename)==0) {
wrunlock();
return;
}
// close current log
events_close_log_unlocked();
// set file id to 0 , so that find_next_id() will be called
events.log_file_id=0;
free(events.base_filename);
events.base_filename=strdup(mysql_thread___eventslog_filename);
if (strlen(events.base_filename)) {
events.enabled=true;
events_open_log_unlocked();
} else {
events.enabled=false;
}
wrunlock();
}
void MySQL_Logger::events_set_datadir(char *s) {
events.datadir=strdup(s);
flush_log();
};
void MySQL_Logger::audit_set_base_filename() {
// if filename is the same, return
wrlock();
audit.max_log_file_size=mysql_thread___auditlog_filesize;
if (strcmp(audit.base_filename,mysql_thread___auditlog_filename)==0) {
wrunlock();
return;
}
// close current log
audit_close_log_unlocked();
// set file id to 0 , so that find_next_id() will be called
audit.log_file_id=0;
free(audit.base_filename);
audit.base_filename=strdup(mysql_thread___auditlog_filename);
if (strlen(audit.base_filename)) {
audit.enabled=true;
audit_open_log_unlocked();
} else {
audit.enabled=false;
}
wrunlock();
}
void MySQL_Logger::audit_set_datadir(char *s) {
audit.datadir=strdup(s);
flush_log();
};
void MySQL_Logger::log_request(MySQL_Session *sess, MySQL_Data_Stream *myds) {
if (events.enabled==false) return;
if (events.logfile==NULL) return;
MySQL_Connection_userinfo *ui=sess->client_myds->myconn->userinfo;
uint64_t curtime_real=realtime_time();
uint64_t curtime_mono=sess->thread->curtime;
int cl=0;
char *ca=(char *)""; // default
if (sess->client_myds->addr.addr) {
ca=sess->client_myds->addr.addr;
}
cl+=strlen(ca);
if (cl && sess->client_myds->addr.port) {
ca=(char *)malloc(cl+8);
sprintf(ca,"%s:%d",sess->client_myds->addr.addr,sess->client_myds->addr.port);
}
cl=strlen(ca);
enum log_event_type let = PROXYSQL_COM_QUERY; // default
switch (sess->status) {
case PROCESSING_STMT_EXECUTE:
let = PROXYSQL_COM_STMT_EXECUTE;
break;
case PROCESSING_STMT_PREPARE:
let = PROXYSQL_COM_STMT_PREPARE;
break;
case WAITING_CLIENT_DATA:
{
unsigned char c=*((unsigned char *)sess->pktH->ptr+sizeof(mysql_hdr));
switch ((enum_mysql_command)c) {
case _MYSQL_COM_STMT_PREPARE:
// proxysql is responding to COM_STMT_PREPARE without
// preparing on any backend
let = PROXYSQL_COM_STMT_PREPARE;
break;
default:
break;
}
}
break;
default:
break;
}
MySQL_Event me(let,
sess->thread_session_id,ui->username,ui->schemaname,
sess->CurrentQuery.start_time + curtime_real - curtime_mono,
sess->CurrentQuery.end_time + curtime_real - curtime_mono,
GloQPro->get_digest(&sess->CurrentQuery.QueryParserArgs),
ca, cl
);
char *c = NULL;
int ql = 0;
switch (sess->status) {
case PROCESSING_STMT_EXECUTE:
c = (char *)sess->CurrentQuery.stmt_info->query;
ql = sess->CurrentQuery.stmt_info->query_length;
break;
case PROCESSING_STMT_PREPARE:
default:
c = (char *)sess->CurrentQuery.QueryPointer;
ql = sess->CurrentQuery.QueryLength;
break;
}
if (c) {
me.set_query(c,ql);
} else {
me.set_query("",0);
}
if (sess->CurrentQuery.have_affected_rows) {
me.set_affected_rows(sess->CurrentQuery.affected_rows);
}
me.set_rows_sent(sess->CurrentQuery.rows_sent);
int sl=0;
char *sa=(char *)""; // default
if (myds) {
if (myds->myconn) {
sa=myds->myconn->parent->address;
}
}
sl+=strlen(sa);
if (sl && myds->myconn->parent->port) {
sa=(char *)malloc(sl+8);
sprintf(sa,"%s:%d", myds->myconn->parent->address, myds->myconn->parent->port);
}
sl=strlen(sa);
if (sl) {
int hid=-1;
hid=myds->myconn->parent->myhgc->hid;
me.set_server(hid,sa,sl);
}
// for performance reason, we are moving the write lock
// right before the write to disk
//wrlock();
me.write(events.logfile, sess);
unsigned long curpos=events.logfile->tellp();
if (curpos > events.max_log_file_size) {
events_flush_log_unlocked();
}
wrunlock();
if (cl && sess->client_myds->addr.port) {
free(ca);
}
if (sl && myds->myconn->parent->port) {
free(sa);
}
}
void MySQL_Logger::log_audit_entry(log_event_type _et, MySQL_Session *sess, MySQL_Data_Stream *myds, char *xi) {
if (audit.enabled==false) return;
if (audit.logfile==NULL) return;
if (sess == NULL) return;
if (sess->client_myds == NULL) return;
MySQL_Connection_userinfo *ui= NULL;
if (sess) {
if (sess->client_myds) {
if (sess->client_myds->myconn) {
ui = sess->client_myds->myconn->userinfo;
}
}
}
if (sess) {
// to reduce complexing in the calling function, we do some changes here
switch (_et) {
case PROXYSQL_MYSQL_AUTH_OK:
switch (sess->session_type) {
case PROXYSQL_SESSION_ADMIN:
case PROXYSQL_SESSION_STATS:
_et = PROXYSQL_ADMIN_AUTH_OK;
break;
case PROXYSQL_SESSION_SQLITE:
_et = PROXYSQL_SQLITE_AUTH_OK;
default:
break;
}
break;
case PROXYSQL_MYSQL_AUTH_ERR:
switch (sess->session_type) {
case PROXYSQL_SESSION_ADMIN:
case PROXYSQL_SESSION_STATS:
_et = PROXYSQL_ADMIN_AUTH_ERR;
break;
case PROXYSQL_SESSION_SQLITE:
_et = PROXYSQL_SQLITE_AUTH_ERR;
default:
break;
}
break;
case PROXYSQL_MYSQL_AUTH_QUIT:
switch (sess->session_type) {
case PROXYSQL_SESSION_ADMIN:
case PROXYSQL_SESSION_STATS:
_et = PROXYSQL_ADMIN_AUTH_QUIT;
break;
case PROXYSQL_SESSION_SQLITE:
_et = PROXYSQL_SQLITE_AUTH_QUIT;
default:
break;
}
break;
case PROXYSQL_MYSQL_AUTH_CLOSE:
switch (sess->session_type) {
case PROXYSQL_SESSION_ADMIN:
case PROXYSQL_SESSION_STATS:
_et = PROXYSQL_ADMIN_AUTH_CLOSE;
break;
case PROXYSQL_SESSION_SQLITE:
_et = PROXYSQL_SQLITE_AUTH_CLOSE;
default:
break;
}
break;
default:
break;
}
}
uint64_t curtime_real=realtime_time();
uint64_t curtime_mono=sess->thread->curtime;
int cl=0;
char *ca=(char *)""; // default
if (sess->client_myds->addr.addr) {
ca=sess->client_myds->addr.addr;
}
cl+=strlen(ca);
if (cl && sess->client_myds->addr.port) {
ca=(char *)malloc(cl+8);
sprintf(ca,"%s:%d",sess->client_myds->addr.addr,sess->client_myds->addr.port);
}
cl=strlen(ca);
char *un = (char *)"";
char *sn = (char *)"";
if (ui) {
if (ui->username) {
un = ui->username;
}
if (ui->schemaname) {
sn = ui->schemaname;
}
}
MySQL_Event me(_et, sess->thread_session_id,
un, sn,
curtime_real, 0, 0,
ca, cl
);
/*
char *c=(char *)sess->CurrentQuery.QueryPointer;
if (c) {
me.set_query(c,sess->CurrentQuery.QueryLength);
} else {
me.set_query("",0);
}
*/
int sl=0;
char *sa=(char *)""; // default
if (myds) {
if (myds->myconn) {
sa=myds->myconn->parent->address;
}
}
sl+=strlen(sa);
if (sl && myds->myconn->parent->port) {
sa=(char *)malloc(sl+8);
sprintf(sa,"%s:%d", myds->myconn->parent->address, myds->myconn->parent->port);
}
sl=strlen(sa);
if (sl) {
int hid=-1;
hid=myds->myconn->parent->myhgc->hid;
// me.set_server(hid,sa,sl);
}
if (xi) {
me.set_extra_info(xi);
}
// for performance reason, we are moving the write lock
// right before the write to disk
//wrlock();
me.write(audit.logfile, sess);
unsigned long curpos=audit.logfile->tellp();
if (curpos > audit.max_log_file_size) {
audit_flush_log_unlocked();
}
wrunlock();
if (cl && sess->client_myds->addr.port) {
free(ca);
}
if (sl && myds->myconn->parent->port) {
free(sa);
}
}
void MySQL_Logger::flush() {
wrlock();
if (events.logfile) {
events.logfile->flush();
}
if (audit.logfile) {
audit.logfile->flush();
}
wrunlock();
}
unsigned int MySQL_Logger::events_find_next_id() {
int maxidx=0;
DIR *dir;
struct dirent *ent;
char *eval_filename = NULL;
char *eval_dirname = NULL;
char *eval_pathname = NULL;
assert(events.base_filename);
if (events.base_filename[0] == '/') {
eval_pathname = strdup(events.base_filename);
eval_filename = basename(eval_pathname);
eval_dirname = dirname(eval_pathname);
} else {
assert(events.datadir);
eval_filename = strdup(events.base_filename);
eval_dirname = strdup(events.datadir);
}
size_t efl=strlen(eval_filename);
if ((dir = opendir(eval_dirname)) != NULL) {
while ((ent = readdir (dir)) != NULL) {
if (strlen(ent->d_name)==efl+9) {
if (strncmp(ent->d_name,eval_filename,efl)==0) {
if (ent->d_name[efl]=='.') {
int idx=atoi(ent->d_name+efl+1);
if (idx>maxidx) maxidx=idx;
}
}
}
}
closedir (dir);
if (events.base_filename[0] != '/') {
free(eval_dirname);
free(eval_filename);
}
if (eval_pathname) {
free(eval_pathname);
}
return maxidx;
} else {
/* could not open directory */
proxy_error("Unable to open datadir: %s\n", eval_dirname);
exit(EXIT_FAILURE);
}
return 0;
}
unsigned int MySQL_Logger::audit_find_next_id() {
int maxidx=0;
DIR *dir;
struct dirent *ent;
char *eval_filename = NULL;
char *eval_dirname = NULL;
char *eval_pathname = NULL;
assert(audit.base_filename);
if (audit.base_filename[0] == '/') {
eval_pathname = strdup(audit.base_filename);
eval_filename = basename(eval_pathname);
eval_dirname = dirname(eval_pathname);
} else {
assert(audit.datadir);
eval_filename = strdup(audit.base_filename);
eval_dirname = strdup(audit.datadir);
}
size_t efl=strlen(eval_filename);
if ((dir = opendir(eval_dirname)) != NULL) {
while ((ent = readdir (dir)) != NULL) {
if (strlen(ent->d_name)==efl+9) {
if (strncmp(ent->d_name,eval_filename,efl)==0) {
if (ent->d_name[efl]=='.') {
int idx=atoi(ent->d_name+efl+1);
if (idx>maxidx) maxidx=idx;
}
}
}
}
closedir (dir);
if (audit.base_filename[0] != '/') {
free(eval_dirname);
free(eval_filename);
}
if (eval_pathname) {
free(eval_pathname);
}
return maxidx;
} else {
/* could not open directory */
proxy_error("Unable to open datadir: %s\n", eval_dirname);
exit(EXIT_FAILURE);
}
return 0;
}
void MySQL_Logger::print_version() {
fprintf(stderr,"Standard ProxySQL MySQL Logger rev. %s -- %s -- %s\n", PROXYSQL_MYSQL_LOGGER_VERSION, __FILE__, __TIMESTAMP__);
};