41
41
#define ESCAPE_CHAR '\\'
42
42
#define SEPARATOR_CHAR ','
44
namespace drizzle_plugin
44
47
static bool sysvar_logging_query_enable= false;
45
static char* sysvar_logging_query_filename= NULL;
46
static char* sysvar_logging_query_pcre= NULL;
47
48
/* TODO fix these to not be unsigned long once we have sensible sys_var system */
48
static unsigned long sysvar_logging_query_threshold_slow= 0;
49
static unsigned long sysvar_logging_query_threshold_big_resultset= 0;
50
static unsigned long sysvar_logging_query_threshold_big_examined= 0;
49
static uint32_constraint sysvar_logging_query_threshold_slow;
50
static uint32_constraint sysvar_logging_query_threshold_big_resultset;
51
static uint32_constraint sysvar_logging_query_threshold_big_examined;
52
53
/* quote a string to be safe to include in a CSV line
53
54
that means backslash quoting all commas, doublequotes, backslashes,
155
: drizzled::plugin::Logging("Logging_query"),
156
fd(-1), re(NULL), pe(NULL),
157
formatter("%1%,%2%,%3%,\"%4%\",\"%5%\",\"%6%\",%7%,%8%,"
158
"%9%,%10%,%11%,%12%,%13%,%14%,\"%15%\"\n")
157
Logging_query(const std::string &filename,
158
const std::string &query_pcre) :
159
drizzled::plugin::Logging("Logging_query"),
161
_query_pcre(query_pcre),
162
fd(-1), re(NULL), pe(NULL),
163
formatter("%1%,%2%,%3%,\"%4%\",\"%5%\",\"%6%\",%7%,%8%,"
164
"%9%,%10%,%11%,%12%,%13%,%14%,\"%15%\"\n")
161
167
/* if there is no destination filename, dont bother doing anything */
162
if (sysvar_logging_query_filename == NULL)
168
if (_filename.empty())
165
fd= open(sysvar_logging_query_filename,
171
fd= open(_filename.c_str(),
166
172
O_WRONLY | O_APPEND | O_CREAT,
167
173
S_IRUSR|S_IWUSR);
170
176
char errmsg[STRERROR_MAX];
171
177
strerror_r(errno, errmsg, sizeof(errmsg));
172
178
errmsg_printf(ERRMSG_LVL_ERROR, _("fail open() fn=%s er=%s\n"),
173
sysvar_logging_query_filename,
178
if (sysvar_logging_query_pcre != NULL)
184
if (not _query_pcre.empty())
180
186
const char *this_pcre_error;
181
187
int this_pcre_erroffset;
182
re= pcre_compile(sysvar_logging_query_pcre, 0, &this_pcre_error,
188
re= pcre_compile(_query_pcre.c_str(), 0, &this_pcre_error,
183
189
&this_pcre_erroffset, NULL);
184
190
pe= pcre_study(re, 0, &this_pcre_error);
185
191
/* TODO emit error messages if there is a problem */
223
229
// return if not enabled or query was too fast or resultset was too small
224
230
if (sysvar_logging_query_enable == false)
226
if (session->sent_row_count < sysvar_logging_query_threshold_big_resultset)
232
if (session->sent_row_count < sysvar_logging_query_threshold_big_resultset.get())
228
if (session->examined_row_count < sysvar_logging_query_threshold_big_examined)
234
if (session->examined_row_count < sysvar_logging_query_threshold_big_examined.get())
231
237
/* TODO, the session object should have a "utime command completed"
289
static Logging_query *handler= NULL;
291
296
static int logging_query_plugin_init(drizzled::module::Context &context)
294
299
const module::option_map &vm= context.getOptions();
295
if (vm.count("threshold-slow"))
297
if (sysvar_logging_query_threshold_slow > UINT32_MAX)
299
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for threshold-slow"));
304
if (vm.count("threshold-big-resultset"))
306
if (sysvar_logging_query_threshold_big_resultset > UINT32_MAX)
308
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for threshold-big-resultset"));
313
if (vm.count("threshold-big-examined"))
315
if (sysvar_logging_query_threshold_big_examined > UINT32_MAX)
317
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for threshold-big-examined"));
321
handler= new Logging_query();
322
context.add(handler);
301
if (vm.count("filename") > 0)
303
context.add(new Logging_query(vm["filename"].as<string>(),
304
vm["pcre"].as<string>()));
305
context.registerVariable(new sys_var_bool_ptr("enable", &sysvar_logging_query_enable));
306
context.registerVariable(new sys_var_const_string_val("filename", vm["filename"].as<string>()));
307
context.registerVariable(new sys_var_const_string_val("pcre", vm["pcre"].as<string>()));
308
context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_slow", sysvar_logging_query_threshold_slow));
309
context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_big_resultset", sysvar_logging_query_threshold_big_resultset));
310
context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_big_examined", sysvar_logging_query_threshold_big_examined));
329
318
context("enable",
330
319
po::value<bool>(&sysvar_logging_query_enable)->default_value(false)->zero_tokens(),
331
320
N_("Enable logging to CSV file"));
323
N_("File to log to"));
325
po::value<string>()->default_value(""),
326
N_("PCRE to match the query against"));
332
327
context("threshold-slow",
333
po::value<unsigned long>(&sysvar_logging_query_threshold_slow)->default_value(0),
328
po::value<uint32_constraint>(&sysvar_logging_query_threshold_slow)->default_value(0),
334
329
N_("Threshold for logging slow queries, in microseconds"));
335
330
context("threshold-big-resultset",
336
po::value<unsigned long>(&sysvar_logging_query_threshold_big_resultset)->default_value(0),
331
po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_resultset)->default_value(0),
337
332
N_("Threshold for logging big queries, for rows returned"));
338
333
context("threshold-big-examined",
339
po::value<unsigned long>(&sysvar_logging_query_threshold_big_examined)->default_value(0),
334
po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_examined)->default_value(0),
340
335
N_("Threshold for logging big queries, for rows examined"));
343
static DRIZZLE_SYSVAR_BOOL(
345
sysvar_logging_query_enable,
347
N_("Enable logging to CSV file"),
348
NULL, /* check func */
349
NULL, /* update func */
350
false /* default */);
352
static DRIZZLE_SYSVAR_STR(
354
sysvar_logging_query_filename,
356
N_("File to log to"),
357
NULL, /* check func */
358
NULL, /* update func*/
361
static DRIZZLE_SYSVAR_STR(
363
sysvar_logging_query_pcre,
365
N_("PCRE to match the query against"),
366
NULL, /* check func */
367
NULL, /* update func*/
370
static DRIZZLE_SYSVAR_ULONG(
372
sysvar_logging_query_threshold_slow,
374
N_("Threshold for logging slow queries, in microseconds"),
375
NULL, /* check func */
376
NULL, /* update func */
379
UINT32_MAX, /* max */
382
static DRIZZLE_SYSVAR_ULONG(
383
threshold_big_resultset,
384
sysvar_logging_query_threshold_big_resultset,
386
N_("Threshold for logging big queries, for rows returned"),
387
NULL, /* check func */
388
NULL, /* update func */
391
UINT32_MAX, /* max */
394
static DRIZZLE_SYSVAR_ULONG(
395
threshold_big_examined,
396
sysvar_logging_query_threshold_big_examined,
398
N_("Threshold for logging big queries, for rows examined"),
399
NULL, /* check func */
400
NULL, /* update func */
403
UINT32_MAX, /* max */
406
static drizzle_sys_var* logging_query_system_variables[]= {
407
DRIZZLE_SYSVAR(enable),
408
DRIZZLE_SYSVAR(filename),
409
DRIZZLE_SYSVAR(pcre),
410
DRIZZLE_SYSVAR(threshold_slow),
411
DRIZZLE_SYSVAR(threshold_big_resultset),
412
DRIZZLE_SYSVAR(threshold_big_examined),
338
} /* namespace drizzle_plugin */
416
340
DRIZZLE_DECLARE_PLUGIN
421
345
"Mark Atwood <mark@fallenpegasus.com>",
422
346
N_("Log queries to a CSV file"),
423
347
PLUGIN_LICENSE_GPL,
424
logging_query_plugin_init,
425
logging_query_system_variables,
348
drizzle_plugin::logging_query_plugin_init,
350
drizzle_plugin::init_options
428
352
DRIZZLE_DECLARE_PLUGIN_END;