22
22
#include <drizzled/gettext.h>
23
23
#include <drizzled/session.h>
25
/* todo, make this dynamic as needed */
26
#define MAX_MSG_LEN (32*1024)
25
/* TODO make this dynamic as needed */
26
static const int MAX_MSG_LEN= 32*1024;
28
static char* logging_query_filename= NULL;
29
static bool logging_query_enable= true;
30
static ulong logging_query_threshold_slow= 0;
31
static ulong logging_query_threshold_big_resultset= 0;
32
static ulong logging_query_threshold_big_examined= 0;
28
static bool sysvar_logging_query_enable= false;
29
static char* sysvar_logging_query_filename= NULL;
30
/* TODO fix these to not be unsigned long one we have sensible sys_var system */
31
static unsigned long sysvar_logging_query_threshold_slow= 0;
32
static unsigned long sysvar_logging_query_threshold_big_resultset= 0;
33
static unsigned long sysvar_logging_query_threshold_big_examined= 0;
59
60
and all the ASCII unprintable characters
60
61
as long as we pass the high-bit bytes unchanged
61
62
this is safe to do to a UTF8 string
62
we have to be careful about overrunning the targetbuffer
63
or else a very long query can overwrite memory
63
we dont allow overrunning the targetbuffer
64
to avoid having a very long query overwrite memory
65
66
TODO consider remapping the unprintables instead to "Printable
66
67
Representation", the Unicode characters from the area U+2400 to
73
74
static unsigned char *quotify (const unsigned char *src, size_t srclen,
74
75
unsigned char *dst, size_t dstlen)
76
static char hexit[]= { '0', '1', '2', '3', '4', '5', '6', '7',
77
static const char hexit[]= { '0', '1', '2', '3', '4', '5', '6', '7',
77
78
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
78
size_t dst_ndx; /* index down the dst */
79
size_t src_ndx; /* index down the src */
79
size_t dst_ndx; /* ndx down the dst */
80
size_t src_ndx; /* ndx down the src */
82
83
assert(dstlen > 0);
84
for (dst_ndx=0,src_ndx=0; src_ndx<srclen; src_ndx++)
85
for (dst_ndx= 0,src_ndx= 0; src_ndx < srclen; src_ndx++)
87
/* Worst case, need 5 dst bytes for the next src byte.
88
/* Worst case, need 5 dst bytes for the next src byte.
88
89
backslash x hexit hexit null
89
90
so if not enough room, just terminate the string and return
91
92
if ((dstlen - dst_ndx) < 5)
93
dst[dst_ndx]= (unsigned char) 0x00;
94
dst[dst_ndx]= (unsigned char)0x00;
186
/* Yes, we know that checking logging_query_enable,
187
logging_query_threshold_big_resultset, and
188
logging_query_threshold_big_examined is not threadsafe, because some
189
other thread might change these sysvars. But we don't care. We
190
might start logging a little late as it spreads to other threads.
187
/* Yes, we know that checking sysvar_logging_query_enable,
188
sysvar_logging_query_threshold_big_resultset, and
189
sysvar_logging_query_threshold_big_examined is not threadsafe,
190
because some other thread might change these sysvars. But we
191
don't care. We might start logging a little late as it spreads
192
to other threads. Big deal. */
193
194
// return if not enabled or query was too fast or resultset was too small
194
if (logging_query_enable == false)
196
if (session->sent_row_count < logging_query_threshold_big_resultset)
198
if (session->examined_row_count < logging_query_threshold_big_examined)
195
if (sysvar_logging_query_enable == false)
197
if (session->sent_row_count < sysvar_logging_query_threshold_big_resultset)
199
if (session->examined_row_count < sysvar_logging_query_threshold_big_examined)
201
202
// logging this is far too verbose
212
213
uint64_t t_mark= get_microtime();
214
if ((t_mark - session->start_utime) < (logging_query_threshold_slow)) return false;
215
if ((t_mark - session->start_utime) < (sysvar_logging_query_threshold_slow))
216
218
// buffer to quotify the query
217
219
unsigned char qs[255];
221
// to avoid trying to printf %s something that is potentially NULL
222
const char *dbs= (session->db) ? session->db : "";
225
dbl= session->db_length;
220
228
snprintf(msgbuf, MAX_MSG_LEN,
221
"%lld,%ld,%ld,\"%.*s\",\"%s\",\"%.*s\",%lld,%lld,%lld,%ld,%ld\n",
222
(unsigned long long) t_mark,
223
(unsigned long) session->thread_id,
224
(unsigned long) session->query_id,
229
"%"PRIu64",%"PRIu64",%"PRIu64",\"%.*s\",\"%s\",\"%.*s\","
230
"%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64"\n",
225
234
// dont need to quote the db name, always CSV safe
226
session->db_length, session->db,
227
236
// do need to quote the query
228
(char *) quotify((unsigned char *) session->query, session->query_length,
237
quotify((unsigned char *)session->query,
238
session->query_length, qs, sizeof(qs)),
230
239
// command_name is defined in drizzled/sql_parse.cc
231
240
// dont need to quote the command name, always CSV safe
232
(int) command_name[session->command].length,
241
(int)command_name[session->command].length,
233
242
command_name[session->command].str,
234
243
// counters are at end, to make it easier to add more
235
(unsigned long long) (t_mark - session->connect_utime),
236
(unsigned long long) (t_mark - session->start_utime),
237
(unsigned long long) (t_mark - session->utime_after_lock),
238
(unsigned long) session->sent_row_count,
239
(unsigned long) session->examined_row_count);
244
(t_mark - session->connect_utime),
245
(t_mark - session->start_utime),
246
(t_mark - session->utime_after_lock),
247
session->sent_row_count,
248
session->examined_row_count);
242
251
// a single write has a kernel thread lock, thus no need mutex guard this
311
static DRIZZLE_SYSVAR_BOOL(
313
sysvar_logging_query_enable,
315
N_("Enable logging to CSV file"),
316
NULL, /* check func */
317
NULL, /* update func */
318
false /* default */);
302
320
static DRIZZLE_SYSVAR_STR(
304
logging_query_filename,
322
sysvar_logging_query_filename,
305
323
PLUGIN_VAR_READONLY,
306
324
N_("File to log to"),
307
325
NULL, /* check func */
308
326
NULL, /* update func*/
309
327
NULL /* default */);
311
static DRIZZLE_SYSVAR_BOOL(
313
logging_query_enable,
315
N_("Enable logging"),
316
NULL, /* check func */
317
NULL, /* update func */
320
329
static DRIZZLE_SYSVAR_ULONG(
322
logging_query_threshold_slow,
331
sysvar_logging_query_threshold_slow,
323
332
PLUGIN_VAR_OPCMDARG,
324
333
N_("Threshold for logging slow queries, in microseconds"),
325
334
NULL, /* check func */
326
335
NULL, /* update func */
338
UINT32_MAX, /* max */
332
341
static DRIZZLE_SYSVAR_ULONG(
333
342
threshold_big_resultset,
334
logging_query_threshold_big_resultset,
343
sysvar_logging_query_threshold_big_resultset,
335
344
PLUGIN_VAR_OPCMDARG,
336
345
N_("Threshold for logging big queries, for rows returned"),
337
346
NULL, /* check func */
338
347
NULL, /* update func */
350
UINT32_MAX, /* max */
344
353
static DRIZZLE_SYSVAR_ULONG(
345
354
threshold_big_examined,
346
logging_query_threshold_big_examined,
355
sysvar_logging_query_threshold_big_examined,
347
356
PLUGIN_VAR_OPCMDARG,
348
357
N_("Threshold for logging big queries, for rows examined"),
349
358
NULL, /* check func */
350
359
NULL, /* update func */
362
UINT32_MAX, /* max */
356
365
static struct st_mysql_sys_var* logging_query_system_variables[]= {
366
DRIZZLE_SYSVAR(enable),
357
367
DRIZZLE_SYSVAR(filename),
358
DRIZZLE_SYSVAR(enable),
359
368
DRIZZLE_SYSVAR(threshold_slow),
360
369
DRIZZLE_SYSVAR(threshold_big_resultset),
361
370
DRIZZLE_SYSVAR(threshold_big_examined),