~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/logging_query/logging_query.cc

  • Committer: Mark Atwood
  • Date: 2008-10-16 11:33:16 UTC
  • mto: (520.1.13 drizzle)
  • mto: This revision was merged to the branch mainline in revision 530.
  • Revision ID: mark@fallenpegasus.com-20081016113316-ff6jdt31ck90sjdh
an implemention of the errmsg plugin

Show diffs side-by-side

added added

removed removed

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