From 648625d0d2644042798d63bc9729ae477d9cffd3 Mon Sep 17 00:00:00 2001 From: hickert Date: Wed, 18 Aug 2010 14:31:53 +0000 Subject: [PATCH] Updated stats handling -create a file for each day -transmit entries per day -remove transmitted stats files afterwards. git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@19407 594d385d-05f5-0310-b6e9-bd551577e9d8 --- gosa-core/include/class_core.inc | 6 +- gosa-core/include/class_stats.inc | 127 +++++++++++++----- .../generic/statistics/class_statistics.inc | 99 +++++++++++--- 3 files changed, 179 insertions(+), 53 deletions(-) diff --git a/gosa-core/include/class_core.inc b/gosa-core/include/class_core.inc index 94440a9af..6f9df0b45 100644 --- a/gosa-core/include/class_core.inc +++ b/gosa-core/include/class_core.inc @@ -249,11 +249,11 @@ class core extends plugin { "mandatory" => TRUE), array( - "name" => "statsDatabaseFile", - "type" => "file", + "name" => "statsDatabaseDirectory", + "type" => "path", "default" => "/var/spool/gosa/stats", "description" => _("The database file for GOSa usage statistics."), - "check" => "gosaProperty::isWriteableFile", + "check" => "gosaProperty::isWriteablePath", "migrate" => "", "group" => "core", "mandatory" => TRUE), diff --git a/gosa-core/include/class_stats.inc b/gosa-core/include/class_stats.inc index 8d49c2f93..282fc2c45 100644 --- a/gosa-core/include/class_stats.inc +++ b/gosa-core/include/class_stats.inc @@ -7,7 +7,6 @@ class stats static protected $lastCpuLoadTimestamp = 0; static protected $tableName = "stats"; - static protected $tableFile = "/var/spool/gosa/stats"; static protected $lastHandle = NULL; static protected $statsEnabled = FALSE; @@ -16,56 +15,97 @@ class stats /*! \brief This method tries to connect the GOsa-stats database and * then returns a database handle on success else NULL. * - * (The GOsa-stats database has to be enabled : statsDatabaseEnabled/statsDatabaseFile) + * (The GOsa-stats database has to be enabled : statsDatabaseEnabled/statsDatabaseDirectory) * * This database will then contain information about the use of GOsa, * no customer data will be stored. * * @return handle Returns a sqlite database handle. */ - static function getDatabaseHandle() + static function getDatabaseHandle($filename = '') { + // We cannot log while the path to store logs in is empty. + global $config; + $path = $config->get_cfg_value('core', 'statsDatabaseDirectory'); + if(empty($path)){ + return(NULL); + } + + // Check if path exists, if not try to create it + if(!is_dir($path) ){ + $res = @mkdir($path); + if(!$res){ + return(NULL); + } + } + + // Append a date suffix to the database file, to prevent huge and unusable database files. + if($filename == ''){ + $filename = date('Y-m-d'); + } + $tableFile = $path.'/'.$filename; + // Try to return last valid handle. - if(stats::$lastHandle != NULL && is_resource(stats::$lastHandle)){ - return(stats::$lastHandle); + if(file_exists($tableFile) && + isset(stats::$lastHandle[$filename]) && + stats::$lastHandle[$filename] != NULL && + is_resource(stats::$lastHandle[$filename])){ + return(stats::$lastHandle[$filename]); } // Check if Logging is enabled - global $config; if(!is_object($config) || ! $config instanceOf config){ return(NULL); } // Get statsFile property - stats::$tableFile = $config->get_cfg_value('core', 'statsDatabaseFile'); stats::$statsEnabled = $config->boolValueIsTrue('core', 'statsDatabaseEnabled'); if(!stats::$statsEnabled){ - return; + return(NULL); } - // Append a date suffix to the database file, to prevent huge and unusable database files. - stats::$tableFile.= date('-Y_m_d'); - // Check for SQLite extension if(!stats::checkSQLiteExtension()){ return(NULL); } // Check if we are able to read/write the given database file. - if(!is_writeable(stats::$tableFile) && !is_writeable(dirname(stats::$tableFile))){ + if(!is_writeable($path) && !is_writeable(dirname($tableFile))){ return(NULL); } - + // Try to create database, if it exists just open it. - $handle = sqlite_popen(stats::$tableFile, 0666, $error); + $handle = sqlite_open($tableFile, 0666, $error); if($handle){ stats::createDatabaseOnDemand($handle); } - stats::$lastHandle = $handle; + stats::$lastHandle[$filename] = $handle; return($handle); } + /*! \brief Returns a list of all created stat files + * @return Array A list of all currently stored stat files. + */ + static function getLocalStatFiles() + { + $res = array(); + + // Check if we're creating logs right now. + if(stats::getDatabaseHandle()){ + global $config; + + // Walk through all files found in the storage path + $path = $config->get_cfg_value('core', 'statsDatabaseDirectory'); + $dir = opendir($path); + while($file = readdir($dir)){ + if(is_file($path.'/'.$file)) $res[] = $file; + } + } + return($res); + } + + /*! \brief Check whether the qlite extension is available or not. * @return boolean TRUE on success else FALSE */ @@ -222,7 +262,19 @@ class stats '{$memory_usage}','{$cpu_load}','{$info}')"; sqlite_query($query, $res); } - + + + /*! \brief Closes all sqlite handles opened by this class + */ + static function closeHandles() + { + foreach(stats::lastHandle as $handle){ + if($handle && is_resource($handle)){ + sqlite_close($handle); + } + } + } + /*! \brief This method returns all entries of the GOsa-stats table. * You can limit the result by setting the from/to parameter (timestamp). @@ -230,31 +282,44 @@ class stats * @param int to The timestamp to end the request. * @return array An array containing the requested entries. */ - static function dumpTables($from = NULL, $to = NULL) + static function dumpTables($filename) { // Get database connection $TABLE_NAME = stats::$tableName; - $handle = stats::getDatabaseHandle(); + $handle = stats::getDatabaseHandle($filename); if(!$handle) return; - // Build up filter to limit dumped entries to the given range. - $tim = ""; - if($from != NULL){ - $from = sqlite_escape_string($from); - $tim.= "AND TIMESTAMP >= '{$from}' "; - } - if($to != NULL){ - $to = sqlite_escape_string($to); - $tim.= "AND TIMESTAMP <= '{$to}' "; - } - $tim = preg_replace("/^AND /"," WHERE ",$tim); - // Create Filter and start query - $filter = "SELECT * FROM {$TABLE_NAME}{$tim} ORDER BY ID"; + $filter = "SELECT * FROM {$TABLE_NAME} ORDER BY ID"; $ret = sqlite_array_query($filter, $handle, SQLITE_ASSOC); return($ret); } + + static function removeStatsFile($filename) + { + // Get statsFile property + global $config; + $path = $config->get_cfg_value('core', 'statsDatabaseDirectory'); + stats::$statsEnabled = $config->boolValueIsTrue('core', 'statsDatabaseEnabled'); + if(!stats::$statsEnabled){ + return(NULL); + } + + // We cannot log while the path to store logs in is empty. + if(empty($path)){ + return(NULL); + } + + // Check if file exists and then remove it + if(isset(stats::$lastHandle[$filename]) && is_resource(stats::$lastHandle[$filename])){ + sqlite_close(stats::$lastHandle[$filename]); + } + if(file_exists($path.'/'.$filename)){ + unlink($path.'/'.$filename); + } + } + /*! \brief This is just a dummy output/debug method * It directly prints some stats and table infos on the screen. diff --git a/gosa-core/plugins/generic/statistics/class_statistics.inc b/gosa-core/plugins/generic/statistics/class_statistics.inc index ecd85d9a9..15db5bc17 100644 --- a/gosa-core/plugins/generic/statistics/class_statistics.inc +++ b/gosa-core/plugins/generic/statistics/class_statistics.inc @@ -17,6 +17,8 @@ class statistics extends plugin var $graph1DatePicker1 = 0; var $graph1DatePicker2 = 0; + var $unsbmittedFiles = array(); + function __construct($config) { plugin::plugin($config, NULL); @@ -35,8 +37,61 @@ class statistics extends plugin "WyukwauWoid2", TRUE); } + + // Get list of unsubmitted files. + $this->unsbmittedFiles = $this->getUnsubmittedStatistics(); + } + + /*! \brief Returns a list local stored statistic files + @param Array A list of filenames and dates. + */ + function getLocalStatisticsFiles() + { + + $res = stats::getLocalStatFiles(); + $tmp = array(); + if(count($res)){ + foreach($res as $file){ + $date = strtotime($file); + if($date){ + $tmp[$file] = $date; + } + } + } + return($tmp); + } + + + /*! \brief Returns a list of not transmitted stat files (except files for the current day) + * @return Array A list of unsubmitted statistic files. + */ + function getUnsubmittedStatistics() + { + $available = $this->getLocalStatisticsFiles(); + $alreadyTransmitted = $this->getStatisticsDatesFromServer(); + $unsubmitted = array_intersect($available,$alreadyTransmitted); + return($unsubmitted); + } + + + /*! \brief Request a list of dates for which the server can return statistics. + @param Array A list of dates $ret=[iso-str] = timestamp + */ + function getStatisticsDatesFromServer() + { + $res = $this->rpcHandle->getInstanceStatDates(); + $dates = array(); + if(!$this->rpcHandle->success()){ + msg_dialog::display(_("Error"),msgPool::rpcError($this->rpcHandle->get_error()),ERROR_DIALOG); + }else{ + foreach($res as $date){ + $dates[$date] = strtotime($date); + } + } + return($dates); } + function execute() { if(isset($_POST['graph1DatePicker1'])) $this->graph1DatePicker1 = get_post('graph1DatePicker1'); @@ -61,17 +116,22 @@ class statistics extends plugin // Send stats if(isset($_POST['transmitStatistics'])){ - $tmp = stats::dumpTables(); - $dump = array(); - foreach($tmp as $entry){ - $dump[] = array_values($entry); - } - $res = $this->rpcHandle->updateInstanceStatus($dump); - if(!$this->rpcHandle->success()){ - msg_dialog::display(_("Error"),msgPool::rpcError($this->rpcHandle->get_error()),ERROR_DIALOG); - }else{ - echo $res." Entries inserted"; + $this->unsbmittedFiles = $this->getUnsubmittedStatistics(); + foreach($this->unsbmittedFiles as $filename => $date){ + $tmp = stats::dumpTables($filename); + $dump = array(); + foreach($tmp as $entry){ + $dump[] = array_values($entry); + } + $res = $this->rpcHandle->updateInstanceStatus($dump); + if(!$this->rpcHandle->success()){ + msg_dialog::display(_("Error"),msgPool::rpcError($this->rpcHandle->get_error()),ERROR_DIALOG); + }else{ + stats::removeStatsFile($filename); + echo "Inserted ".$res." entries for date ".date('d.m.Y', $date)."
"; + } } + $this->unsbmittedFiles = $this->getUnsubmittedStatistics(); } // Transmit daily statistics to GOsa-Server @@ -95,7 +155,7 @@ class statistics extends plugin new pChartInclude(); // Get most used categories, but only eight at once. - if(count($res['actionsPerCategory']) && 0){ + if(count($res['actionsPerCategory'])){ // -------- // Generate PIE chart of most used categories @@ -108,9 +168,12 @@ class statistics extends plugin $DataSet = new pData; $this->graphID_1 = preg_replace("/[^0-9]/","",microtime(TRUE)); - $DataSet->AddPoint(array_values($mostUsedCategories),"Serie1"); - $DataSet->AddPoint(array_keys($mostUsedCategories),"Serie2"); + $values = array_values($mostUsedCategories); + $keys = array_keys($mostUsedCategories); + + $DataSet->AddPoint($values,"Serie1"); $DataSet->AddAllSeries(); + $DataSet->AddPoint($keys,"Serie2"); $DataSet->SetAbsciseLabelSerie("Serie2"); // Initialise the graph @@ -162,6 +225,8 @@ class statistics extends plugin // Add results to our data set. $DataSet2->AddPoint($dataArray[$category], $category); $DataSet2->SetSerieName(_($category), $category); + $Test->setLabel($DataSet->GetData(),$DataSet->GetDataDescription(),"Serie1",0,"Daily incomes"); + $DataSet2->AddSerie($category); // Detect maximum value, to adjust the Y-Axis $tmpMax = max($dataArray[$category]); @@ -169,8 +234,6 @@ class statistics extends plugin } ksort($dates); - $DataSet2->AddAllSeries(); - // Prepare date strings for X-Axis, only print a given number of // of labels to keep the axis readable. $Xam = 5; // Number of labels @@ -187,7 +250,6 @@ class statistics extends plugin $DataSet2->AddPoint($tmp, 'date'); $DataSet2->SetAbsciseLabelSerie('date'); - $DataSet2->RemoveSerie('date'); $Test2 = new pChart(800,230); $Test2->setFixedScale(0.0001,($max*1.1)); @@ -205,7 +267,6 @@ class statistics extends plugin $DataSet2->RemoveSerie('date'); } - // Draw the cubic curve graph if(count($dataArray)){ $Test2->drawFilledLineGraph($DataSet2->GetData(),$DataSet2->GetDataDescription(),50,TRUE); @@ -221,8 +282,8 @@ class statistics extends plugin $DataSet2->AddPoint($errors, 'Errors'); $DataSet2->SetSerieName('Errors', 'Errors'); - $DataSet2->AddAllSeries(); - $DataSet2->RemoveSerie('date'); + $DataSet2->AddSerie('Errors'); + // Draw legend $Test2->drawLegend(650,30,$DataSet2->GetDataDescription(),255,255,255); -- 2.30.2