~drizzle-trunk/drizzle/development

1637.3.1 by Mark Atwood
new syslog module, with plugins for query log, error message, and SYSLOG() function
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2009 Sun Microsystems
5
 *  Copyright (C) 2010 Mark Atwood
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; version 2 of the License.
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
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
 */
20
21
#include "config.h"
22
23
#include <drizzled/gettext.h>
24
#include <drizzled/session.h>
25
26
#include <stdarg.h>
27
#include <limits.h>
28
#include <sys/time.h>
29
#include <sys/types.h>
30
#include <sys/stat.h>
31
#include <fcntl.h>
32
33
#include "logging.h"
34
#include "wrap.h"
35
36
using namespace drizzled;
37
38
/* stolen from mysys/my_getsystime
39
   until the Session has a good utime "now" we can use
40
   will have to use this instead */
41
42
static uint64_t get_microtime()
43
{
44
#if defined(HAVE_GETHRTIME)
45
  return gethrtime()/1000;
46
#else
47
  uint64_t newtime;
48
  struct timeval t;
49
  /* loop is because gettimeofday may fail on some systems */
50
  while (gettimeofday(&t, NULL) != 0) {}
51
  newtime= (uint64_t)t.tv_sec * 1000000 + t.tv_usec;
52
  return newtime;
53
#endif
54
}
55
56
Logging_syslog::Logging_syslog()
57
  : drizzled::plugin::Logging("Logging_syslog")
58
{
59
  syslog_facility= WrapSyslog::getFacilityByName(syslog_module::sysvar_facility);
60
  if (syslog_facility < 0)
61
  {
62
    errmsg_printf(ERRMSG_LVL_WARN,
63
                  _("syslog facility \"%s\" not known, using \"local0\""),
64
                  syslog_module::sysvar_facility);
65
    syslog_facility= WrapSyslog::getFacilityByName("local0");
66
  }
67
68
  syslog_priority= WrapSyslog::getPriorityByName(syslog_module::sysvar_logging_priority);
69
  if (syslog_priority < 0)
70
  {
71
    errmsg_printf(ERRMSG_LVL_WARN,
72
                  _("syslog priority \"%s\" not known, using \"info\""),
73
                  syslog_module::sysvar_logging_priority);
74
    syslog_priority= WrapSyslog::getPriorityByName("info");
75
  }
76
77
  WrapSyslog::singleton().openlog(syslog_module::sysvar_ident);
78
}
79
80
81
bool Logging_syslog::post (Session *session)
82
{
83
  assert(session != NULL);
84
85
  if (syslog_module::sysvar_logging_enable == false)
86
    return false;
87
  
88
  // return if query was not too small
89
  if (session->sent_row_count < syslog_module::sysvar_logging_threshold_big_resultset)
90
    return false;
91
  if (session->examined_row_count < syslog_module::sysvar_logging_threshold_big_examined)
92
    return false;
93
  
94
  /* TODO, the session object should have a "utime command completed"
95
     inside itself, so be more accurate, and so this doesnt have to
96
     keep calling current_utime, which can be slow */
97
  
98
  uint64_t t_mark= get_microtime();
99
100
  // return if query was not too slow
101
  if ((t_mark - session->start_utime) < syslog_module::sysvar_logging_threshold_slow)
102
    return false;
103
  
104
  /* to avoid trying to printf %s something that is potentially NULL */
105
  
106
  const char *dbs= session->db.empty() ? "" : session->db.c_str();
107
  
108
  const char *qys= (! session->getQueryString().empty()) ? session->getQueryString().c_str() : "";
109
  int qyl= 0;
110
  if (qys)
111
    qyl= session->getQueryLength();
112
113
  WrapSyslog::singleton()
114
    .log(syslog_facility, syslog_priority,
115
         "thread_id=%ld query_id=%ld"
116
         " db=\"%.*s\""
117
         " query=\"%.*s\""
118
         " command=\"%.*s\""
119
         " t_connect=%lld t_start=%lld t_lock=%lld"
120
         " rows_sent=%ld rows_examined=%ld"
121
         " tmp_table=%ld total_warn_count=%ld\n",
122
         (unsigned long) session->thread_id,
123
         (unsigned long) session->getQueryId(),
124
         (int) session->db.length(), dbs,
125
         qyl, qys,
126
         (int) command_name[session->command].length,
127
         command_name[session->command].str,
128
         (unsigned long long) (t_mark - session->getConnectMicroseconds()),
129
         (unsigned long long) (t_mark - session->start_utime),
130
         (unsigned long long) (t_mark - session->utime_after_lock),
131
         (unsigned long) session->sent_row_count,
132
         (unsigned long) session->examined_row_count,
133
         (unsigned long) session->tmp_table,
134
         (unsigned long) session->total_warn_count);
135
  
136
    return false;
137
}