~drizzle-trunk/drizzle/development

499.2.14 by Mark Atwood
fixes as per MontyT's comments, prep for internationalization
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
499.2.10 by Mark Atwood
add editor format hints, and other useful metadata comments
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
499.2.14 by Mark Atwood
fixes as per MontyT's comments, prep for internationalization
3
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2008, 2009 Sun Microsystems, Inc.
499.2.10 by Mark Atwood
add editor format hints, and other useful metadata comments
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
 */
383.6.1 by Mark Atwood
add pluggable logging
19
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
20
#include "config.h"
1130.1.1 by Monty Taylor
Merged in plugin-slot-reorg patches.
21
#include <drizzled/plugin/logging.h>
549 by Monty Taylor
Took gettext.h out of header files.
22
#include <drizzled/gettext.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
23
#include <drizzled/session.h>
1076.1.1 by Trond Norbye
Use PCRE_HEADER instead of <pcre.h>
24
#include PCRE_HEADER
1259.7.4 by Monty Taylor
Fixed namespace and include issues in some plugins we hadn't been building.
25
#include <limits.h>
26
#include <sys/time.h>
27
#include <sys/types.h>
28
#include <sys/stat.h>
29
#include <fcntl.h>
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
30
#include <string>
31
#include <boost/format.hpp>
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
32
#include <boost/program_options.hpp>
33
#include <drizzled/module/option_map.h>
1502.3.1 by iwamatsu at nigauri
Add cstdio include to files needing it. Fixes the build on some debian
34
#include <cstdio>
1702.3.3 by LinuxJedi
Fix errors in FreeBSD build
35
#include <cerrno>
1259.7.4 by Monty Taylor
Fixed namespace and include issues in some plugins we hadn't been building.
36
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
37
namespace po= boost::program_options;
1259.7.4 by Monty Taylor
Fixed namespace and include issues in some plugins we hadn't been building.
38
using namespace drizzled;
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
39
using namespace std;
383.6.1 by Mark Atwood
add pluggable logging
40
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
41
#define ESCAPE_CHAR      '\\'
42
#define SEPARATOR_CHAR   ','
383.6.3 by Mark Atwood
more work on plugable logging
43
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
44
namespace drizzle_plugin
45
{
46
812.1.6 by Mark Atwood
logging to syslog
47
static bool sysvar_logging_query_enable= false;
1039.4.5 by Mark Atwood
add PCRE matching to logging to file
48
/* TODO fix these to not be unsigned long once we have sensible sys_var system */
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
49
static uint32_constraint sysvar_logging_query_threshold_slow;
50
static uint32_constraint sysvar_logging_query_threshold_big_resultset;
51
static uint32_constraint sysvar_logging_query_threshold_big_examined;
438.2.2 by Mark Atwood
sysvar for filename for pluggable query logging to log to
52
812.1.1 by Mark Atwood
fixup logging plugin, make it compile in, and make it do CSV
53
/* quote a string to be safe to include in a CSV line
54
   that means backslash quoting all commas, doublequotes, backslashes,
55
   and all the ASCII unprintable characters
56
   as long as we pass the high-bit bytes unchanged
57
   this is safe to do to a UTF8 string
812.1.6 by Mark Atwood
logging to syslog
58
   we dont allow overrunning the targetbuffer
59
   to avoid having a very long query overwrite memory
812.1.1 by Mark Atwood
fixup logging plugin, make it compile in, and make it do CSV
60
61
   TODO consider remapping the unprintables instead to "Printable
62
   Representation", the Unicode characters from the area U+2400 to
63
   U+2421 reserved for representing control characters when it is
64
   necessary to print or display them rather than have them perform
65
   their intended function.
66
67
*/
68
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
69
static void quotify(const string &src, string &dst)
812.1.1 by Mark Atwood
fixup logging plugin, make it compile in, and make it do CSV
70
{
779.5.1 by Monty Taylor
Merged Mark.
71
  static const char hexit[]= { '0', '1', '2', '3', '4', '5', '6', '7',
812.1.1 by Mark Atwood
fixup logging plugin, make it compile in, and make it do CSV
72
			  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
73
  string::const_iterator src_iter;
74
  
75
  for (src_iter= src.begin(); src_iter < src.end(); ++src_iter)
812.1.3 by Mark Atwood
fix style
76
  {
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
77
    if (static_cast<unsigned char>(*src_iter) > 0x7f)
78
    {
79
      dst.push_back(*src_iter);
80
    }
81
    else if (*src_iter == 0x00)  // null
82
    {
83
      dst.push_back(ESCAPE_CHAR); dst.push_back('0');
84
    }
85
    else if (*src_iter == 0x07)  // bell
86
    {
87
      dst.push_back(ESCAPE_CHAR); dst.push_back('a');
88
    }
89
    else if (*src_iter == 0x08)  // backspace
90
    {
91
      dst.push_back(ESCAPE_CHAR); dst.push_back('b');
92
    }
93
    else if (*src_iter == 0x09)  // horiz tab
94
    {
95
      dst.push_back(ESCAPE_CHAR); dst.push_back('t');
96
    }
97
    else if (*src_iter == 0x0a)  // line feed
98
    {
99
      dst.push_back(ESCAPE_CHAR); dst.push_back('n');
100
    }
101
    else if (*src_iter == 0x0b)  // vert tab
102
    {
103
      dst.push_back(ESCAPE_CHAR); dst.push_back('v');
104
    }
105
    else if (*src_iter == 0x0c)  // formfeed
106
    {
107
      dst.push_back(ESCAPE_CHAR); dst.push_back('f');
108
    }
109
    else if (*src_iter == 0x0d)  // carrage return
110
    {
111
      dst.push_back(ESCAPE_CHAR); dst.push_back('r');
112
    }
113
    else if (*src_iter == 0x1b)  // escape
114
    {
115
      dst.push_back(ESCAPE_CHAR); dst.push_back('e');
116
    }
117
    else if (*src_iter == 0x22)  // quotation mark
118
    {
119
      dst.push_back(ESCAPE_CHAR); dst.push_back(0x22);
120
    }
121
    else if (*src_iter == SEPARATOR_CHAR)
122
    {
123
      dst.push_back(ESCAPE_CHAR); dst.push_back(SEPARATOR_CHAR);
124
    }
125
    else if (*src_iter == ESCAPE_CHAR)
126
    {
127
      dst.push_back(ESCAPE_CHAR); dst.push_back(ESCAPE_CHAR);
128
    }
129
    else if ((*src_iter < 0x20) || (*src_iter == 0x7F))  // other unprintable ASCII
130
    {
131
      dst.push_back(ESCAPE_CHAR);
132
      dst.push_back('x');
133
      dst.push_back(hexit[(*src_iter >> 4) & 0x0f]);
134
      dst.push_back(hexit[*src_iter & 0x0f]);
812.1.3 by Mark Atwood
fix style
135
    }
136
    else  // everything else
137
    {
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
138
      dst.push_back(*src_iter);
812.1.3 by Mark Atwood
fix style
139
    }
812.1.1 by Mark Atwood
fixup logging plugin, make it compile in, and make it do CSV
140
  }
141
}
142
143
1130.1.1 by Monty Taylor
Merged in plugin-slot-reorg patches.
144
class Logging_query: public drizzled::plugin::Logging
958.1.1 by Monty Taylor
Made logging plugin class based.
145
{
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
146
  const std::string _filename;
147
  const std::string _query_pcre;
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
148
  int fd;
149
  pcre *re;
150
  pcre_extra *pe;
151
1607.1.2 by David Shrewsbury
Made the boost::format object reusable.
152
  /** Format of the output string */
153
  boost::format formatter;
154
968.2.33 by Monty Taylor
Removed plugin_foreach from logging_handler.
155
public:
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
156
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
157
  Logging_query(const std::string &filename,
158
                const std::string &query_pcre) :
159
    drizzled::plugin::Logging("Logging_query"),
160
    _filename(filename),
161
    _query_pcre(query_pcre),
162
    fd(-1), re(NULL), pe(NULL),
163
    formatter("%1%,%2%,%3%,\"%4%\",\"%5%\",\"%6%\",%7%,%8%,"
164
              "%9%,%10%,%11%,%12%,%13%,%14%,\"%15%\"\n")
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
165
  {
166
167
    /* if there is no destination filename, dont bother doing anything */
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
168
    if (_filename.empty())
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
169
      return;
170
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
171
    fd= open(_filename.c_str(),
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
172
             O_WRONLY | O_APPEND | O_CREAT,
173
             S_IRUSR|S_IWUSR);
174
    if (fd < 0)
175
    {
1702.3.2 by LinuxJedi
Migrate the rest of strerror to strerror_r
176
      char errmsg[STRERROR_MAX];
177
      strerror_r(errno, errmsg, sizeof(errmsg));
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
178
      errmsg_printf(ERRMSG_LVL_ERROR, _("fail open() fn=%s er=%s\n"),
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
179
                    _filename.c_str(),
1702.3.2 by LinuxJedi
Migrate the rest of strerror to strerror_r
180
                    errmsg);
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
181
      return;
182
    }
183
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
184
    if (not _query_pcre.empty())
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
185
    {
186
      const char *this_pcre_error;
187
      int this_pcre_erroffset;
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
188
      re= pcre_compile(_query_pcre.c_str(), 0, &this_pcre_error,
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
189
                       &this_pcre_erroffset, NULL);
190
      pe= pcre_study(re, 0, &this_pcre_error);
191
      /* TODO emit error messages if there is a problem */
192
    }
193
  }
968.2.33 by Monty Taylor
Removed plugin_foreach from logging_handler.
194
1039.4.8 by Mark Atwood
add destructor to logging_query, to close filehandle and clean up PCRE stuff
195
  ~Logging_query()
196
  {
197
    if (fd >= 0)
198
    {
199
      close(fd);
200
    }
201
202
    if (pe != NULL)
203
    {
204
      pcre_free(pe);
205
    }
206
207
    if (re != NULL)
208
    {
209
      pcre_free(re);
210
    }
211
  }
212
958.1.1 by Monty Taylor
Made logging plugin class based.
213
  virtual bool post (Session *session)
214
  {
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
215
    size_t wrv;
958.1.1 by Monty Taylor
Made logging plugin class based.
216
217
    assert(session != NULL);
218
219
    if (fd < 0)
220
      return false;
221
222
    /* Yes, we know that checking sysvar_logging_query_enable,
223
       sysvar_logging_query_threshold_big_resultset, and
224
       sysvar_logging_query_threshold_big_examined is not threadsafe,
225
       because some other thread might change these sysvars.  But we
226
       don't care.  We might start logging a little late as it spreads
227
       to other threads.  Big deal. */
228
229
    // return if not enabled or query was too fast or resultset was too small
230
    if (sysvar_logging_query_enable == false)
231
      return false;
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
232
    if (session->sent_row_count < sysvar_logging_query_threshold_big_resultset.get())
958.1.1 by Monty Taylor
Made logging plugin class based.
233
      return false;
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
234
    if (session->examined_row_count < sysvar_logging_query_threshold_big_examined.get())
958.1.1 by Monty Taylor
Made logging plugin class based.
235
      return false;
236
237
    /* TODO, the session object should have a "utime command completed"
238
       inside itself, so be more accurate, and so this doesnt have to
239
       keep calling current_utime, which can be slow */
240
  
1878.10.1 by Billy Earney
removed my_micro_time, my_micro_time_and_time, along with my_getsystime and replaced with boost:date_time for compatibility between OS.
241
    boost::posix_time::ptime mytime(boost::posix_time::microsec_clock::local_time());
242
    boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
243
    uint64_t t_mark= (mytime-epoch).total_microseconds();
244
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
245
    if ((t_mark - session->start_utime) < (sysvar_logging_query_threshold_slow.get()))
958.1.1 by Monty Taylor
Made logging plugin class based.
246
      return false;
1039.4.5 by Mark Atwood
add PCRE matching to logging to file
247
1921.4.13 by Brian Aker
Fix issue where session info might not be correct.
248
    Session::QueryString query_string(session->getQueryString());
1039.4.5 by Mark Atwood
add PCRE matching to logging to file
249
    if (re)
250
    {
251
      int this_pcre_rc;
1921.4.13 by Brian Aker
Fix issue where session info might not be correct.
252
      this_pcre_rc= pcre_exec(re, pe, query_string->c_str(), query_string->length(), 0, 0, NULL, 0);
1039.4.5 by Mark Atwood
add PCRE matching to logging to file
253
      if (this_pcre_rc < 0)
254
        return false;
255
    }
256
958.1.1 by Monty Taylor
Made logging plugin class based.
257
    // buffer to quotify the query
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
258
    string qs;
259
    
260
    // Since quotify() builds the quoted string incrementally, we can
261
    // avoid some reallocating if we reserve some space up front.
1921.4.13 by Brian Aker
Fix issue where session info might not be correct.
262
    qs.reserve(query_string->length());
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
263
    
1921.4.13 by Brian Aker
Fix issue where session info might not be correct.
264
    quotify(*query_string, qs);
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
265
    
958.1.1 by Monty Taylor
Made logging plugin class based.
266
    // to avoid trying to printf %s something that is potentially NULL
1976.5.2 by Brian Aker
This resolves the issue where one thread may be looking at schema while
267
    util::string::const_shared_ptr schema(session->schema());
268
    const char *dbs= (schema and not schema->empty()) ? schema->c_str() : "";
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
269
270
    formatter % t_mark
271
              % session->thread_id
272
              % session->getQueryId()
273
              % dbs
274
              % qs
275
              % command_name[session->command].str
276
              % (t_mark - session->getConnectMicroseconds())
277
              % (t_mark - session->start_utime)
278
              % (t_mark - session->utime_after_lock)
279
              % session->sent_row_count
280
              % session->examined_row_count
281
              % session->tmp_table
282
              % session->total_warn_count
283
              % session->getServerId()
284
              % glob_hostname;
285
286
    string msgbuf= formatter.str();
287
958.1.1 by Monty Taylor
Made logging plugin class based.
288
    // a single write has a kernel thread lock, thus no need mutex guard this
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
289
    wrv= write(fd, msgbuf.c_str(), msgbuf.length());
290
    assert(wrv == msgbuf.length());
291
958.1.1 by Monty Taylor
Made logging plugin class based.
292
    return false;
293
  }
294
};
383.6.1 by Mark Atwood
add pluggable logging
295
1530.2.6 by Monty Taylor
Moved plugin::Context to module::Context.
296
static int logging_query_plugin_init(drizzled::module::Context &context)
383.6.1 by Mark Atwood
add pluggable logging
297
{
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
298
299
  const module::option_map &vm= context.getOptions();
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
300
301
  if (vm.count("filename") > 0)
302
  {
303
    context.add(new Logging_query(vm["filename"].as<string>(),
304
                                  vm["pcre"].as<string>()));
305
    context.registerVariable(new sys_var_bool_ptr("enable", &sysvar_logging_query_enable));
306
    context.registerVariable(new sys_var_const_string_val("filename", vm["filename"].as<string>()));
307
    context.registerVariable(new sys_var_const_string_val("pcre", vm["pcre"].as<string>()));
308
    context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_slow", sysvar_logging_query_threshold_slow));
309
    context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_big_resultset", sysvar_logging_query_threshold_big_resultset));
310
    context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_big_examined", sysvar_logging_query_threshold_big_examined));
311
  }
383.6.1 by Mark Atwood
add pluggable logging
312
313
  return 0;
314
}
315
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
316
static void init_options(drizzled::module::option_context &context)
317
{
318
  context("enable",
319
          po::value<bool>(&sysvar_logging_query_enable)->default_value(false)->zero_tokens(),
320
          N_("Enable logging to CSV file"));
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
321
  context("filename",
322
          po::value<string>(),
323
          N_("File to log to"));
324
  context("pcre",
325
          po::value<string>()->default_value(""),
326
          N_("PCRE to match the query against"));
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
327
  context("threshold-slow",
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
328
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_slow)->default_value(0),
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
329
          N_("Threshold for logging slow queries, in microseconds"));
330
  context("threshold-big-resultset",
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
331
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_resultset)->default_value(0),
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
332
          N_("Threshold for logging big queries, for rows returned"));
333
  context("threshold-big-examined",
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
334
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_examined)->default_value(0),
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
335
          N_("Threshold for logging big queries, for rows examined"));
336
}
337
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
338
} /* namespace drizzle_plugin */
438.2.2 by Mark Atwood
sysvar for filename for pluggable query logging to log to
339
1228.1.5 by Monty Taylor
Merged in some naming things.
340
DRIZZLE_DECLARE_PLUGIN
383.6.1 by Mark Atwood
add pluggable logging
341
{
1241.10.2 by Monty Taylor
Added support for embedding the drizzle version number in the plugin file.
342
  DRIZZLE_VERSION_ID,
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
343
  "logging-query",
812.1.6 by Mark Atwood
logging to syslog
344
  "0.2",
383.6.1 by Mark Atwood
add pluggable logging
345
  "Mark Atwood <mark@fallenpegasus.com>",
812.1.6 by Mark Atwood
logging to syslog
346
  N_("Log queries to a CSV file"),
383.6.1 by Mark Atwood
add pluggable logging
347
  PLUGIN_LICENSE_GPL,
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
348
  drizzle_plugin::logging_query_plugin_init,
349
  NULL,
350
  drizzle_plugin::init_options
383.6.1 by Mark Atwood
add pluggable logging
351
}
1228.1.5 by Monty Taylor
Merged in some naming things.
352
DRIZZLE_DECLARE_PLUGIN_END;