2311.1.3
by Daniel Nichter
Change to GPLv3 license. |
1 |
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
2311.1.1
by Daniel Nichter
Add query_log plugin. It's tested and documented. |
2 |
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
|
3 |
*
|
|
2311.1.3
by Daniel Nichter
Change to GPLv3 license. |
4 |
* Copyright 2011 Daniel Nichter
|
2311.1.1
by Daniel Nichter
Add query_log plugin. It's tested and documented. |
5 |
*
|
2311.1.3
by Daniel Nichter
Change to GPLv3 license. |
6 |
* This program is free software: you can redistribute it and/or modify
|
2311.1.1
by Daniel Nichter
Add query_log plugin. It's tested and documented. |
7 |
* it under the terms of the GNU General Public License as published by
|
2311.1.3
by Daniel Nichter
Change to GPLv3 license. |
8 |
* the Free Software Foundation, either version 3 of the License, or
|
9 |
* (at your option) any later version.
|
|
2311.1.1
by Daniel Nichter
Add query_log plugin. It's tested and documented. |
10 |
*
|
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.
|
|
15 |
*
|
|
16 |
* You should have received a copy of the GNU General Public License
|
|
2311.1.3
by Daniel Nichter
Change to GPLv3 license. |
17 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2311.1.1
by Daniel Nichter
Add query_log plugin. It's tested and documented. |
18 |
*/
|
19 |
||
20 |
#include <config.h> |
|
21 |
#include <string> |
|
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" |
|
29 |
||
30 |
namespace po= boost::program_options; |
|
31 |
using namespace std; |
|
32 |
using namespace drizzled; |
|
33 |
||
2385.3.30
by Olaf van der Spek
cppcheck |
34 |
namespace drizzle_plugin { |
35 |
||
2311.1.6
by Daniel Nichter
Fix -Wmissing-declarations warnings by adding forward declarations. |
36 |
/**
|
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++
|
|
44 |
*/
|
|
45 |
bool update_file(Session *, set_var *var); |
|
46 |
void update_file_enabled(Session *, sql_var_t); |
|
2311.1.1
by Daniel Nichter
Add query_log plugin. It's tested and documented. |
47 |
|
48 |
/**
|
|
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().
|
|
53 |
*/
|
|
54 |
static drizzled::plugin::QueryLog *query_log= NULL; |
|
55 |
static QueryLoggerFile *logger_file= NULL; |
|
56 |
||
57 |
/**
|
|
58 |
* Sensible defaults.
|
|
59 |
*/
|
|
60 |
const char *default_file= "drizzled-queries.log"; ///< Default query log file |
|
61 |
||
62 |
/**
|
|
63 |
* @brief
|
|
64 |
* Update query_log_file (query_log->sysvar_file).
|
|
65 |
*
|
|
66 |
* @details
|
|
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.
|
|
73 |
*
|
|
74 |
* @retval true Error, log file not changed
|
|
75 |
* @retval false Success, log file changed
|
|
76 |
*/
|
|
77 |
bool update_file(Session *, set_var *var) |
|
78 |
{
|
|
79 |
const char *new_file= var->value->str_value.ptr(); |
|
80 |
||
2385.3.30
by Olaf van der Spek
cppcheck |
81 |
if (not new_file) |
2311.1.1
by Daniel Nichter
Add query_log plugin. It's tested and documented. |
82 |
{
|
83 |
errmsg_printf(error::ERROR, _("The query log file name must be defined.")); |
|
84 |
return false; |
|
85 |
}
|
|
86 |
||
2385.3.30
by Olaf van der Spek
cppcheck |
87 |
if (not *new_file) |
2311.1.1
by Daniel Nichter
Add query_log plugin. It's tested and documented. |
88 |
{
|
89 |
errmsg_printf(error::ERROR, _("The query log file name must have a value.")); |
|
90 |
return false; |
|
91 |
}
|
|
92 |
||
93 |
/**
|
|
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
|
|
96 |
* might be trying to:
|
|
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.
|
|
105 |
*/
|
|
106 |
if (query_log->sysvar_file_enabled) |
|
107 |
{
|
|
108 |
if (logger_file->openLogFile(new_file)) |
|
109 |
{
|
|
110 |
errmsg_printf(error::ERROR, "Cannot open the query log file %s", new_file); |
|
111 |
return true; // error |
|
112 |
}
|
|
113 |
}
|
|
114 |
||
115 |
// Update query_log_file in SHOW VARIABLES.
|
|
116 |
query_log->sysvar_file= new_file; |
|
117 |
||
118 |
return false; // success |
|
119 |
}
|
|
120 |
||
121 |
/**
|
|
122 |
* @brief
|
|
123 |
* Update query_log_file_enabled (query_log->sysvar_file_enabled).
|
|
124 |
*
|
|
125 |
* @details
|
|
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.
|
|
131 |
*/
|
|
132 |
void update_file_enabled(Session *, sql_var_t) |
|
133 |
{
|
|
134 |
if (query_log->sysvar_file_enabled) |
|
135 |
{
|
|
136 |
if (logger_file->openLogFile(query_log->sysvar_file.c_str())) |
|
137 |
{
|
|
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; |
|
140 |
}
|
|
141 |
}
|
|
142 |
else
|
|
143 |
logger_file->closeLogFile(); |
|
144 |
}
|
|
145 |
||
146 |
/**
|
|
147 |
* @brief
|
|
148 |
* Initialize query-log command line options.
|
|
149 |
*
|
|
150 |
* @details
|
|
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
|
|
155 |
* in query_log.
|
|
156 |
*/
|
|
157 |
static void init_options(drizzled::module::option_context &context) |
|
158 |
{
|
|
159 |
logger_file= new QueryLoggerFile(); |
|
160 |
query_log= new drizzled::plugin::QueryLog(true, logger_file); |
|
161 |
||
162 |
context( |
|
163 |
"file-enabled", |
|
164 |
po::value<bool>(&query_log->sysvar_file_enabled)->default_value(false)->zero_tokens(), |
|
165 |
N_("Enable query logging to file")); |
|
166 |
||
167 |
context( |
|
168 |
"file", |
|
169 |
po::value<string>(&query_log->sysvar_file)->default_value(default_file), |
|
170 |
N_("Query log file")); |
|
171 |
||
172 |
context( |
|
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")); |
|
176 |
||
177 |
context( |
|
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")); |
|
181 |
||
182 |
context( |
|
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")); |
|
186 |
||
187 |
context( |
|
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")); |
|
191 |
||
192 |
context( |
|
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")); |
|
196 |
||
197 |
context( |
|
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")); |
|
201 |
||
202 |
context( |
|
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")); |
|
206 |
||
207 |
}
|
|
208 |
||
209 |
/**
|
|
210 |
* @brief
|
|
211 |
* Add query_log plugin to Drizzle and initalize query_log system variables.
|
|
212 |
*
|
|
213 |
* @details
|
|
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
|
|
224 |
* update_file().
|
|
225 |
*
|
|
226 |
* @retval 0 Success
|
|
227 |
*/
|
|
228 |
static int init(drizzled::module::Context &context) |
|
229 |
{
|
|
230 |
const module::option_map &vm= context.getOptions(); |
|
231 |
||
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()); |
|
236 |
||
237 |
// Plug into Drizzle!
|
|
238 |
context.add(query_log); |
|
239 |
||
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)); |
|
245 |
||
246 |
context.registerVariable( |
|
247 |
new sys_var_bool_ptr( |
|
248 |
"file_enabled", &query_log->sysvar_file_enabled, &update_file_enabled)); |
|
249 |
||
250 |
context.registerVariable( |
|
251 |
new sys_var_std_string( |
|
252 |
"file", query_log->sysvar_file, NULL, &update_file)); |
|
253 |
||
254 |
context.registerVariable( |
|
255 |
new sys_var_constrained_value<uint32_t>( |
|
256 |
"threshold_execution_time", query_log->sysvar_threshold_execution_time)); |
|
257 |
||
258 |
context.registerVariable( |
|
259 |
new sys_var_constrained_value<uint32_t>( |
|
260 |
"threshold_lock_time", query_log->sysvar_threshold_lock_time)); |
|
261 |
||
262 |
context.registerVariable( |
|
263 |
new sys_var_constrained_value<uint32_t>( |
|
264 |
"threshold_rows_examined", query_log->sysvar_threshold_rows_examined)); |
|
265 |
||
266 |
context.registerVariable( |
|
267 |
new sys_var_constrained_value<uint32_t>( |
|
268 |
"threshold_rows_sent", query_log->sysvar_threshold_rows_sent)); |
|
269 |
||
270 |
context.registerVariable( |
|
271 |
new sys_var_constrained_value<uint32_t>( |
|
272 |
"threshold_tmp_tables", query_log->sysvar_threshold_tmp_tables)); |
|
273 |
||
274 |
context.registerVariable( |
|
275 |
new sys_var_constrained_value<uint32_t>( |
|
276 |
"threshold_warnings", query_log->sysvar_threshold_warnings)); |
|
277 |
||
278 |
context.registerVariable( |
|
279 |
new sys_var_constrained_value<uint32_t>( |
|
280 |
"threshold_session_time", query_log->sysvar_threshold_session_time)); |
|
281 |
||
282 |
return 0; // success |
|
283 |
}
|
|
284 |
||
285 |
} /* namespace drizzle_plugin */ |
|
286 |
||
287 |
DRIZZLE_PLUGIN(drizzle_plugin::init, NULL, drizzle_plugin::init_options); |