Drizzled Public API Documentation

logging_stats.cc

00001 /*
00002  * Copyright (C) 2010 Joseph Daly <skinny.moey@gmail.com>
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *   * Redistributions of source code must retain the above copyright notice,
00009  *     this list of conditions and the following disclaimer.
00010  *   * Redistributions in binary form must reproduce the above copyright notice,
00011  *     this list of conditions and the following disclaimer in the documentation
00012  *     and/or other materials provided with the distribution.
00013  *   * Neither the name of Joseph Daly nor the names of its contributors
00014  *     may be used to endorse or promote products derived from this software
00015  *     without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
00027  * THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00087 #include <config.h>
00088 #include "user_commands.h"
00089 #include "status_vars.h"
00090 #include "global_stats.h"
00091 #include "logging_stats.h"
00092 #include "status_tool.h"
00093 #include "stats_schema.h"
00094 #include <boost/program_options.hpp>
00095 #include <drizzled/module/option_map.h>
00096 #include <drizzled/session.h>
00097 #include <drizzled/sql_lex.h>
00098 
00099 namespace po= boost::program_options;
00100 using namespace drizzled;
00101 using namespace plugin;
00102 using namespace std;
00103 
00104 static bool sysvar_logging_stats_enabled= true;
00105 
00106 typedef constrained_check<uint32_t, 50000, 10> scoreboard_size_constraint;
00107 static scoreboard_size_constraint sysvar_logging_stats_scoreboard_size;
00108 
00109 typedef constrained_check<uint32_t, 50000, 100> max_user_count_constraint;
00110 static max_user_count_constraint sysvar_logging_stats_max_user_count;
00111 
00112 typedef constrained_check<uint32_t, 500, 5> bucket_count_constraint;
00113 static bucket_count_constraint sysvar_logging_stats_bucket_count;
00114 
00115 LoggingStats::LoggingStats(string name_arg) : Logging(name_arg)
00116 {
00117   current_scoreboard= new Scoreboard(sysvar_logging_stats_scoreboard_size, 
00118                                      sysvar_logging_stats_bucket_count);
00119 
00120   cumulative_stats= new CumulativeStats(sysvar_logging_stats_max_user_count); 
00121 }
00122 
00123 LoggingStats::~LoggingStats()
00124 {
00125   delete current_scoreboard;
00126   delete cumulative_stats;
00127 }
00128 
00129 void LoggingStats::updateCurrentScoreboard(ScoreboardSlot *scoreboard_slot,
00130                                            Session *session)
00131 {
00132   enum_sql_command sql_command= session->lex().sql_command;
00133 
00134   scoreboard_slot->getUserCommands()->logCommand(sql_command);
00135 
00136   /* If a flush occurred copy over values before setting new values */
00137   if (scoreboard_slot->getStatusVars()->hasBeenFlushed(session))
00138   {
00139     cumulative_stats->logGlobalStatusVars(scoreboard_slot);
00140   }
00141   scoreboard_slot->getStatusVars()->logStatusVar(session);
00142 }
00143 
00144 bool LoggingStats::resetGlobalScoreboard()
00145 {
00146   cumulative_stats->getGlobalStatusVars()->reset();
00147   cumulative_stats->getGlobalStats()->getUserCommands()->reset();
00148 
00149   ScoreBoardVectors *vector_of_scoreboard_vectors=
00150     current_scoreboard->getVectorOfScoreboardVectors();
00151 
00152   ScoreBoardVectors::iterator v_of_scoreboard_v_begin_it= vector_of_scoreboard_vectors->begin();
00153 
00154   ScoreBoardVectors::iterator v_of_scoreboard_v_end_it= vector_of_scoreboard_vectors->end();
00155 
00156   for (; v_of_scoreboard_v_begin_it != v_of_scoreboard_v_end_it; ++v_of_scoreboard_v_begin_it)
00157   {
00158     std::vector<ScoreboardSlot* > *scoreboard_vector= *v_of_scoreboard_v_begin_it;
00159 
00160     std::vector<ScoreboardSlot* >::iterator scoreboard_vector_it= scoreboard_vector->begin();
00161     std::vector<ScoreboardSlot* >::iterator scoreboard_vector_end= scoreboard_vector->end();
00162     for (; scoreboard_vector_it != scoreboard_vector_end; ++scoreboard_vector_it)
00163     {
00164       ScoreboardSlot *scoreboard_slot= *scoreboard_vector_it;
00165       scoreboard_slot->getStatusVars()->reset();
00166       scoreboard_slot->getUserCommands()->reset();
00167     }
00168   }
00169 
00170   return false;
00171 }
00172 
00173 bool LoggingStats::post(Session *session)
00174 {
00175   if (! isEnabled() || (session->getSessionId() == 0))
00176   {
00177     return false;
00178   }
00179 
00180   ScoreboardSlot *scoreboard_slot= current_scoreboard->findScoreboardSlotToLog(session);
00181 
00182   /* Its possible that the scoreboard is full with active sessions in which case 
00183      this could be null */
00184   if (scoreboard_slot)
00185   {
00186     updateCurrentScoreboard(scoreboard_slot, session);
00187   }
00188   return false;
00189 }
00190 
00191 bool LoggingStats::postEnd(Session *session)
00192 {
00193   if (! isEnabled() || (session->getSessionId() == 0))
00194   {
00195     return false;
00196   }
00197 
00198   bool isInScoreboard= false;
00199   ScoreboardSlot *scoreboard_slot= current_scoreboard->findOurScoreboardSlot(session);
00200 
00201   if (scoreboard_slot)
00202   {
00203     isInScoreboard= true;
00204   } 
00205   else 
00206   { 
00207     /* the session did not have a slot reserved, that could be because the scoreboard was
00208        full, but most likely its a failed authentication so post() is never called where
00209        the slot is assigned. Log the global status values below, and if the user has a slot
00210        log to it, but do not reserve a new slot for a user. If it was a failed authentication
00211        the scoreboard would be filled up quickly with invalid users. 
00212     */
00213     scoreboard_slot= new ScoreboardSlot();
00214     scoreboard_slot->setUser(session->user()->username());
00215     scoreboard_slot->setIp(session->user()->address());
00216   }
00217 
00218   scoreboard_slot->getStatusVars()->logStatusVar(session);
00219   scoreboard_slot->getStatusVars()->getStatusVarCounters()->connection_time= session->getConnectSeconds(); 
00220 
00221   cumulative_stats->logUserStats(scoreboard_slot, isInScoreboard);
00222   cumulative_stats->logGlobalStats(scoreboard_slot);
00223   cumulative_stats->logGlobalStatusVars(scoreboard_slot);
00224 
00225   if (isInScoreboard)
00226   {
00227     scoreboard_slot->reset();
00228   } 
00229   else 
00230   {
00231     delete scoreboard_slot;
00232   } 
00233 
00234   return false;
00235 }
00236 
00237 /* Plugin initialization and system variables */
00238 
00239 static LoggingStats *logging_stats= NULL;
00240 
00241 static CurrentCommandsTool *current_commands_tool= NULL;
00242 
00243 static CumulativeCommandsTool *cumulative_commands_tool= NULL;
00244 
00245 static GlobalStatementsTool *global_statements_tool= NULL;
00246 
00247 static SessionStatementsTool *session_statements_tool= NULL;
00248 
00249 static StatusTool *global_status_tool= NULL;
00250 
00251 static StatusTool *session_status_tool= NULL;
00252 
00253 static CumulativeUserStatsTool *cumulative_user_stats_tool= NULL;
00254 
00255 static ScoreboardStatsTool *scoreboard_stats_tool= NULL;
00256 
00257 static void enable(Session *, sql_var_t)
00258 {
00259   if (logging_stats)
00260   {
00261     if (sysvar_logging_stats_enabled)
00262     {
00263       logging_stats->enable();
00264     }
00265     else
00266     {
00267       logging_stats->disable();
00268     }
00269   }
00270 }
00271 
00272 static bool initTable()
00273 {
00274   current_commands_tool= new(nothrow)CurrentCommandsTool(logging_stats);
00275 
00276   if (! current_commands_tool)
00277   {
00278     return true;
00279   }
00280 
00281   cumulative_commands_tool= new(nothrow)CumulativeCommandsTool(logging_stats);
00282 
00283   if (! cumulative_commands_tool)
00284   {
00285     return true;
00286   }
00287 
00288   global_statements_tool= new(nothrow)GlobalStatementsTool(logging_stats);
00289 
00290   if (! global_statements_tool)
00291   {
00292     return true;
00293   }
00294 
00295   session_statements_tool= new(nothrow)SessionStatementsTool(logging_stats);
00296 
00297   if (! session_statements_tool)
00298   {
00299     return true;
00300   }
00301 
00302   session_status_tool= new(nothrow)StatusTool(logging_stats, true);
00303 
00304   if (! session_status_tool)
00305   {
00306     return true;
00307   }
00308 
00309   global_status_tool= new(nothrow)StatusTool(logging_stats, false);
00310 
00311   if (! global_status_tool)
00312   {
00313     return true;
00314   }
00315 
00316   cumulative_user_stats_tool= new(nothrow)CumulativeUserStatsTool(logging_stats);
00317 
00318   if (! cumulative_user_stats_tool)
00319   {
00320     return true;
00321   }
00322 
00323   scoreboard_stats_tool= new(nothrow)ScoreboardStatsTool(logging_stats);
00324   
00325   if (! scoreboard_stats_tool)
00326   {
00327     return true;
00328   }
00329 
00330   return false;
00331 }
00332 
00333 static int init(drizzled::module::Context &context)
00334 {
00335   const module::option_map &vm= context.getOptions();
00336 
00337   sysvar_logging_stats_enabled= (vm.count("disable")) ? false : true;
00338 
00339   logging_stats= new LoggingStats("logging_stats");
00340 
00341   if (initTable())
00342   {
00343     return 1;
00344   }
00345 
00346   context.add(logging_stats);
00347   context.add(current_commands_tool);
00348   context.add(cumulative_commands_tool);
00349   context.add(global_statements_tool);
00350   context.add(session_statements_tool);
00351   context.add(session_status_tool);
00352   context.add(global_status_tool);
00353   context.add(cumulative_user_stats_tool);
00354   context.add(scoreboard_stats_tool);
00355 
00356   if (sysvar_logging_stats_enabled)
00357   {
00358     logging_stats->enable();
00359   }
00360 
00361   context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("max_user_count", sysvar_logging_stats_max_user_count));
00362   context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("bucket_count", sysvar_logging_stats_bucket_count));
00363   context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("scoreboard_size", sysvar_logging_stats_scoreboard_size));
00364   context.registerVariable(new sys_var_bool_ptr("enable", &sysvar_logging_stats_enabled, enable));
00365 
00366   return 0;
00367 }
00368 
00369 
00370 static void init_options(drizzled::module::option_context &context)
00371 {
00372   context("max-user-count",
00373           po::value<max_user_count_constraint>(&sysvar_logging_stats_max_user_count)->default_value(500),
00374           _("Max number of users that will be logged"));
00375   context("bucket-count",
00376           po::value<bucket_count_constraint>(&sysvar_logging_stats_bucket_count)->default_value(10),
00377           _("Max number of range locks to use for Scoreboard"));
00378   context("scoreboard-size",
00379           po::value<scoreboard_size_constraint>(&sysvar_logging_stats_scoreboard_size)->default_value(2000),
00380           _("Max number of concurrent sessions that will be logged"));
00381   context("disable", _("Enable Logging Statistics Collection"));
00382 }
00383 
00384 DRIZZLE_DECLARE_PLUGIN
00385 {
00386   DRIZZLE_VERSION_ID,
00387   "logging_stats",
00388   "0.1",
00389   "Joseph Daly",
00390   N_("User Statistics as DATA_DICTIONARY tables"),
00391   PLUGIN_LICENSE_BSD,
00392   init,   /* Plugin Init      */
00393   NULL, /* depends */
00394   init_options    /* config options   */
00395 }
00396 DRIZZLE_DECLARE_PLUGIN_END;