~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
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
20
#include <config.h>
2239.1.6 by Olaf van der Spek
Refactor includes
21
#include <drizzled/plugin.h>
1130.1.1 by Monty Taylor
Merged in plugin-slot-reorg patches.
22
#include <drizzled/plugin/logging.h>
549 by Monty Taylor
Took gettext.h out of header files.
23
#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.
24
#include <drizzled/session.h>
2269.1.4 by Olaf van der Spek
Session Times
25
#include <drizzled/session/times.h>
2227.4.3 by Olaf van der Spek
Remove unnecessary statement.h include
26
#include <drizzled/sql_parse.h>
1076.1.1 by Trond Norbye
Use PCRE_HEADER instead of <pcre.h>
27
#include PCRE_HEADER
1259.7.4 by Monty Taylor
Fixed namespace and include issues in some plugins we hadn't been building.
28
#include <limits.h>
29
#include <sys/time.h>
30
#include <sys/types.h>
31
#include <sys/stat.h>
32
#include <fcntl.h>
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
33
#include <string>
34
#include <boost/format.hpp>
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
35
#include <boost/program_options.hpp>
36
#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
37
#include <cstdio>
1702.3.3 by LinuxJedi
Fix errors in FreeBSD build
38
#include <cerrno>
1259.7.4 by Monty Taylor
Fixed namespace and include issues in some plugins we hadn't been building.
39
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
40
namespace po= boost::program_options;
1259.7.4 by Monty Taylor
Fixed namespace and include issues in some plugins we hadn't been building.
41
using namespace drizzled;
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
42
using namespace std;
383.6.1 by Mark Atwood
add pluggable logging
43
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
44
#define ESCAPE_CHAR      '\\'
45
#define SEPARATOR_CHAR   ','
383.6.3 by Mark Atwood
more work on plugable logging
46
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
47
namespace drizzle_plugin
48
{
49
812.1.6 by Mark Atwood
logging to syslog
50
static bool sysvar_logging_query_enable= false;
1039.4.5 by Mark Atwood
add PCRE matching to logging to file
51
/* 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.
52
static uint32_constraint sysvar_logging_query_threshold_slow;
53
static uint32_constraint sysvar_logging_query_threshold_big_resultset;
54
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
55
812.1.1 by Mark Atwood
fixup logging plugin, make it compile in, and make it do CSV
56
/* quote a string to be safe to include in a CSV line
57
   that means backslash quoting all commas, doublequotes, backslashes,
58
   and all the ASCII unprintable characters
59
   as long as we pass the high-bit bytes unchanged
60
   this is safe to do to a UTF8 string
812.1.6 by Mark Atwood
logging to syslog
61
   we dont allow overrunning the targetbuffer
62
   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
63
64
   TODO consider remapping the unprintables instead to "Printable
65
   Representation", the Unicode characters from the area U+2400 to
66
   U+2421 reserved for representing control characters when it is
67
   necessary to print or display them rather than have them perform
68
   their intended function.
69
70
*/
71
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
72
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
73
{
779.5.1 by Monty Taylor
Merged Mark.
74
  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
75
			  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
76
  string::const_iterator src_iter;
2227.4.3 by Olaf van der Spek
Remove unnecessary statement.h include
77
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
78
  for (src_iter= src.begin(); src_iter < src.end(); ++src_iter)
812.1.3 by Mark Atwood
fix style
79
  {
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
80
    if (static_cast<unsigned char>(*src_iter) > 0x7f)
81
    {
82
      dst.push_back(*src_iter);
83
    }
84
    else if (*src_iter == 0x00)  // null
85
    {
86
      dst.push_back(ESCAPE_CHAR); dst.push_back('0');
87
    }
88
    else if (*src_iter == 0x07)  // bell
89
    {
90
      dst.push_back(ESCAPE_CHAR); dst.push_back('a');
91
    }
92
    else if (*src_iter == 0x08)  // backspace
93
    {
94
      dst.push_back(ESCAPE_CHAR); dst.push_back('b');
95
    }
96
    else if (*src_iter == 0x09)  // horiz tab
97
    {
98
      dst.push_back(ESCAPE_CHAR); dst.push_back('t');
99
    }
100
    else if (*src_iter == 0x0a)  // line feed
101
    {
102
      dst.push_back(ESCAPE_CHAR); dst.push_back('n');
103
    }
104
    else if (*src_iter == 0x0b)  // vert tab
105
    {
106
      dst.push_back(ESCAPE_CHAR); dst.push_back('v');
107
    }
108
    else if (*src_iter == 0x0c)  // formfeed
109
    {
110
      dst.push_back(ESCAPE_CHAR); dst.push_back('f');
111
    }
112
    else if (*src_iter == 0x0d)  // carrage return
113
    {
114
      dst.push_back(ESCAPE_CHAR); dst.push_back('r');
115
    }
116
    else if (*src_iter == 0x1b)  // escape
117
    {
118
      dst.push_back(ESCAPE_CHAR); dst.push_back('e');
119
    }
120
    else if (*src_iter == 0x22)  // quotation mark
121
    {
122
      dst.push_back(ESCAPE_CHAR); dst.push_back(0x22);
123
    }
124
    else if (*src_iter == SEPARATOR_CHAR)
125
    {
126
      dst.push_back(ESCAPE_CHAR); dst.push_back(SEPARATOR_CHAR);
127
    }
128
    else if (*src_iter == ESCAPE_CHAR)
129
    {
130
      dst.push_back(ESCAPE_CHAR); dst.push_back(ESCAPE_CHAR);
131
    }
132
    else if ((*src_iter < 0x20) || (*src_iter == 0x7F))  // other unprintable ASCII
133
    {
134
      dst.push_back(ESCAPE_CHAR);
135
      dst.push_back('x');
136
      dst.push_back(hexit[(*src_iter >> 4) & 0x0f]);
137
      dst.push_back(hexit[*src_iter & 0x0f]);
812.1.3 by Mark Atwood
fix style
138
    }
139
    else  // everything else
140
    {
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
141
      dst.push_back(*src_iter);
812.1.3 by Mark Atwood
fix style
142
    }
812.1.1 by Mark Atwood
fixup logging plugin, make it compile in, and make it do CSV
143
  }
144
}
145
146
1130.1.1 by Monty Taylor
Merged in plugin-slot-reorg patches.
147
class Logging_query: public drizzled::plugin::Logging
958.1.1 by Monty Taylor
Made logging plugin class based.
148
{
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
149
  const std::string _filename;
150
  const std::string _query_pcre;
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
151
  int fd;
152
  pcre *re;
153
  pcre_extra *pe;
154
1607.1.2 by David Shrewsbury
Made the boost::format object reusable.
155
  /** Format of the output string */
156
  boost::format formatter;
157
968.2.33 by Monty Taylor
Removed plugin_foreach from logging_handler.
158
public:
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
159
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
160
  Logging_query(const std::string &filename,
161
                const std::string &query_pcre) :
162
    drizzled::plugin::Logging("Logging_query"),
163
    _filename(filename),
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")
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
168
  {
169
170
    /* if there is no destination filename, dont bother doing anything */
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
171
    if (_filename.empty())
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
172
      return;
173
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
174
    fd= open(_filename.c_str(),
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
175
             O_WRONLY | O_APPEND | O_CREAT,
176
             S_IRUSR|S_IWUSR);
2126.3.3 by Brian Aker
Merge in error message rework. Many error messages are fixed in this patch.
177
1039.4.6 by Mark Atwood
make logging_query be more C++ ish
178
    if (fd < 0)
179
    {
2126.3.3 by Brian Aker
Merge in error message rework. Many error messages are fixed in this patch.
180
      sql_perror( _("fail open()"), _filename);
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
2040.4.3 by Brian Aker
Scale down the calls to universal_time().
237
    /*
238
      TODO, the session object should have a "utime command completed"
239
      inside itself, so be more accurate, and so this doesnt have to
240
      keep calling current_utime, which can be slow.
241
    */
2269.1.5 by Olaf van der Spek
Session Times
242
    uint64_t t_mark= session->times.getCurrentTimestamp(false);
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.
243
2269.1.6 by Olaf van der Spek
Session Times
244
    if (session->times.getElapsedTime() < sysvar_logging_query_threshold_slow.get())
958.1.1 by Monty Taylor
Made logging plugin class based.
245
      return false;
1039.4.5 by Mark Atwood
add PCRE matching to logging to file
246
1921.4.13 by Brian Aker
Fix issue where session info might not be correct.
247
    Session::QueryString query_string(session->getQueryString());
2194.7.2 by Monty Taylor
Fixed an assumption that the query string would always be valid.
248
    if (query_string == NULL)
249
    {
250
      return false;
251
    }
252
1039.4.5 by Mark Atwood
add PCRE matching to logging to file
253
    if (re)
254
    {
255
      int this_pcre_rc;
1921.4.13 by Brian Aker
Fix issue where session info might not be correct.
256
      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
257
      if (this_pcre_rc < 0)
258
        return false;
259
    }
260
958.1.1 by Monty Taylor
Made logging plugin class based.
261
    // buffer to quotify the query
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
262
    string qs;
2227.4.3 by Olaf van der Spek
Remove unnecessary statement.h include
263
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
264
    // Since quotify() builds the quoted string incrementally, we can
265
    // 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.
266
    qs.reserve(query_string->length());
2227.4.3 by Olaf van der Spek
Remove unnecessary statement.h include
267
1921.4.13 by Brian Aker
Fix issue where session info might not be correct.
268
    quotify(*query_string, qs);
2227.4.3 by Olaf van der Spek
Remove unnecessary statement.h include
269
958.1.1 by Monty Taylor
Made logging plugin class based.
270
    // to avoid trying to printf %s something that is potentially NULL
2269.1.7 by Olaf van der Spek
Use util::string::ptr
271
    util::string::ptr schema(session->schema());
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
272
    formatter % t_mark
273
              % session->thread_id
274
              % session->getQueryId()
2269.1.6 by Olaf van der Spek
Session Times
275
              % (schema ? schema->c_str() : "")
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
276
              % qs
2119.4.1 by Monty Taylor
Turns on -fvisibility=hidden by default. Symbols intended to be used by
277
              % getCommandName(session->command)
2269.1.6 by Olaf van der Spek
Session Times
278
              % (t_mark - session->times.getConnectMicroseconds())
279
              % session->times.getElapsedTime()
2269.1.4 by Olaf van der Spek
Session Times
280
              % (t_mark - session->times.utime_after_lock)
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
281
              % session->sent_row_count
282
              % session->examined_row_count
283
              % session->tmp_table
284
              % session->total_warn_count
285
              % session->getServerId()
2183.1.2 by Monty Taylor
A slew of tiny meaningless changes.
286
              % getServerHostname();
1607.1.1 by David Shrewsbury
Replace static buffers with std::string.
287
288
    string msgbuf= formatter.str();
289
958.1.1 by Monty Taylor
Made logging plugin class based.
290
    // 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.
291
    wrv= write(fd, msgbuf.c_str(), msgbuf.length());
292
    assert(wrv == msgbuf.length());
293
958.1.1 by Monty Taylor
Made logging plugin class based.
294
    return false;
295
  }
296
};
383.6.1 by Mark Atwood
add pluggable logging
297
1530.2.6 by Monty Taylor
Moved plugin::Context to module::Context.
298
static int logging_query_plugin_init(drizzled::module::Context &context)
383.6.1 by Mark Atwood
add pluggable logging
299
{
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
300
  const module::option_map &vm= context.getOptions();
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
301
2252.1.28 by Olaf van der Spek
Refactor Program Options usage
302
  if (vm.count("filename"))
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
303
  {
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));
307
    context.registerVariable(new sys_var_const_string_val("filename", vm["filename"].as<string>()));
308
    context.registerVariable(new sys_var_const_string_val("pcre", vm["pcre"].as<string>()));
309
    context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_slow", sysvar_logging_query_threshold_slow));
310
    context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_big_resultset", sysvar_logging_query_threshold_big_resultset));
311
    context.registerVariable(new sys_var_constrained_value<uint32_t>("threshold_big_examined", sysvar_logging_query_threshold_big_examined));
312
  }
383.6.1 by Mark Atwood
add pluggable logging
313
314
  return 0;
315
}
316
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
317
static void init_options(drizzled::module::option_context &context)
318
{
319
  context("enable",
320
          po::value<bool>(&sysvar_logging_query_enable)->default_value(false)->zero_tokens(),
2068.4.1 by Andrew Hutchings
Fix intl domain
321
          _("Enable logging to CSV file"));
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
322
  context("filename",
323
          po::value<string>(),
2068.4.1 by Andrew Hutchings
Fix intl domain
324
          _("File to log to"));
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
325
  context("pcre",
326
          po::value<string>()->default_value(""),
2068.4.1 by Andrew Hutchings
Fix intl domain
327
          _("PCRE to match the query against"));
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
328
  context("threshold-slow",
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
329
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_slow)->default_value(0),
2068.4.1 by Andrew Hutchings
Fix intl domain
330
          _("Threshold for logging slow queries, in microseconds"));
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
331
  context("threshold-big-resultset",
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
332
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_resultset)->default_value(0),
2068.4.1 by Andrew Hutchings
Fix intl domain
333
          _("Threshold for logging big queries, for rows returned"));
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
334
  context("threshold-big-examined",
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
335
          po::value<uint32_constraint>(&sysvar_logging_query_threshold_big_examined)->default_value(0),
2068.4.1 by Andrew Hutchings
Fix intl domain
336
          _("Threshold for logging big queries, for rows examined"));
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
337
}
338
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
339
} /* namespace drizzle_plugin */
438.2.2 by Mark Atwood
sysvar for filename for pluggable query logging to log to
340
1228.1.5 by Monty Taylor
Merged in some naming things.
341
DRIZZLE_DECLARE_PLUGIN
383.6.1 by Mark Atwood
add pluggable logging
342
{
1241.10.2 by Monty Taylor
Added support for embedding the drizzle version number in the plugin file.
343
  DRIZZLE_VERSION_ID,
1660.7.1 by Vijay Samuel
Merge re factored commandline for logging_query using boost::program_options
344
  "logging-query",
812.1.6 by Mark Atwood
logging to syslog
345
  "0.2",
383.6.1 by Mark Atwood
add pluggable logging
346
  "Mark Atwood <mark@fallenpegasus.com>",
812.1.6 by Mark Atwood
logging to syslog
347
  N_("Log queries to a CSV file"),
383.6.1 by Mark Atwood
add pluggable logging
348
  PLUGIN_LICENSE_GPL,
1964.2.17 by Monty Taylor
Did logging_query. Fixed rabbitmq.
349
  drizzle_plugin::logging_query_plugin_init,
350
  NULL,
351
  drizzle_plugin::init_options
383.6.1 by Mark Atwood
add pluggable logging
352
}
1228.1.5 by Monty Taylor
Merged in some naming things.
353
DRIZZLE_DECLARE_PLUGIN_END;