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/session/times.h>
00098 #include <drizzled/sql_lex.h>
00099 #include <drizzled/statistics_variables.h>
00100 
00101 namespace po= boost::program_options;
00102 using namespace drizzled;
00103 using namespace plugin;
00104 using namespace std;
00105 
00106 static bool sysvar_logging_stats_enabled= true;
00107 
00108 typedef constrained_check<uint32_t, 50000, 10> scoreboard_size_constraint;
00109 static scoreboard_size_constraint sysvar_logging_stats_scoreboard_size;
00110 
00111 typedef constrained_check<uint32_t, 50000, 100> max_user_count_constraint;
00112 static max_user_count_constraint sysvar_logging_stats_max_user_count;
00113 
00114 typedef constrained_check<uint32_t, 500, 5> bucket_count_constraint;
00115 static bucket_count_constraint sysvar_logging_stats_bucket_count;
00116 
00117 LoggingStats::LoggingStats(string name_arg) : Logging(name_arg)
00118 {
00119   current_scoreboard= new Scoreboard(sysvar_logging_stats_scoreboard_size, 
00120                                      sysvar_logging_stats_bucket_count);
00121 
00122   cumulative_stats= new CumulativeStats(sysvar_logging_stats_max_user_count); 
00123 }
00124 
00125 LoggingStats::~LoggingStats()
00126 {
00127   delete current_scoreboard;
00128   delete cumulative_stats;
00129 }
00130 
00131 void LoggingStats::updateCurrentScoreboard(ScoreboardSlot *scoreboard_slot,
00132                                            Session *session)
00133 {
00134   enum_sql_command sql_command= session->lex().sql_command;
00135 
00136   scoreboard_slot->getUserCommands()->logCommand(sql_command);
00137 
00138   /* If a flush occurred copy over values before setting new values */
00139   if (scoreboard_slot->getStatusVars()->hasBeenFlushed(session))
00140   {
00141     cumulative_stats->logGlobalStatusVars(scoreboard_slot);
00142   }
00143   scoreboard_slot->getStatusVars()->logStatusVar(session);
00144 }
00145 
00146 bool LoggingStats::resetGlobalScoreboard()
00147 {
00148   cumulative_stats->getGlobalStatusVars()->reset();
00149   cumulative_stats->getGlobalStats()->getUserCommands()->reset();
00150 
00151   ScoreBoardVectors *vector_of_scoreboard_vectors=
00152     current_scoreboard->getVectorOfScoreboardVectors();
00153 
00154   ScoreBoardVectors::iterator v_of_scoreboard_v_begin_it= vector_of_scoreboard_vectors->begin();
00155 
00156   ScoreBoardVectors::iterator v_of_scoreboard_v_end_it= vector_of_scoreboard_vectors->end();
00157 
00158   for (; v_of_scoreboard_v_begin_it != v_of_scoreboard_v_end_it; ++v_of_scoreboard_v_begin_it)
00159   {
00160     std::vector<ScoreboardSlot* > *scoreboard_vector= *v_of_scoreboard_v_begin_it;
00161 
00162     std::vector<ScoreboardSlot* >::iterator scoreboard_vector_it= scoreboard_vector->begin();
00163     std::vector<ScoreboardSlot* >::iterator scoreboard_vector_end= scoreboard_vector->end();
00164     for (; scoreboard_vector_it != scoreboard_vector_end; ++scoreboard_vector_it)
00165     {
00166       ScoreboardSlot *scoreboard_slot= *scoreboard_vector_it;
00167       scoreboard_slot->getStatusVars()->reset();
00168       scoreboard_slot->getUserCommands()->reset();
00169     }
00170   }
00171 
00172   return false;
00173 }
00174 
00175 bool LoggingStats::post(Session *session)
00176 {
00177   if (! isEnabled() || (session->getSessionId() == 0))
00178   {
00179     return false;
00180   }
00181 
00182   ScoreboardSlot *scoreboard_slot= current_scoreboard->findScoreboardSlotToLog(session);
00183 
00184   /* Its possible that the scoreboard is full with active sessions in which case 
00185      this could be null */
00186   if (scoreboard_slot)
00187   {
00188     updateCurrentScoreboard(scoreboard_slot, session);
00189   }
00190   return false;
00191 }
00192 
00193 bool LoggingStats::postEnd(Session *session)
00194 {
00195   if (! isEnabled() || (session->getSessionId() == 0))
00196   {
00197     return false;
00198   }
00199 
00200   bool isInScoreboard= false;
00201   ScoreboardSlot *scoreboard_slot= current_scoreboard->findOurScoreboardSlot(session);
00202 
00203   if (scoreboard_slot)
00204   {
00205     isInScoreboard= true;
00206   } 
00207   else 
00208   { 
00209     /* the session did not have a slot reserved, that could be because the scoreboard was
00210        full, but most likely its a failed authentication so post() is never called where
00211        the slot is assigned. Log the global status values below, and if the user has a slot
00212        log to it, but do not reserve a new slot for a user. If it was a failed authentication
00213        the scoreboard would be filled up quickly with invalid users. 
00214     */
00215     scoreboard_slot= new ScoreboardSlot();
00216     scoreboard_slot->setUser(session->user()->username());
00217     scoreboard_slot->setIp(session->user()->address());
00218   }
00219 
00220   scoreboard_slot->getStatusVars()->logStatusVar(session);
00221   boost::posix_time::ptime end(boost::posix_time::microsec_clock::universal_time());
00222   uint64_t end_time= (end - session->times.epoch()).total_seconds();
00223   scoreboard_slot->getStatusVars()->getStatusVarCounters()->connection_time= end_time - session->times.getConnectSeconds();
00224 
00225   cumulative_stats->logUserStats(scoreboard_slot, isInScoreboard);
00226   cumulative_stats->logGlobalStats(scoreboard_slot);
00227   cumulative_stats->logGlobalStatusVars(scoreboard_slot);
00228 
00229   if (isInScoreboard)
00230   {
00231     scoreboard_slot->reset();
00232   } 
00233   else 
00234   {
00235     delete scoreboard_slot;
00236   } 
00237 
00238   return false;
00239 }
00240 
00241 /* Plugin initialization and system variables */
00242 
00243 static LoggingStats *logging_stats= NULL;
00244 
00245 static CurrentCommandsTool *current_commands_tool= NULL;
00246 
00247 static CumulativeCommandsTool *cumulative_commands_tool= NULL;
00248 
00249 static GlobalStatementsTool *global_statements_tool= NULL;
00250 
00251 static SessionStatementsTool *session_statements_tool= NULL;
00252 
00253 static StatusTool *global_status_tool= NULL;
00254 
00255 static StatusTool *session_status_tool= NULL;
00256 
00257 static CumulativeUserStatsTool *cumulative_user_stats_tool= NULL;
00258 
00259 static ScoreboardStatsTool *scoreboard_stats_tool= NULL;
00260 
00261 static void enable(Session *, sql_var_t)
00262 {
00263   if (logging_stats)
00264   {
00265     if (sysvar_logging_stats_enabled)
00266     {
00267       logging_stats->enable();
00268     }
00269     else
00270     {
00271       logging_stats->disable();
00272     }
00273   }
00274 }
00275 
00276 static int init(drizzled::module::Context &context)
00277 {
00278   const module::option_map &vm= context.getOptions();
00279   sysvar_logging_stats_enabled= not vm.count("disable");
00280 
00281   logging_stats= new LoggingStats("logging_stats");
00282   current_commands_tool= new CurrentCommandsTool(logging_stats);
00283   cumulative_commands_tool= new CumulativeCommandsTool(logging_stats);
00284   global_statements_tool= new GlobalStatementsTool(logging_stats);
00285   session_statements_tool= new SessionStatementsTool(logging_stats);
00286   session_status_tool= new StatusTool(logging_stats, true);
00287   global_status_tool= new StatusTool(logging_stats, false);
00288   cumulative_user_stats_tool= new CumulativeUserStatsTool(logging_stats);
00289   scoreboard_stats_tool= new ScoreboardStatsTool(logging_stats);
00290 
00291   context.add(logging_stats);
00292   context.add(current_commands_tool);
00293   context.add(cumulative_commands_tool);
00294   context.add(global_statements_tool);
00295   context.add(session_statements_tool);
00296   context.add(session_status_tool);
00297   context.add(global_status_tool);
00298   context.add(cumulative_user_stats_tool);
00299   context.add(scoreboard_stats_tool);
00300 
00301   if (sysvar_logging_stats_enabled)
00302     logging_stats->enable();
00303 
00304   context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("max_user_count", sysvar_logging_stats_max_user_count));
00305   context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("bucket_count", sysvar_logging_stats_bucket_count));
00306   context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("scoreboard_size", sysvar_logging_stats_scoreboard_size));
00307   context.registerVariable(new sys_var_bool_ptr("enable", &sysvar_logging_stats_enabled, enable));
00308 
00309   return 0;
00310 }
00311 
00312 
00313 static void init_options(drizzled::module::option_context &context)
00314 {
00315   context("max-user-count",
00316           po::value<max_user_count_constraint>(&sysvar_logging_stats_max_user_count)->default_value(500),
00317           _("Max number of users that will be logged"));
00318   context("bucket-count",
00319           po::value<bucket_count_constraint>(&sysvar_logging_stats_bucket_count)->default_value(10),
00320           _("Max number of range locks to use for Scoreboard"));
00321   context("scoreboard-size",
00322           po::value<scoreboard_size_constraint>(&sysvar_logging_stats_scoreboard_size)->default_value(2000),
00323           _("Max number of concurrent sessions that will be logged"));
00324   context("disable", _("Enable Logging Statistics Collection"));
00325 }
00326 
00327 DRIZZLE_DECLARE_PLUGIN
00328 {
00329   DRIZZLE_VERSION_ID,
00330   "logging_stats",
00331   "0.1",
00332   "Joseph Daly",
00333   N_("User Statistics as DATA_DICTIONARY tables"),
00334   PLUGIN_LICENSE_BSD,
00335   init,   /* Plugin Init      */
00336   NULL, /* depends */
00337   init_options    /* config options   */
00338 }
00339 DRIZZLE_DECLARE_PLUGIN_END;