~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/logging_query/logging_query.cc

  • Committer: Brian Aker
  • Date: 2010-07-28 23:07:42 UTC
  • mto: This revision was merged to the branch mainline in revision 1671.
  • Revision ID: brian@gaz-20100728230742-idji8pjd3trphd1a
Fix up a few additional cases around case insensitive usage for
unordered_map. This also places the code in util/string.h behind an
additional namespace of "util"

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008, 2009 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008,2009 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#include <config.h>
 
20
#include "config.h"
21
21
#include <drizzled/plugin/logging.h>
22
22
#include <drizzled/gettext.h>
23
23
#include <drizzled/session.h>
32
32
#include <boost/program_options.hpp>
33
33
#include <drizzled/module/option_map.h>
34
34
#include <cstdio>
35
 
#include <cerrno>
36
35
 
37
36
namespace po= boost::program_options;
38
37
using namespace drizzled;
41
40
#define ESCAPE_CHAR      '\\'
42
41
#define SEPARATOR_CHAR   ','
43
42
 
44
 
namespace drizzle_plugin
45
 
{
46
 
 
47
43
static bool sysvar_logging_query_enable= false;
 
44
static char* sysvar_logging_query_filename= NULL;
 
45
static char* sysvar_logging_query_pcre= NULL;
48
46
/* TODO fix these to not be unsigned long once we have sensible sys_var system */
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;
 
47
static unsigned long sysvar_logging_query_threshold_slow= 0;
 
48
static unsigned long sysvar_logging_query_threshold_big_resultset= 0;
 
49
static unsigned long sysvar_logging_query_threshold_big_examined= 0;
 
50
 
 
51
/* stolen from mysys/my_getsystime
 
52
   until the Session has a good utime "now" we can use
 
53
   will have to use this instead */
 
54
 
 
55
static uint64_t get_microtime()
 
56
{
 
57
#if defined(HAVE_GETHRTIME)
 
58
  return gethrtime()/1000;
 
59
#else
 
60
  uint64_t newtime;
 
61
  struct timeval t;
 
62
  /*
 
63
    The following loop is here because gettimeofday may fail on some systems
 
64
  */
 
65
  while (gettimeofday(&t, NULL) != 0) {}
 
66
  newtime= (uint64_t)t.tv_sec * 1000000 + t.tv_usec;
 
67
  return newtime;
 
68
#endif  /* defined(HAVE_GETHRTIME) */
 
69
}
52
70
 
53
71
/* quote a string to be safe to include in a CSV line
54
72
   that means backslash quoting all commas, doublequotes, backslashes,
143
161
 
144
162
class Logging_query: public drizzled::plugin::Logging
145
163
{
146
 
  const std::string _filename;
147
 
  const std::string _query_pcre;
148
164
  int fd;
149
165
  pcre *re;
150
166
  pcre_extra *pe;
154
170
 
155
171
public:
156
172
 
157
 
  Logging_query(const std::string &filename,
158
 
                const std::string &query_pcre) :
159
 
    drizzled::plugin::Logging("Logging_query"),
160
 
    _filename(filename),
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")
 
173
  Logging_query()
 
174
    : drizzled::plugin::Logging("Logging_query"),
 
175
      fd(-1), re(NULL), pe(NULL),
 
176
      formatter("%1%,%2%,%3%,\"%4%\",\"%5%\",\"%6%\",%7%,%8%,"
 
177
                "%9%,%10%,%11%,%12%,%13%,%14%,\"%15%\"\n")
165
178
  {
166
179
 
167
180
    /* if there is no destination filename, dont bother doing anything */
168
 
    if (_filename.empty())
 
181
    if (sysvar_logging_query_filename == NULL)
169
182
      return;
170
183
 
171
 
    fd= open(_filename.c_str(),
 
184
    fd= open(sysvar_logging_query_filename,
172
185
             O_WRONLY | O_APPEND | O_CREAT,
173
186
             S_IRUSR|S_IWUSR);
174
 
 
175
187
    if (fd < 0)
176
188
    {
177
 
      sql_perror( _("fail open()"), _filename);
 
189
      errmsg_printf(ERRMSG_LVL_ERROR, _("fail open() fn=%s er=%s\n"),
 
190
                    sysvar_logging_query_filename,
 
191
                    strerror(errno));
178
192
      return;
179
193
    }
180
194
 
181
 
    if (not _query_pcre.empty())
 
195
    if (sysvar_logging_query_pcre != NULL)
182
196
    {
183
197
      const char *this_pcre_error;
184
198
      int this_pcre_erroffset;
185
 
      re= pcre_compile(_query_pcre.c_str(), 0, &this_pcre_error,
 
199
      re= pcre_compile(sysvar_logging_query_pcre, 0, &this_pcre_error,
186
200
                       &this_pcre_erroffset, NULL);
187
201
      pe= pcre_study(re, 0, &this_pcre_error);
188
202
      /* TODO emit error messages if there is a problem */
226
240
    // return if not enabled or query was too fast or resultset was too small
227
241
    if (sysvar_logging_query_enable == false)
228
242
      return false;
229
 
    if (session->sent_row_count < sysvar_logging_query_threshold_big_resultset.get())
230
 
      return false;
231
 
    if (session->examined_row_count < sysvar_logging_query_threshold_big_examined.get())
232
 
      return false;
233
 
 
234
 
    /*
235
 
      TODO, the session object should have a "utime command completed"
236
 
      inside itself, so be more accurate, and so this doesnt have to
237
 
      keep calling current_utime, which can be slow.
238
 
    */
239
 
    uint64_t t_mark= session->getCurrentTimestamp(false);
240
 
 
241
 
    if (session->getElapsedTime() < (sysvar_logging_query_threshold_slow.get()))
242
 
      return false;
243
 
 
244
 
    Session::QueryString query_string(session->getQueryString());
 
243
    if (session->sent_row_count < sysvar_logging_query_threshold_big_resultset)
 
244
      return false;
 
245
    if (session->examined_row_count < sysvar_logging_query_threshold_big_examined)
 
246
      return false;
 
247
 
 
248
    /* TODO, the session object should have a "utime command completed"
 
249
       inside itself, so be more accurate, and so this doesnt have to
 
250
       keep calling current_utime, which can be slow */
 
251
  
 
252
    uint64_t t_mark= get_microtime();
 
253
  
 
254
    if ((t_mark - session->start_utime) < (sysvar_logging_query_threshold_slow))
 
255
      return false;
 
256
 
245
257
    if (re)
246
258
    {
247
259
      int this_pcre_rc;
248
 
      this_pcre_rc= pcre_exec(re, pe, query_string->c_str(), query_string->length(), 0, 0, NULL, 0);
 
260
      this_pcre_rc= pcre_exec(re, pe, session->query.c_str(), session->query.length(), 0, 0, NULL, 0);
249
261
      if (this_pcre_rc < 0)
250
262
        return false;
251
263
    }
255
267
    
256
268
    // Since quotify() builds the quoted string incrementally, we can
257
269
    // avoid some reallocating if we reserve some space up front.
258
 
    qs.reserve(query_string->length());
 
270
    qs.reserve(session->getQueryLength());
259
271
    
260
 
    quotify(*query_string, qs);
 
272
    quotify(session->getQueryString(), qs);
261
273
    
262
274
    // to avoid trying to printf %s something that is potentially NULL
263
 
    util::string::const_shared_ptr schema(session->schema());
264
 
    const char *dbs= (schema and not schema->empty()) ? schema->c_str() : "";
 
275
    const char *dbs= session->db.empty() ? "" : session->db.c_str();
265
276
 
266
277
    formatter % t_mark
267
278
              % session->thread_id
268
279
              % session->getQueryId()
269
280
              % dbs
270
281
              % qs
271
 
              % getCommandName(session->command)
 
282
              % command_name[session->command].str
272
283
              % (t_mark - session->getConnectMicroseconds())
273
 
              % session->getElapsedTime()
 
284
              % (t_mark - session->start_utime)
274
285
              % (t_mark - session->utime_after_lock)
275
286
              % session->sent_row_count
276
287
              % session->examined_row_count
277
288
              % session->tmp_table
278
289
              % session->total_warn_count
279
290
              % session->getServerId()
280
 
              % getServerHostname();
 
291
              % glob_hostname;
281
292
 
282
293
    string msgbuf= formatter.str();
283
294
 
289
300
  }
290
301
};
291
302
 
 
303
static Logging_query *handler= NULL;
 
304
 
292
305
static int logging_query_plugin_init(drizzled::module::Context &context)
293
306
{
294
307
 
295
308
  const module::option_map &vm= context.getOptions();
296
 
 
297
 
  if (vm.count("filename") > 0)
298
 
  {
299
 
    context.add(new Logging_query(vm["filename"].as<string>(),
300
 
                                  vm["pcre"].as<string>()));
301
 
    context.registerVariable(new sys_var_bool_ptr("enable", &sysvar_logging_query_enable));
302
 
    context.registerVariable(new sys_var_const_string_val("filename", vm["filename"].as<string>()));
303
 
    context.registerVariable(new sys_var_const_string_val("pcre", vm["pcre"].as<string>()));
304
 
    context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_slow", sysvar_logging_query_threshold_slow));
305
 
    context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_big_resultset", sysvar_logging_query_threshold_big_resultset));
306
 
    context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_big_examined", sysvar_logging_query_threshold_big_examined));
307
 
  }
 
309
  if (vm.count("threshold-slow"))
 
310
  {
 
311
    if (sysvar_logging_query_threshold_slow > UINT32_MAX)
 
312
    {
 
313
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for threshold-slow"));
 
314
      exit(-1);
 
315
    }
 
316
  }
 
317
 
 
318
  if (vm.count("threshold-big-resultset"))
 
319
  {
 
320
    if (sysvar_logging_query_threshold_big_resultset > UINT32_MAX)
 
321
    {
 
322
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for threshold-big-resultset"));
 
323
      exit(-1);
 
324
    }
 
325
  }
 
326
 
 
327
  if (vm.count("threshold-big-examined"))
 
328
  {
 
329
    if (sysvar_logging_query_threshold_big_examined > UINT32_MAX)
 
330
    {
 
331
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for threshold-big-examined"));
 
332
      exit(-1);
 
333
    }
 
334
  }
 
335
  handler= new Logging_query();
 
336
  context.add(handler);
308
337
 
309
338
  return 0;
310
339
}
313
342
{
314
343
  context("enable",
315
344
          po::value<bool>(&sysvar_logging_query_enable)->default_value(false)->zero_tokens(),
316
 
          _("Enable logging to CSV file"));
317
 
  context("filename",
318
 
          po::value<string>(),
319
 
          _("File to log to"));
320
 
  context("pcre",
321
 
          po::value<string>()->default_value(""),
322
 
          _("PCRE to match the query against"));
 
345
          N_("Enable logging to CSV file"));
323
346
  context("threshold-slow",
324
 
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_slow)->default_value(0),
325
 
          _("Threshold for logging slow queries, in microseconds"));
 
347
          po::value<unsigned long>(&sysvar_logging_query_threshold_slow)->default_value(0),
 
348
          N_("Threshold for logging slow queries, in microseconds"));
326
349
  context("threshold-big-resultset",
327
 
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_resultset)->default_value(0),
328
 
          _("Threshold for logging big queries, for rows returned"));
 
350
          po::value<unsigned long>(&sysvar_logging_query_threshold_big_resultset)->default_value(0),
 
351
          N_("Threshold for logging big queries, for rows returned"));
329
352
  context("threshold-big-examined",
330
 
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_examined)->default_value(0),
331
 
          _("Threshold for logging big queries, for rows examined"));
 
353
          po::value<unsigned long>(&sysvar_logging_query_threshold_big_examined)->default_value(0),
 
354
          N_("Threshold for logging big queries, for rows examined"));
332
355
}
333
356
 
334
 
} /* namespace drizzle_plugin */
 
357
static DRIZZLE_SYSVAR_BOOL(
 
358
  enable,
 
359
  sysvar_logging_query_enable,
 
360
  PLUGIN_VAR_NOCMDARG,
 
361
  N_("Enable logging to CSV file"),
 
362
  NULL, /* check func */
 
363
  NULL, /* update func */
 
364
  false /* default */);
 
365
 
 
366
static DRIZZLE_SYSVAR_STR(
 
367
  filename,
 
368
  sysvar_logging_query_filename,
 
369
  PLUGIN_VAR_READONLY,
 
370
  N_("File to log to"),
 
371
  NULL, /* check func */
 
372
  NULL, /* update func*/
 
373
  NULL /* default */);
 
374
 
 
375
static DRIZZLE_SYSVAR_STR(
 
376
  pcre,
 
377
  sysvar_logging_query_pcre,
 
378
  PLUGIN_VAR_READONLY,
 
379
  N_("PCRE to match the query against"),
 
380
  NULL, /* check func */
 
381
  NULL, /* update func*/
 
382
  NULL /* default */);
 
383
 
 
384
static DRIZZLE_SYSVAR_ULONG(
 
385
  threshold_slow,
 
386
  sysvar_logging_query_threshold_slow,
 
387
  PLUGIN_VAR_OPCMDARG,
 
388
  N_("Threshold for logging slow queries, in microseconds"),
 
389
  NULL, /* check func */
 
390
  NULL, /* update func */
 
391
  0, /* default */
 
392
  0, /* min */
 
393
  UINT32_MAX, /* max */
 
394
  0 /* blksiz */);
 
395
 
 
396
static DRIZZLE_SYSVAR_ULONG(
 
397
  threshold_big_resultset,
 
398
  sysvar_logging_query_threshold_big_resultset,
 
399
  PLUGIN_VAR_OPCMDARG,
 
400
  N_("Threshold for logging big queries, for rows returned"),
 
401
  NULL, /* check func */
 
402
  NULL, /* update func */
 
403
  0, /* default */
 
404
  0, /* min */
 
405
  UINT32_MAX, /* max */
 
406
  0 /* blksiz */);
 
407
 
 
408
static DRIZZLE_SYSVAR_ULONG(
 
409
  threshold_big_examined,
 
410
  sysvar_logging_query_threshold_big_examined,
 
411
  PLUGIN_VAR_OPCMDARG,
 
412
  N_("Threshold for logging big queries, for rows examined"),
 
413
  NULL, /* check func */
 
414
  NULL, /* update func */
 
415
  0, /* default */
 
416
  0, /* min */
 
417
  UINT32_MAX, /* max */
 
418
  0 /* blksiz */);
 
419
 
 
420
static drizzle_sys_var* logging_query_system_variables[]= {
 
421
  DRIZZLE_SYSVAR(enable),
 
422
  DRIZZLE_SYSVAR(filename),
 
423
  DRIZZLE_SYSVAR(pcre),
 
424
  DRIZZLE_SYSVAR(threshold_slow),
 
425
  DRIZZLE_SYSVAR(threshold_big_resultset),
 
426
  DRIZZLE_SYSVAR(threshold_big_examined),
 
427
  NULL
 
428
};
335
429
 
336
430
DRIZZLE_DECLARE_PLUGIN
337
431
{
341
435
  "Mark Atwood <mark@fallenpegasus.com>",
342
436
  N_("Log queries to a CSV file"),
343
437
  PLUGIN_LICENSE_GPL,
344
 
  drizzle_plugin::logging_query_plugin_init,
345
 
  NULL,
346
 
  drizzle_plugin::init_options
 
438
  logging_query_plugin_init,
 
439
  logging_query_system_variables,
 
440
  init_options
347
441
}
348
442
DRIZZLE_DECLARE_PLUGIN_END;