1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright 2011 Daniel Nichter
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, either version 3 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
22
#include <boost/program_options.hpp>
23
#include <drizzled/item.h>
24
#include <drizzled/data_home.h>
25
#include <drizzled/module/option_map.h>
26
#include <drizzled/session.h>
27
#include <drizzled/plugin.h>
28
#include "query_log.h"
30
namespace po= boost::program_options;
32
using namespace drizzled;
34
namespace drizzle_plugin
37
* Forward declarations.
38
* Mac OS X 10.6 with gcc 4.2.1 misses this warning (but still compiles):
39
* configure:23893: g++ -c -Werror -pedantic -Wmissing-declarations \
40
* -std=gnu++98 -O0 -DDEBUG conftest.cpp >&5
41
* cc1plus: warnings being treated as errors
42
* cc1plus: warning: command line option "-Wmissing-declarations" is valid
43
* for C/ObjC but not for C++
45
bool update_file(Session *, set_var *var);
46
void update_file_enabled(Session *, sql_var_t);
49
* An instance of our class, QueryLog, which implements the query_log plugin,
50
* and an instance of the QueryLoggerClass for logging queries to a file.
51
* These objects are global so update_file() and update_file_enabled() can
52
* access them. They're instantiated in init_options().
54
static drizzled::plugin::QueryLog *query_log= NULL;
55
static QueryLoggerFile *logger_file= NULL;
60
const char *default_file= "drizzled-queries.log"; ///< Default query log file
64
* Update query_log_file (query_log->sysvar_file).
67
* When SET GLOBAL query_log_file="new-file.log" is executed by the user,
68
* this function is called which checkes that the new file is not NULL or
69
* a blank string, then calls logger_file->openLogFile, passing it the new
70
* log file name, e.g. "new-file.log". If the new log file is opened, the
71
* system variable is updated, else it is not updated and logging continues
72
* to the old log file.
74
* @retval true Error, log file not changed
75
* @retval false Success, log file changed
77
bool update_file(Session *, set_var *var)
79
const char *new_file= var->value->str_value.ptr();
83
errmsg_printf(error::ERROR, _("The query log file name must be defined."));
87
if (strlen(new_file) == 0)
89
errmsg_printf(error::ERROR, _("The query log file name must have a value."));
94
* If the the log file is enabled, then try to open the new log file.
95
* If it's not enabled, then just update query_log_file because the user
97
* close current log file (SET GLOBAL log_file_enabled=FALSE)
98
* switch to new log file (SET GLOBAL log_file="new-file.log")
99
* enable new log file (SET GLOBAL log_file_enabled=TRUE)
100
* (Maybe they're doing this to rotate the log?) If this is the case,
101
* then we don't want to open the new log file before it's enabled,
102
* but we also don't want to leave query_log_file set to the old log
103
* file name. When the log file is re-enabled later, update_file_enabled()
104
* will be called and the new log file will be opened.
106
if (query_log->sysvar_file_enabled)
108
if (logger_file->openLogFile(new_file))
110
errmsg_printf(error::ERROR, "Cannot open the query log file %s", new_file);
111
return true; // error
115
// Update query_log_file in SHOW VARIABLES.
116
query_log->sysvar_file= new_file;
118
return false; // success
123
* Update query_log_file_enabled (query_log->sysvar_file_enabled).
126
* When SET GLOBAL query_log_file_enabled=... is executed by the user,
127
* this function is called *after* Drizzle updates the variable with the
128
* new value, so in this function we have the new/current value. If the
129
* log file is enabled, then open query_log_file (query_log->sysvar_file);
130
* else, close the log file.
132
void update_file_enabled(Session *, sql_var_t)
134
if (query_log->sysvar_file_enabled)
136
if (logger_file->openLogFile(query_log->sysvar_file.c_str()))
138
errmsg_printf(error::ERROR, "Cannot enable the query log file because the query log file %s cannot be opened.", query_log->sysvar_file.c_str());
139
query_log->sysvar_file_enabled= false;
143
logger_file->closeLogFile();
148
* Initialize query-log command line options.
151
* This function is called first, before init(). We instantiate our one
152
* and only QueryLog object (query_log) here so that po (boost::program_options)
153
* can store the command line options' values in public query_log variables.
154
* This avoids using global variables and keeps (almost) everything encapsulated
157
static void init_options(drizzled::module::option_context &context)
159
logger_file= new QueryLoggerFile();
160
query_log= new drizzled::plugin::QueryLog(true, logger_file);
164
po::value<bool>(&query_log->sysvar_file_enabled)->default_value(false)->zero_tokens(),
165
N_("Enable query logging to file"));
169
po::value<string>(&query_log->sysvar_file)->default_value(default_file),
170
N_("Query log file"));
173
"threshold-execution-time",
174
po::value<uint32_constraint>(&query_log->sysvar_threshold_execution_time)->default_value(0),
175
_("Threshold for logging slow queries, in microseconds"));
178
"threshold-lock-time",
179
po::value<uint32_constraint>(&query_log->sysvar_threshold_lock_time)->default_value(0),
180
_("Threshold for logging long locking queries, in microseconds"));
183
"threshold-rows-examined",
184
po::value<uint32_constraint>(&query_log->sysvar_threshold_rows_examined)->default_value(0),
185
_("Threshold for logging queries that examine too many rows, integer"));
188
"threshold-rows-sent",
189
po::value<uint32_constraint>(&query_log->sysvar_threshold_rows_sent)->default_value(0),
190
_("Threshold for logging queries that return too many rows, integer"));
193
"threshold-tmp-tables",
194
po::value<uint32_constraint>(&query_log->sysvar_threshold_tmp_tables)->default_value(0),
195
_("Threshold for logging queries that use too many temporary tables, integer"));
198
"threshold-warnings",
199
po::value<uint32_constraint>(&query_log->sysvar_threshold_warnings)->default_value(0),
200
_("Threshold for logging queries that cause too many warnings, integer"));
203
"threshold-session-time",
204
po::value<uint32_constraint>(&query_log->sysvar_threshold_session_time)->default_value(0),
205
_("Threshold for logging queries that are active too long, in seconds"));
211
* Add query_log plugin to Drizzle and initalize query_log system variables.
214
* This is where we plug into Drizzle and register our system variables.
215
* Since this is called after init_options(), vm has either values from
216
* the command line or defaults. System variables corresponding to
217
* command line options use the same public query_log variables so that
218
* values from vm (the command line) are automatically reflected in the
219
* system variable (SHOW VARIABLES). This also makes changes to certain
220
* system variables automatic/instant because when they're updated (e.g.
221
* SET GLOBAL query_log_enabled=TRUE|FALSE) Drizzle changes the corresponding
222
* public query_log variable. Certain system variables, like query_log_file,
223
* require more work to change, so they're handled by update functions like
228
static int init(drizzled::module::Context &context)
230
const module::option_map &vm= context.getOptions();
232
// Open the log file now that we have either an explicit value from the
233
// command line (--query-log.file=FILE) or the default file.
234
if (vm["file-enabled"].as<bool>())
235
logger_file->openLogFile(vm["file"].as<string>().c_str());
237
// Plug into Drizzle!
238
context.add(query_log);
240
// Register our system variables with Drizzle, e.g. query_log_enabled,
241
// query_log_file, etc. in SHOW VARIABLES.
242
context.registerVariable(
243
new sys_var_bool_ptr(
244
"enabled", &query_log->sysvar_enabled));
246
context.registerVariable(
247
new sys_var_bool_ptr(
248
"file_enabled", &query_log->sysvar_file_enabled, &update_file_enabled));
250
context.registerVariable(
251
new sys_var_std_string(
252
"file", query_log->sysvar_file, NULL, &update_file));
254
context.registerVariable(
255
new sys_var_constrained_value<uint32_t>(
256
"threshold_execution_time", query_log->sysvar_threshold_execution_time));
258
context.registerVariable(
259
new sys_var_constrained_value<uint32_t>(
260
"threshold_lock_time", query_log->sysvar_threshold_lock_time));
262
context.registerVariable(
263
new sys_var_constrained_value<uint32_t>(
264
"threshold_rows_examined", query_log->sysvar_threshold_rows_examined));
266
context.registerVariable(
267
new sys_var_constrained_value<uint32_t>(
268
"threshold_rows_sent", query_log->sysvar_threshold_rows_sent));
270
context.registerVariable(
271
new sys_var_constrained_value<uint32_t>(
272
"threshold_tmp_tables", query_log->sysvar_threshold_tmp_tables));
274
context.registerVariable(
275
new sys_var_constrained_value<uint32_t>(
276
"threshold_warnings", query_log->sysvar_threshold_warnings));
278
context.registerVariable(
279
new sys_var_constrained_value<uint32_t>(
280
"threshold_session_time", query_log->sysvar_threshold_session_time));
285
} /* namespace drizzle_plugin */
287
DRIZZLE_PLUGIN(drizzle_plugin::init, NULL, drizzle_plugin::init_options);