Code

Updated stats handling
authorhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Wed, 18 Aug 2010 14:31:53 +0000 (14:31 +0000)
committerhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Wed, 18 Aug 2010 14:31:53 +0000 (14:31 +0000)
-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
gosa-core/include/class_stats.inc
gosa-core/plugins/generic/statistics/class_statistics.inc

index 94440a9afbd119718f29d109265776ab95703585..6f9df0b45fcf17070a033a4d538a7f4ec65cf0b5 100644 (file)
@@ -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),
index 8d49c2f93e8ffb85b0eea798c86fea8de3a1cf22..282fc2c45fbbd0700589c8d3542c5e13af9bd0f0 100644 (file)
@@ -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.
index ecd85d9a9a0487c8b8d460652130ffe9637d8246..15db5bc1798e2838b4b08d4e8f43abcc7d543a0b 100644 (file)
@@ -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)."<br>";
+                }
             }
+            $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);