1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Mark Atwood
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.
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.
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
1
/* drizzle/plugin/logging_query/logging_query.cc */
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>
27
/* todo, make this dynamic as needed */
28
8
#define MAX_MSG_LEN (32*1024)
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;
37
14
// copied from drizzled/sql_parse.cc
38
16
const LEX_STRING command_name[]={
39
17
{ C_STRING_WITH_LEN("Sleep") },
40
18
{ C_STRING_WITH_LEN("Quit") },
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 */
68
static uint64_t get_microtime()
41
bool logging_query_func_pre (THD *thd)
70
#if defined(HAVE_GETHRTIME)
71
return gethrtime()/1000;
76
The following loop is here because gettimeofday may fail on some systems
43
char msgbuf[MAX_MSG_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,
78
while (gettimeofday(&t, NULL) != 0) {}
79
newtime= (uint64_t)t.tv_sec * 1000000 + t.tv_usec;
81
#endif /* defined(HAVE_GETHRTIME) */
64
wrv= write(fd, msgbuf, msgbuf_len);
65
assert(wrv == msgbuf_len);
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)))
92
bool logging_query_func_post (Session *session)
70
bool logging_query_func_post (THD *thd)
94
72
char msgbuf[MAX_MSG_LEN];
98
76
if (fd < 0) return false;
100
assert(session != NULL);
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
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();
120
81
snprintf(msgbuf, MAX_MSG_LEN,
121
"thread_id=%ld query_id=%ld"
122
" t_connect=%lld t_start=%lld t_lock=%lld"
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,
140
92
wrv= write(fd, msgbuf, msgbuf_len);
141
93
assert(wrv == msgbuf_len);
159
112
S_IRUSR|S_IWUSR);
162
sql_print_error(_("fail open() fn=%s er=%s\n"),
163
logging_query_filename,
115
fprintf(stderr, "fail open fn=%s er=%s\n",
116
logging_query_filename,
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,
198
static DRIZZLE_SYSVAR_STR(
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*/
207
static DRIZZLE_SYSVAR_BOOL(
209
logging_query_enable,
211
N_("Enable logging"),
212
NULL, /* check func */
213
NULL, /* update func */
216
static DRIZZLE_SYSVAR_ULONG(
218
logging_query_enable_time,
220
N_("Disable after this many seconds. Zero for forever"),
221
NULL, /* check func */
222
NULL, /* update func */
229
static DRIZZLE_SYSVAR_ULONG(
231
logging_query_threshold_slow,
233
N_("Threshold for logging slow queries, in microseconds"),
234
NULL, /* check func */
235
NULL, /* update func */
242
static DRIZZLE_SYSVAR_ULONG(
243
threshold_big_resultset,
244
logging_query_threshold_big_resultset,
246
N_("Threshold for logging big queries, for rows returned"),
247
NULL, /* check func */
248
NULL, /* update func */
255
static DRIZZLE_SYSVAR_ULONG(
256
threshhold_big_examined,
257
logging_query_threshold_big_examined,
259
N_("Threshold for logging big queries, for rows examined"),
260
NULL, /* check func */
261
NULL, /* update func */
152
"File to log queries to.",
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),