~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/logging_query/logging_query.cc

Merging Mark's work

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* drizzle/plugin/logging_query/logging_query.cc */
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Mark Atwood
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
2
19
 
3
20
/* need to define DRIZZLE_SERVER to get inside the THD */
4
21
#define DRIZZLE_SERVER 1
5
22
#include <drizzled/server_includes.h>
6
23
#include <drizzled/plugin_logging.h>
7
24
 
 
25
/* todo, make this dynamic as needed */
8
26
#define MAX_MSG_LEN (32*1024)
9
27
 
10
28
static char* logging_query_filename= NULL;
 
29
static bool logging_query_enable= true;
 
30
static ulong logging_query_enable_time= 0;
 
31
static ulong logging_query_threshold_big_resultset= 0;
11
32
 
12
33
static int fd= -1;
13
34
 
14
35
// copied from drizzled/sql_parse.cc
15
 
 
16
36
const LEX_STRING command_name[]={
17
37
  { C_STRING_WITH_LEN("Sleep") },
18
38
  { C_STRING_WITH_LEN("Quit") },
38
58
};
39
59
 
40
60
 
41
 
bool logging_query_func_pre (THD *thd)
 
61
/* stolen from mysys/my_getsystime 
 
62
   until the THD has a good utime "now" we can use
 
63
   will have to use this instead */
 
64
 
 
65
#include <sys/time.h>
 
66
static uint64_t get_microtime()
42
67
{
43
 
  char msgbuf[MAX_MSG_LEN];
44
 
  int msgbuf_len= 0;
45
 
  int wrv;
46
 
 
47
 
  if (fd < 0) 
48
 
    return false;
49
 
 
50
 
  assert(thd != NULL);
51
 
 
52
 
  msgbuf_len=
53
 
    snprintf(msgbuf, MAX_MSG_LEN,
54
 
             "log bgn thread_id=%ld query_id=%ld command=%.*s"
55
 
             " db=\"%.*s\" query=\"%.*s\"\n",
56
 
             (unsigned long) thd->thread_id,
57
 
             (unsigned long) thd->query_id,
58
 
             (uint32_t)command_name[thd->command].length, command_name[thd->command].str,
59
 
             thd->db_length, thd->db,
60
 
             thd->query_length, thd->query);
61
 
  /* a single write has a OS level thread lock
62
 
     so there is no need to have mutexes guarding this write,
 
68
#if defined(HAVE_GETHRTIME)
 
69
  return gethrtime()/1000;
 
70
#else
 
71
  uint64_t newtime;
 
72
  struct timeval t;
 
73
  /*
 
74
    The following loop is here because gettimeofday may fail on some systems
63
75
  */
64
 
  wrv= write(fd, msgbuf, msgbuf_len);
65
 
  assert(wrv == msgbuf_len);
 
76
  while (gettimeofday(&t, NULL) != 0) {}
 
77
  newtime= (uint64_t)t.tv_sec * 1000000 + t.tv_usec;
 
78
  return newtime;
 
79
#endif  /* defined(HAVE_GETHRTIME) */
 
80
}
66
81
 
 
82
/* we could just not have a pre entrypoint at all,
 
83
   and have logging_pre == NULL
 
84
   but we have this here for the sake of being an example */
 
85
bool logging_query_func_pre (THD *thd __attribute__((unused)))
 
86
{
67
87
  return false;
68
88
}
69
89
 
77
97
 
78
98
  assert(thd != NULL);
79
99
 
 
100
  /*
 
101
    here is some time stuff from class THD
 
102
      uint64_t connect_utime;
 
103
        todo, looks like this isnt being set
 
104
        we could store the time this plugin was loaded
 
105
        but that would just be a dumb workaround
 
106
      uint64_t start_utime;
 
107
      uint64_t utime_after_lock;
 
108
      uint64_t current_utime();
 
109
        todo, cant get to because of namemangling
 
110
  */
 
111
 
 
112
  /* todo, the THD should have a "utime command completed" inside
 
113
     itself, so be more accurate, and so plugins dont have to keep
 
114
     calling current_utime, which can be slow */
 
115
  uint64_t t_mark= get_microtime();
 
116
 
80
117
  msgbuf_len=
81
118
    snprintf(msgbuf, MAX_MSG_LEN,
82
 
             "log end thread_id=%ld query_id=%ld command=%.*s"
83
 
             " rows.sent=%ld rows.exam=%u\n",
 
119
             _("thread_id=%ld query_id=%ld"
 
120
               " t_connect=%lld t_start=%lld t_lock=%lld"
 
121
               " command=%.*s"
 
122
               " rows_sent=%ld rows_examined=%u\n"
 
123
               " db=\"%.*s\" query=\"%.*s\"\n"),
84
124
             (unsigned long) thd->thread_id, 
85
125
             (unsigned long) thd->query_id,
86
 
             (uint32_t)command_name[thd->command].length, command_name[thd->command].str,
 
126
             (unsigned long long)(t_mark - thd->connect_utime),
 
127
             (unsigned long long)(t_mark - thd->start_utime),
 
128
             (unsigned long long)(t_mark - thd->utime_after_lock),
 
129
             (uint32_t)command_name[thd->command].length,
 
130
             command_name[thd->command].str,
87
131
             (unsigned long) thd->sent_row_count,
88
 
             (uint32_t) thd->examined_row_count);
 
132
             (uint32_t) thd->examined_row_count,
 
133
             thd->db_length, thd->db,
 
134
             thd->query_length, thd->query);
89
135
  /* a single write has a OS level thread lock
90
136
     so there is no need to have mutexes guarding this write,
91
137
  */
92
138
  wrv= write(fd, msgbuf, msgbuf_len);
93
139
  assert(wrv == msgbuf_len);
94
140
 
95
 
 
96
141
  return false;
97
142
}
98
143
 
112
157
           S_IRUSR|S_IWUSR);
113
158
  if (fd < 0) 
114
159
  {
115
 
    fprintf(stderr, "fail open fn=%s er=%s\n",
116
 
            logging_query_filename,
117
 
            strerror(errno));
 
160
    sql_print_error(_("fail open() fn=%s er=%s\n"),
 
161
                    logging_query_filename,
 
162
                    strerror(errno));
118
163
 
119
 
    /* we should return an error here, so the plugin doesnt load
 
164
    /* todo
 
165
       we should return an error here, so the plugin doesnt load
120
166
       but this causes Drizzle to crash
121
167
       so until that is fixed,
122
168
       just return a success,
147
193
  return 0;
148
194
}
149
195
 
150
 
static DRIZZLE_SYSVAR_STR(filename, logging_query_filename,
 
196
static DRIZZLE_SYSVAR_STR(
 
197
  filename,
 
198
  logging_query_filename,
151
199
  PLUGIN_VAR_READONLY,
152
 
  "File to log queries to.",
153
 
  NULL, NULL, NULL);
 
200
  N_("File to log to"),
 
201
  NULL, /* check func */
 
202
  NULL, /* update func*/
 
203
  NULL /* default */);
 
204
 
 
205
static DRIZZLE_SYSVAR_BOOL(
 
206
  enable,
 
207
  logging_query_enable,
 
208
  PLUGIN_VAR_NOCMDARG,
 
209
  N_("Enable logging"),
 
210
  NULL, /* check func */
 
211
  NULL, /* update func */
 
212
  true /* default */);
 
213
 
 
214
static DRIZZLE_SYSVAR_ULONG(
 
215
  enable_time,
 
216
  logging_query_enable_time,
 
217
  PLUGIN_VAR_OPCMDARG,
 
218
  N_("Disable after this many seconds. Zero for forever"),
 
219
  NULL, /* check func */
 
220
  NULL, /* update func */
 
221
  0, /* default */
 
222
  0, /* min */
 
223
  ULONG_MAX, /* max */
 
224
  0 /* blksiz */);
 
225
 
 
226
#ifdef NOT_YET
 
227
static DRIZZLE_SYSVAR_ULONG(
 
228
  threshhold_slow,
 
229
  logging_query_threshold_slow,
 
230
  PLUGIN_VAR_OPCMDARG,
 
231
  N_("Threshold for logging slow queries, in microseconds"),
 
232
  NULL, /* check func */
 
233
  NULL, /* update func */
 
234
  0, /* default */
 
235
  0, /* min */
 
236
  ULONG_MAX, /* max */
 
237
  0 /* blksiz */);
 
238
#endif
 
239
 
 
240
static DRIZZLE_SYSVAR_ULONG(
 
241
  threshold_big_resultset,
 
242
  logging_query_threshold_big_resultset,
 
243
  PLUGIN_VAR_OPCMDARG,
 
244
  N_("Threshold for logging big queries, for rows returned"),
 
245
  NULL, /* check func */
 
246
  NULL, /* update func */
 
247
  0, /* default */
 
248
  0, /* min */
 
249
  ULONG_MAX, /* max */
 
250
  0 /* blksiz */);
 
251
 
 
252
#ifdef NOT_YET
 
253
static DRIZZLE_SYSVAR_ULONG(
 
254
  threshhold_big_examined,
 
255
  logging_query_threshold_big_examined,
 
256
  PLUGIN_VAR_OPCMDARG,
 
257
  N_("Threshold for logging big queries, for rows examined"),
 
258
  NULL, /* check func */
 
259
  NULL, /* update func */
 
260
  0, /* default */
 
261
  0, /* min */
 
262
  ULONG_MAX, /* max */
 
263
  0 /* blksiz */);
 
264
#endif
154
265
 
155
266
static struct st_mysql_sys_var* logging_query_system_variables[]= {
156
267
  DRIZZLE_SYSVAR(filename),
 
268
  DRIZZLE_SYSVAR(enable),
 
269
  DRIZZLE_SYSVAR(enable_time),
 
270
  DRIZZLE_SYSVAR(threshold_big_resultset),
157
271
  NULL
158
272
};
159
273
 
163
277
  "logging_query",
164
278
  "0.1",
165
279
  "Mark Atwood <mark@fallenpegasus.com>",
166
 
  "Log queries",
 
280
  N_("Log queries to a file"),
167
281
  PLUGIN_LICENSE_GPL,
168
282
  logging_query_plugin_init,
169
283
  logging_query_plugin_deinit,