21 #include <drizzled/plugin.h>
22 #include <drizzled/plugin/logging.h>
23 #include <drizzled/gettext.h>
24 #include <drizzled/session.h>
25 #include <drizzled/session/times.h>
26 #include <drizzled/sql_parse.h>
30 #include <sys/types.h>
34 #include <boost/format.hpp>
35 #include <boost/program_options.hpp>
40 namespace po= boost::program_options;
41 using namespace drizzled;
44 #define ESCAPE_CHAR '\\'
45 #define SEPARATOR_CHAR ','
47 namespace drizzle_plugin
50 static bool sysvar_logging_query_enable=
false;
72 static void quotify(
const string &src,
string &dst)
74 static const char hexit[]= {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
75 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f' };
76 string::const_iterator src_iter;
78 for (src_iter= src.begin(); src_iter < src.end(); ++src_iter)
80 if (static_cast<unsigned char>(*src_iter) > 0x7f)
82 dst.push_back(*src_iter);
84 else if (*src_iter == 0x00)
86 dst.push_back(ESCAPE_CHAR); dst.push_back(
'0');
88 else if (*src_iter == 0x07)
90 dst.push_back(ESCAPE_CHAR); dst.push_back(
'a');
92 else if (*src_iter == 0x08)
94 dst.push_back(ESCAPE_CHAR); dst.push_back(
'b');
96 else if (*src_iter == 0x09)
98 dst.push_back(ESCAPE_CHAR); dst.push_back(
't');
100 else if (*src_iter == 0x0a)
102 dst.push_back(ESCAPE_CHAR); dst.push_back(
'n');
104 else if (*src_iter == 0x0b)
106 dst.push_back(ESCAPE_CHAR); dst.push_back(
'v');
108 else if (*src_iter == 0x0c)
110 dst.push_back(ESCAPE_CHAR); dst.push_back(
'f');
112 else if (*src_iter == 0x0d)
114 dst.push_back(ESCAPE_CHAR); dst.push_back(
'r');
116 else if (*src_iter == 0x1b)
118 dst.push_back(ESCAPE_CHAR); dst.push_back(
'e');
120 else if (*src_iter == 0x22)
122 dst.push_back(ESCAPE_CHAR); dst.push_back(0x22);
124 else if (*src_iter == SEPARATOR_CHAR)
126 dst.push_back(ESCAPE_CHAR); dst.push_back(SEPARATOR_CHAR);
128 else if (*src_iter == ESCAPE_CHAR)
130 dst.push_back(ESCAPE_CHAR); dst.push_back(ESCAPE_CHAR);
132 else if ((*src_iter < 0x20) || (*src_iter == 0x7F))
134 dst.push_back(ESCAPE_CHAR);
136 dst.push_back(hexit[(*src_iter >> 4) & 0x0f]);
137 dst.push_back(hexit[*src_iter & 0x0f]);
141 dst.push_back(*src_iter);
149 const std::string _filename;
150 const std::string _query_pcre;
161 const std::string &query_pcre) :
162 drizzled::plugin::Logging(
"csv_query_log"),
164 _query_pcre(query_pcre),
165 fd(-1), re(NULL), pe(NULL),
166 formatter(
"%1%,%2%,%3%,\"%4%\",\"%5%\",\"%6%\",%7%,%8%,"
167 "%9%,%10%,%11%,%12%,%13%,%14%,\"%15%\"\n")
171 if (_filename.empty())
174 fd= open(_filename.c_str(),
175 O_WRONLY | O_APPEND | O_CREAT,
180 sql_perror( _(
"fail open()"), _filename);
184 if (not _query_pcre.empty())
186 const char *this_pcre_error;
187 int this_pcre_erroffset;
188 re= pcre_compile(_query_pcre.c_str(), 0, &this_pcre_error,
189 &this_pcre_erroffset, NULL);
190 pe= pcre_study(re, 0, &this_pcre_error);
213 virtual bool post (
Session *session)
217 assert(session != NULL);
230 if (sysvar_logging_query_enable ==
false)
232 if (session->
sent_row_count < sysvar_logging_query_threshold_big_resultset.get())
242 uint64_t t_mark= session->times.getCurrentTimestamp(
false);
244 if (session->times.getElapsedTime() < sysvar_logging_query_threshold_slow.get())
248 if (query_string == NULL)
256 this_pcre_rc= pcre_exec(re, pe, query_string->c_str(), query_string->length(), 0, 0, NULL, 0);
257 if (this_pcre_rc < 0)
266 qs.reserve(query_string->length());
268 quotify(*query_string, qs);
271 util::string::ptr schema(session->schema());
275 % (schema ? schema->c_str() :
"")
277 % getCommandName(session->
command)
278 % (t_mark - session->times.getConnectMicroseconds())
279 % session->times.getElapsedTime()
280 % (t_mark - session->times.utime_after_lock)
284 % session->total_warn_count
286 % getServerHostname();
288 string msgbuf= formatter.str();
291 wrv= write(fd, msgbuf.c_str(), msgbuf.length());
292 assert(wrv == msgbuf.length());
302 if (vm.count(
"filename"))
304 context.add(
new Logging_query(vm[
"filename"].as<string>(),
305 vm[
"pcre"].as<string>()));
306 context.registerVariable(
new sys_var_bool_ptr(
"enable", &sysvar_logging_query_enable));
320 po::value<bool>(&sysvar_logging_query_enable)->default_value(
false)->zero_tokens(),
321 _(
"Enable logging to CSV file"));
324 _(
"File to log to"));
326 po::value<string>()->default_value(
""),
327 _(
"PCRE to match the query against"));
328 context(
"threshold-slow",
329 po::value<uint32_constraint>(&sysvar_logging_query_threshold_slow)->default_value(0),
330 _(
"Threshold for logging slow queries, in microseconds"));
331 context(
"threshold-big-resultset",
332 po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_resultset)->default_value(0),
333 _(
"Threshold for logging big queries, for rows returned"));
334 context(
"threshold-big-examined",
335 po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_examined)->default_value(0),
336 _(
"Threshold for logging big queries, for rows examined"));
341 DRIZZLE_DECLARE_PLUGIN
347 N_(
"Logs queries to a CSV file"),
349 drizzle_plugin::logging_query_plugin_init,
351 drizzle_plugin::init_options
353 DRIZZLE_DECLARE_PLUGIN_END;
ha_rows examined_row_count
An Proxy Wrapper around boost::program_options::variables_map.
boost::shared_ptr< const std::string > QueryString
query_id_t getQueryId() const
enum_server_command command
uint32_t getServerId() const