~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/logging_query/logging_query.cc

  • Committer: Stewart Smith
  • Date: 2009-06-17 06:44:38 UTC
  • mto: This revision was merged to the branch mainline in revision 1094.
  • Revision ID: stewart@flamingspork.com-20090617064438-062owpgtdzgr4lvx
type_float.test for MyISAM as temp only

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#include "config.h"
21
 
#include <drizzled/plugin/logging.h>
 
20
#include <drizzled/server_includes.h>
 
21
#include <drizzled/plugin/logging_handler.h>
22
22
#include <drizzled/gettext.h>
23
23
#include <drizzled/session.h>
24
 
#include PCRE_HEADER
25
 
#include <limits.h>
26
 
#include <sys/time.h>
27
 
#include <sys/types.h>
28
 
#include <sys/stat.h>
29
 
#include <fcntl.h>
30
 
#include <string>
31
 
#include <boost/format.hpp>
32
 
#include <boost/program_options.hpp>
33
 
#include <drizzled/module/option_map.h>
34
 
#include <cstdio>
35
 
#include <cerrno>
36
 
 
37
 
namespace po= boost::program_options;
38
 
using namespace drizzled;
39
 
using namespace std;
40
 
 
41
 
#define ESCAPE_CHAR      '\\'
42
 
#define SEPARATOR_CHAR   ','
43
 
 
44
 
namespace drizzle_plugin
45
 
{
 
24
#include <pcre.h>
 
25
 
 
26
/* TODO make this dynamic as needed */
 
27
static const int MAX_MSG_LEN= 32*1024;
46
28
 
47
29
static bool sysvar_logging_query_enable= false;
 
30
static char* sysvar_logging_query_filename= NULL;
 
31
static char* sysvar_logging_query_pcre= NULL;
48
32
/* 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;
 
33
static unsigned long sysvar_logging_query_threshold_slow= 0;
 
34
static unsigned long sysvar_logging_query_threshold_big_resultset= 0;
 
35
static unsigned long sysvar_logging_query_threshold_big_examined= 0;
 
36
 
 
37
/* stolen from mysys/my_getsystime
 
38
   until the Session has a good utime "now" we can use
 
39
   will have to use this instead */
 
40
 
 
41
#include <sys/time.h>
 
42
static uint64_t get_microtime()
 
43
{
 
44
#if defined(HAVE_GETHRTIME)
 
45
  return gethrtime()/1000;
 
46
#else
 
47
  uint64_t newtime;
 
48
  struct timeval t;
 
49
  /*
 
50
    The following loop is here because gettimeofday may fail on some systems
 
51
  */
 
52
  while (gettimeofday(&t, NULL) != 0) {}
 
53
  newtime= (uint64_t)t.tv_sec * 1000000 + t.tv_usec;
 
54
  return newtime;
 
55
#endif  /* defined(HAVE_GETHRTIME) */
 
56
}
52
57
 
53
58
/* quote a string to be safe to include in a CSV line
54
59
   that means backslash quoting all commas, doublequotes, backslashes,
66
71
 
67
72
*/
68
73
 
69
 
static void quotify(const string &src, string &dst)
 
74
static unsigned char *quotify (const unsigned char *src, size_t srclen,
 
75
                               unsigned char *dst, size_t dstlen)
70
76
{
71
77
  static const char hexit[]= { '0', '1', '2', '3', '4', '5', '6', '7',
72
78
                          '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
73
 
  string::const_iterator src_iter;
74
 
  
75
 
  for (src_iter= src.begin(); src_iter < src.end(); ++src_iter)
 
79
  size_t dst_ndx;  /* ndx down the dst */
 
80
  size_t src_ndx;  /* ndx down the src */
 
81
 
 
82
  assert(dst);
 
83
  assert(dstlen > 0);
 
84
 
 
85
  for (dst_ndx= 0,src_ndx= 0; src_ndx < srclen; src_ndx++)
76
86
  {
77
 
    if (static_cast<unsigned char>(*src_iter) > 0x7f)
78
 
    {
79
 
      dst.push_back(*src_iter);
80
 
    }
81
 
    else if (*src_iter == 0x00)  // null
82
 
    {
83
 
      dst.push_back(ESCAPE_CHAR); dst.push_back('0');
84
 
    }
85
 
    else if (*src_iter == 0x07)  // bell
86
 
    {
87
 
      dst.push_back(ESCAPE_CHAR); dst.push_back('a');
88
 
    }
89
 
    else if (*src_iter == 0x08)  // backspace
90
 
    {
91
 
      dst.push_back(ESCAPE_CHAR); dst.push_back('b');
92
 
    }
93
 
    else if (*src_iter == 0x09)  // horiz tab
94
 
    {
95
 
      dst.push_back(ESCAPE_CHAR); dst.push_back('t');
96
 
    }
97
 
    else if (*src_iter == 0x0a)  // line feed
98
 
    {
99
 
      dst.push_back(ESCAPE_CHAR); dst.push_back('n');
100
 
    }
101
 
    else if (*src_iter == 0x0b)  // vert tab
102
 
    {
103
 
      dst.push_back(ESCAPE_CHAR); dst.push_back('v');
104
 
    }
105
 
    else if (*src_iter == 0x0c)  // formfeed
106
 
    {
107
 
      dst.push_back(ESCAPE_CHAR); dst.push_back('f');
108
 
    }
109
 
    else if (*src_iter == 0x0d)  // carrage return
110
 
    {
111
 
      dst.push_back(ESCAPE_CHAR); dst.push_back('r');
112
 
    }
113
 
    else if (*src_iter == 0x1b)  // escape
114
 
    {
115
 
      dst.push_back(ESCAPE_CHAR); dst.push_back('e');
116
 
    }
117
 
    else if (*src_iter == 0x22)  // quotation mark
118
 
    {
119
 
      dst.push_back(ESCAPE_CHAR); dst.push_back(0x22);
120
 
    }
121
 
    else if (*src_iter == SEPARATOR_CHAR)
122
 
    {
123
 
      dst.push_back(ESCAPE_CHAR); dst.push_back(SEPARATOR_CHAR);
124
 
    }
125
 
    else if (*src_iter == ESCAPE_CHAR)
126
 
    {
127
 
      dst.push_back(ESCAPE_CHAR); dst.push_back(ESCAPE_CHAR);
128
 
    }
129
 
    else if ((*src_iter < 0x20) || (*src_iter == 0x7F))  // other unprintable ASCII
130
 
    {
131
 
      dst.push_back(ESCAPE_CHAR);
132
 
      dst.push_back('x');
133
 
      dst.push_back(hexit[(*src_iter >> 4) & 0x0f]);
134
 
      dst.push_back(hexit[*src_iter & 0x0f]);
 
87
 
 
88
    /* Worst case, need 5 dst bytes for the next src byte.
 
89
       backslash x hexit hexit null
 
90
       so if not enough room, just terminate the string and return
 
91
    */
 
92
    if ((dstlen - dst_ndx) < 5)
 
93
    {
 
94
      dst[dst_ndx]= (unsigned char)0x00;
 
95
      return dst;
 
96
    }
 
97
 
 
98
    if (src[src_ndx] > 0x7f)
 
99
    {
 
100
      // pass thru high bit characters, they are non-ASCII UTF8 Unicode
 
101
      dst[dst_ndx++]= src[src_ndx];
 
102
    }
 
103
    else if (src[src_ndx] == 0x00)  // null
 
104
    {
 
105
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= (unsigned char) '0';
 
106
    }
 
107
    else if (src[src_ndx] == 0x07)  // bell
 
108
    {
 
109
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= (unsigned char) 'a';
 
110
    }
 
111
    else if (src[src_ndx] == 0x08)  // backspace
 
112
    {
 
113
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= (unsigned char) 'b';
 
114
    }
 
115
    else if (src[src_ndx] == 0x09)  // horiz tab
 
116
    {
 
117
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= (unsigned char) 't';
 
118
    }
 
119
    else if (src[src_ndx] == 0x0a)  // line feed
 
120
    {
 
121
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= (unsigned char) 'n';
 
122
    }
 
123
    else if (src[src_ndx] == 0x0b)  // vert tab
 
124
    {
 
125
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= (unsigned char) 'v';
 
126
    }
 
127
    else if (src[src_ndx] == 0x0c)  // formfeed
 
128
    {
 
129
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= (unsigned char) 'f';
 
130
    }
 
131
    else if (src[src_ndx] == 0x0d)  // carrage return
 
132
    {
 
133
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= (unsigned char) 'r';
 
134
    }
 
135
    else if (src[src_ndx] == 0x1b)  // escape
 
136
    {
 
137
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= (unsigned char) 'e';
 
138
    }
 
139
    else if (src[src_ndx] == 0x22)  // quotation mark
 
140
    {
 
141
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= 0x22;
 
142
    }
 
143
    else if (src[src_ndx] == 0x2C)  // comma
 
144
    {
 
145
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= 0x2C;
 
146
    }
 
147
    else if (src[src_ndx] == 0x5C)  // backslash
 
148
    {
 
149
      dst[dst_ndx++]= 0x5C; dst[dst_ndx++]= 0x5C;
 
150
    }
 
151
    else if ((src[src_ndx] < 0x20) || (src[src_ndx] == 0x7F))  // other unprintable ASCII
 
152
    {
 
153
      dst[dst_ndx++]= 0x5C;
 
154
      dst[dst_ndx++]= (unsigned char) 'x';
 
155
      dst[dst_ndx++]= hexit[(src[src_ndx] >> 4) & 0x0f];
 
156
      dst[dst_ndx++]= hexit[src[src_ndx] & 0x0f];
135
157
    }
136
158
    else  // everything else
137
159
    {
138
 
      dst.push_back(*src_iter);
 
160
      dst[dst_ndx++]= src[src_ndx];
139
161
    }
 
162
    dst[dst_ndx]= '\0';
140
163
  }
 
164
  return dst;
141
165
}
142
166
 
143
167
 
144
 
class Logging_query: public drizzled::plugin::Logging
 
168
class Logging_query: public Logging_handler
145
169
{
146
 
  const std::string _filename;
147
 
  const std::string _query_pcre;
148
170
  int fd;
149
171
  pcre *re;
150
172
  pcre_extra *pe;
151
173
 
152
 
  /** Format of the output string */
153
 
  boost::format formatter;
154
 
 
155
174
public:
156
175
 
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")
 
176
  Logging_query() : Logging_handler("Logging_query"), fd(-1), re(NULL), pe(NULL)
165
177
  {
166
178
 
167
179
    /* if there is no destination filename, dont bother doing anything */
168
 
    if (_filename.empty())
 
180
    if (sysvar_logging_query_filename == NULL)
169
181
      return;
170
182
 
171
 
    fd= open(_filename.c_str(),
 
183
    fd= open(sysvar_logging_query_filename,
172
184
             O_WRONLY | O_APPEND | O_CREAT,
173
185
             S_IRUSR|S_IWUSR);
174
186
    if (fd < 0)
175
187
    {
176
 
      char errmsg[STRERROR_MAX];
177
 
      strerror_r(errno, errmsg, sizeof(errmsg));
178
188
      errmsg_printf(ERRMSG_LVL_ERROR, _("fail open() fn=%s er=%s\n"),
179
 
                    _filename.c_str(),
180
 
                    errmsg);
 
189
                    sysvar_logging_query_filename,
 
190
                    strerror(errno));
181
191
      return;
182
192
    }
183
193
 
184
 
    if (not _query_pcre.empty())
 
194
    if (sysvar_logging_query_pcre != NULL)
185
195
    {
186
196
      const char *this_pcre_error;
187
197
      int this_pcre_erroffset;
188
 
      re= pcre_compile(_query_pcre.c_str(), 0, &this_pcre_error,
 
198
      re= pcre_compile(sysvar_logging_query_pcre, 0, &this_pcre_error,
189
199
                       &this_pcre_erroffset, NULL);
190
200
      pe= pcre_study(re, 0, &this_pcre_error);
191
201
      /* TODO emit error messages if there is a problem */
210
220
    }
211
221
  }
212
222
 
 
223
 
 
224
  virtual bool pre (Session *)
 
225
  {
 
226
    /* we could just not have a pre entrypoint at all,
 
227
       and have logging_pre == NULL
 
228
       but we have this here for the sake of being an example */
 
229
    return false;
 
230
  }
 
231
 
213
232
  virtual bool post (Session *session)
214
233
  {
215
 
    size_t wrv;
 
234
    char msgbuf[MAX_MSG_LEN];
 
235
    int msgbuf_len= 0;
 
236
    int wrv;
216
237
 
217
238
    assert(session != NULL);
218
239
 
229
250
    // return if not enabled or query was too fast or resultset was too small
230
251
    if (sysvar_logging_query_enable == false)
231
252
      return false;
232
 
    if (session->sent_row_count < sysvar_logging_query_threshold_big_resultset.get())
 
253
    if (session->sent_row_count < sysvar_logging_query_threshold_big_resultset)
233
254
      return false;
234
 
    if (session->examined_row_count < sysvar_logging_query_threshold_big_examined.get())
 
255
    if (session->examined_row_count < sysvar_logging_query_threshold_big_examined)
235
256
      return false;
236
257
 
 
258
    /* TODO, looks like connect_utime isnt being set in the session
 
259
       object.  We could store the time this plugin was loaded, but that
 
260
       would just be a dumb workaround. */
237
261
    /* TODO, the session object should have a "utime command completed"
238
262
       inside itself, so be more accurate, and so this doesnt have to
239
263
       keep calling current_utime, which can be slow */
240
264
  
241
 
    boost::posix_time::ptime mytime(boost::posix_time::microsec_clock::local_time());
242
 
    boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
243
 
    uint64_t t_mark= (mytime-epoch).total_microseconds();
244
 
 
245
 
    if ((t_mark - session->start_utime) < (sysvar_logging_query_threshold_slow.get()))
 
265
    uint64_t t_mark= get_microtime();
 
266
  
 
267
    if ((t_mark - session->start_utime) < (sysvar_logging_query_threshold_slow))
246
268
      return false;
247
269
 
248
 
    Session::QueryString query_string(session->getQueryString());
249
270
    if (re)
250
271
    {
251
272
      int this_pcre_rc;
252
 
      this_pcre_rc= pcre_exec(re, pe, query_string->c_str(), query_string->length(), 0, 0, NULL, 0);
 
273
      this_pcre_rc = pcre_exec(re, pe, session->query, session->query_length, 0, 0, NULL, 0);
253
274
      if (this_pcre_rc < 0)
254
275
        return false;
255
276
    }
256
277
 
257
278
    // buffer to quotify the query
258
 
    string qs;
259
 
    
260
 
    // Since quotify() builds the quoted string incrementally, we can
261
 
    // avoid some reallocating if we reserve some space up front.
262
 
    qs.reserve(query_string->length());
263
 
    
264
 
    quotify(*query_string, qs);
265
 
    
 
279
    unsigned char qs[255];
 
280
  
266
281
    // to avoid trying to printf %s something that is potentially NULL
267
 
    util::string::const_shared_ptr schema(session->schema());
268
 
    const char *dbs= (schema and not schema->empty()) ? schema->c_str() : "";
269
 
 
270
 
    formatter % t_mark
271
 
              % session->thread_id
272
 
              % session->getQueryId()
273
 
              % dbs
274
 
              % qs
275
 
              % command_name[session->command].str
276
 
              % (t_mark - session->getConnectMicroseconds())
277
 
              % (t_mark - session->start_utime)
278
 
              % (t_mark - session->utime_after_lock)
279
 
              % session->sent_row_count
280
 
              % session->examined_row_count
281
 
              % session->tmp_table
282
 
              % session->total_warn_count
283
 
              % session->getServerId()
284
 
              % glob_hostname;
285
 
 
286
 
    string msgbuf= formatter.str();
287
 
 
 
282
    const char *dbs= (session->db) ? session->db : "";
 
283
    int dbl= 0;
 
284
    if (dbs != NULL)
 
285
      dbl= session->db_length;
 
286
  
 
287
    msgbuf_len=
 
288
      snprintf(msgbuf, MAX_MSG_LEN,
 
289
               "%"PRIu64",%"PRIu64",%"PRIu64",\"%.*s\",\"%s\",\"%.*s\","
 
290
               "%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64
 
291
               "%"PRIu32",%"PRIu32"\n",
 
292
               t_mark,
 
293
               session->thread_id,
 
294
               session->query_id,
 
295
               // dont need to quote the db name, always CSV safe
 
296
               dbl, dbs,
 
297
               // do need to quote the query
 
298
               quotify((unsigned char *)session->query,
 
299
                       session->query_length, qs, sizeof(qs)),
 
300
               // command_name is defined in drizzled/sql_parse.cc
 
301
               // dont need to quote the command name, always CSV safe
 
302
               (int)command_name[session->command].length,
 
303
               command_name[session->command].str,
 
304
               // counters are at end, to make it easier to add more
 
305
               (t_mark - session->connect_utime),
 
306
               (t_mark - session->start_utime),
 
307
               (t_mark - session->utime_after_lock),
 
308
               session->sent_row_count,
 
309
               session->examined_row_count,
 
310
               session->tmp_table,
 
311
               session->total_warn_count);
 
312
  
288
313
    // a single write has a kernel thread lock, thus no need mutex guard this
289
 
    wrv= write(fd, msgbuf.c_str(), msgbuf.length());
290
 
    assert(wrv == msgbuf.length());
291
 
 
 
314
    wrv= write(fd, msgbuf, msgbuf_len);
 
315
    assert(wrv == msgbuf_len);
 
316
  
292
317
    return false;
293
318
  }
294
319
};
295
320
 
296
 
static int logging_query_plugin_init(drizzled::module::Context &context)
297
 
{
298
 
 
299
 
  const module::option_map &vm= context.getOptions();
300
 
 
301
 
  if (vm.count("filename") > 0)
302
 
  {
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));
311
 
  }
312
 
 
313
 
  return 0;
314
 
}
315
 
 
316
 
static void init_options(drizzled::module::option_context &context)
317
 
{
318
 
  context("enable",
319
 
          po::value<bool>(&sysvar_logging_query_enable)->default_value(false)->zero_tokens(),
320
 
          N_("Enable logging to CSV file"));
321
 
  context("filename",
322
 
          po::value<string>(),
323
 
          N_("File to log to"));
324
 
  context("pcre",
325
 
          po::value<string>()->default_value(""),
326
 
          N_("PCRE to match the query against"));
327
 
  context("threshold-slow",
328
 
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_slow)->default_value(0),
329
 
          N_("Threshold for logging slow queries, in microseconds"));
330
 
  context("threshold-big-resultset",
331
 
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_resultset)->default_value(0),
332
 
          N_("Threshold for logging big queries, for rows returned"));
333
 
  context("threshold-big-examined",
334
 
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_examined)->default_value(0),
335
 
          N_("Threshold for logging big queries, for rows examined"));
336
 
}
337
 
 
338
 
} /* namespace drizzle_plugin */
339
 
 
340
 
DRIZZLE_DECLARE_PLUGIN
341
 
{
342
 
  DRIZZLE_VERSION_ID,
343
 
  "logging-query",
 
321
static Logging_query *handler= NULL;
 
322
 
 
323
static int logging_query_plugin_init(PluginRegistry &registry)
 
324
{
 
325
  handler= new Logging_query();
 
326
  registry.add(handler);
 
327
 
 
328
  return 0;
 
329
}
 
330
 
 
331
static int logging_query_plugin_deinit(PluginRegistry &registry)
 
332
{
 
333
  registry.remove(handler);
 
334
  delete handler;
 
335
 
 
336
  return 0;
 
337
}
 
338
 
 
339
static DRIZZLE_SYSVAR_BOOL(
 
340
  enable,
 
341
  sysvar_logging_query_enable,
 
342
  PLUGIN_VAR_NOCMDARG,
 
343
  N_("Enable logging to CSV file"),
 
344
  NULL, /* check func */
 
345
  NULL, /* update func */
 
346
  false /* default */);
 
347
 
 
348
static DRIZZLE_SYSVAR_STR(
 
349
  filename,
 
350
  sysvar_logging_query_filename,
 
351
  PLUGIN_VAR_READONLY,
 
352
  N_("File to log to"),
 
353
  NULL, /* check func */
 
354
  NULL, /* update func*/
 
355
  NULL /* default */);
 
356
 
 
357
static DRIZZLE_SYSVAR_STR(
 
358
  pcre,
 
359
  sysvar_logging_query_pcre,
 
360
  PLUGIN_VAR_READONLY,
 
361
  N_("PCRE to match the query against"),
 
362
  NULL, /* check func */
 
363
  NULL, /* update func*/
 
364
  NULL /* default */);
 
365
 
 
366
static DRIZZLE_SYSVAR_ULONG(
 
367
  threshold_slow,
 
368
  sysvar_logging_query_threshold_slow,
 
369
  PLUGIN_VAR_OPCMDARG,
 
370
  N_("Threshold for logging slow queries, in microseconds"),
 
371
  NULL, /* check func */
 
372
  NULL, /* update func */
 
373
  0, /* default */
 
374
  0, /* min */
 
375
  UINT32_MAX, /* max */
 
376
  0 /* blksiz */);
 
377
 
 
378
static DRIZZLE_SYSVAR_ULONG(
 
379
  threshold_big_resultset,
 
380
  sysvar_logging_query_threshold_big_resultset,
 
381
  PLUGIN_VAR_OPCMDARG,
 
382
  N_("Threshold for logging big queries, for rows returned"),
 
383
  NULL, /* check func */
 
384
  NULL, /* update func */
 
385
  0, /* default */
 
386
  0, /* min */
 
387
  UINT32_MAX, /* max */
 
388
  0 /* blksiz */);
 
389
 
 
390
static DRIZZLE_SYSVAR_ULONG(
 
391
  threshold_big_examined,
 
392
  sysvar_logging_query_threshold_big_examined,
 
393
  PLUGIN_VAR_OPCMDARG,
 
394
  N_("Threshold for logging big queries, for rows examined"),
 
395
  NULL, /* check func */
 
396
  NULL, /* update func */
 
397
  0, /* default */
 
398
  0, /* min */
 
399
  UINT32_MAX, /* max */
 
400
  0 /* blksiz */);
 
401
 
 
402
static struct st_mysql_sys_var* logging_query_system_variables[]= {
 
403
  DRIZZLE_SYSVAR(enable),
 
404
  DRIZZLE_SYSVAR(filename),
 
405
  DRIZZLE_SYSVAR(pcre),
 
406
  DRIZZLE_SYSVAR(threshold_slow),
 
407
  DRIZZLE_SYSVAR(threshold_big_resultset),
 
408
  DRIZZLE_SYSVAR(threshold_big_examined),
 
409
  NULL
 
410
};
 
411
 
 
412
drizzle_declare_plugin(logging_query)
 
413
{
 
414
  "logging_query",
344
415
  "0.2",
345
416
  "Mark Atwood <mark@fallenpegasus.com>",
346
417
  N_("Log queries to a CSV file"),
347
418
  PLUGIN_LICENSE_GPL,
348
 
  drizzle_plugin::logging_query_plugin_init,
349
 
  NULL,
350
 
  drizzle_plugin::init_options
 
419
  logging_query_plugin_init,
 
420
  logging_query_plugin_deinit,
 
421
  NULL,   /* status variables */
 
422
  logging_query_system_variables,
 
423
  NULL
351
424
}
352
 
DRIZZLE_DECLARE_PLUGIN_END;
 
425
drizzle_declare_plugin_end;