c8631ce2e0302cb3f93caf21c3d9525043868349
1 <?php
3 class stats
4 {
6 static protected $lastCpuLoad = "";
7 static protected $lastCpuLoadTimestamp = 0;
9 static protected $tableName = "stats";
10 static protected $tableFile = "/var/spool/gosa/stats";
12 static protected $lastHandle = NULL;
13 static protected $statsEnabled = FALSE;
15 static function getDatabaseHandle()
16 {
17 // Try to return last valid handle.
18 if(stats::$lastHandle != NULL && is_resource(stats::$lastHandle)){
19 return(stats::$lastHandle);
20 }
22 // Check if Logging is enabled
23 global $config;
24 if(!is_object($config) || ! $config instanceOf config){
25 return(NULL);
26 }
28 // Get statsFile property
29 stats::$tableFile = $config->get_cfg_value('core', 'statsDatabaseFile');
30 stats::$statsEnabled = $config->boolValueIsTrue('core', 'statsDatabaseEnabled');
31 if(!stats::$statsEnabled){
32 return;
33 }
35 // Check for SQLite extension
36 if(!stats::checkSQLiteExtension()){
37 return(NULL);
38 }
40 // Check if we are able to read/write the given database file.
41 if(!is_writeable(stats::$tableFile) && !is_writeable(dirname(stats::$tableFile))){
42 return(NULL);
43 }
45 // Try to create database, if it exists just open it.
46 $handle = sqlite_popen(stats::$tableFile, 0666, $error);
47 if($handle){
48 stats::createDatabaseOnDemand($handle);
49 }
50 stats::$lastHandle = $handle;
51 return($handle);
52 }
54 /*! \brief |
55 * @param |
56 * @return |
57 */
58 static function checkSQLiteExtension()
59 {
60 return(function_exists('sqlite_popen'));
61 }
64 /*! \brief |
65 * @param |
66 * @return |
67 */
68 static function dropTable($handle)
69 {
70 $TABLE_NAME = stats::$tableName;
71 $query = "DROP TABLE '{$TABLE_NAME}'";
72 $ret = sqlite_query($query, $handle);
73 stats::$lastHandle = NULL;
74 stats::getDatabaseHandle();
75 }
78 /*! \brief |
79 * @param |
80 * @return |
81 */
82 static function get_memory_usage()
83 {
84 return(memory_get_usage());
85 }
88 /*! \brief |
89 * @param |
90 * @return |
91 */
92 static function get_cpu_load()
93 {
94 $cur = time();
95 if(empty(stats::$lastCpuLoad) || (($cur - stats::$lastCpuLoadTimestamp) >=2 )){
96 list($one, $five, $ten) =preg_split("/ /",shell_exec('cat /proc/loadavg'));
97 stats::$lastCpuLoad = $one;
98 stats::$lastCpuLoadTimestamp = $cur;
99 }
100 return(stats::$lastCpuLoad);
101 }
104 /*! \brief |
105 * @param |
106 * @return |
107 */
108 static function createDatabaseOnDemand($handle)
109 {
110 $TABLE_NAME = stats::$tableName;
112 // List Tables an check if there is already everything we need,
113 // if not create it.
114 $query = "SELECT name FROM sqlite_master WHERE type='table' and name='{$TABLE_NAME}'";
115 $ret = sqlite_query($query, $handle);
116 if(!count(sqlite_fetch_all($ret))){
117 $query = "
118 CREATE TABLE {$TABLE_NAME} (
119 ID INTEGER PRIMARY KEY,
120 ACTID INTEGER,
121 TYPE TEXT,
122 PLUGIN TEXT,
123 CATEGORY TEXT,
124 ACTION TEXT,
125 UUID TEXT,
126 TIMESTAMP INTEGER,
127 MTIMESTAMP REAL,
128 DURATION REAL,
129 RENDER_TIME REAL,
130 AMOUNT INTEGER,
131 MEMORY_USAGE INTEGER,
132 CPU_LOAD FLOAT,
133 INFO BLOB
134 )";
135 $ret = sqlite_query($query, $handle);
136 }
137 }
140 /*! \brief |
141 * @param |
142 * @return |
143 */
144 static function log($type, $plugin, $category, $action, $amount = 1, $duration = 0, $info ='')
145 {
146 global $config;
147 global $clicks;
148 global $overallRenderTimer;
150 // Get database handle, if it is invalid (NULL) return without creating stats
151 $res = stats::getDatabaseHandle();
152 # stats::dropTable($res);
153 if(!$res) return;
155 // Ensure that 'clicks' and 'overallRenderTimer' are present and set correctly,
156 // if not simply create them with dummy values...
157 // -- 'clicks' is a counter wich is set in main.php -> Number of page reloads
158 // -- 'overallRenderTimer' is set in main.php -> timestamp of rendering start.
159 if(!isset($clicks) || empty($clicks)) $clicks = 0;
160 if(!isset($overallRenderTimer)){
161 $renderTime = 0;
162 }else{
163 $renderTime = microtime(TRUE) - $overallRenderTimer;
165 // Now set the overallRenderTimer to the current timestamp - else
166 // we will not be able to sum up the render time in a single SQL statement.
167 $overallRenderTimer = microtime(TRUE);
168 }
170 // Enforce floating point values ...damn this sucks.
171 $duration += 0.000001;
172 $renderTime += 0.000001;
174 $duration = sprintf("%0.6f",$duration);
175 $renderTime = sprintf("%0.6f",$renderTime);
177 $duration = preg_replace("/\./",",",$duration);
178 $renderTime = preg_replace("/\./",",",$renderTime);
180 // Prepare values to be useable within a database
181 $uuid = $config->getGOsaUUID();
182 $type = sqlite_escape_string($type);
183 $plugin = sqlite_escape_string($plugin);
184 $action = sqlite_escape_string($action);
185 $timestamp = time();
186 $mtimestamp = microtime(TRUE);
187 $amount = sqlite_escape_string($amount);
188 $duration = sqlite_escape_string($duration);
189 $renderTime = sqlite_escape_string($renderTime);
190 $info = sqlite_escape_string($info);
191 $clicks = sqlite_escape_string($clicks);
192 $memory_usage = sqlite_escape_string(stats::get_memory_usage());
193 $cpu_load = sqlite_escape_string(sprintf("%0.6f",stats::get_cpu_load()));
195 // Clean up category, which usally comes from acl_category and may still contain
196 // some special chars like /
197 $tmp = array();
198 foreach($category as $cat){
199 $tmp[] = trim($cat, '\/,; ');
200 }
201 $category = sqlite_escape_string(implode($tmp, ', '));
203 // Create insert statement.
204 $TABLE_NAME = stats::$tableName;
205 $query = "
206 INSERT INTO {$TABLE_NAME}
207 (ACTID, TYPE, PLUGIN, CATEGORY, ACTION, UUID, MTIMESTAMP, TIMESTAMP,
208 AMOUNT, DURATION, RENDER_TIME, MEMORY_USAGE, CPU_LOAD, INFO)
209 VALUES
210 ('{$clicks}','{$type}','{$plugin}','{$category}','{$action}','{$uuid}',
211 '{$mtimestamp}','{$timestamp}','{$amount}','{$duration}','{$renderTime}',
212 '{$memory_usage}','{$cpu_load}','{$info}')";
213 sqlite_query($query, $res);
214 }
217 /*! \brief |
218 * @param |
219 * @return |
220 */
221 static function show()
222 {
223 $res = stats::getDatabaseHandle();
224 # stats::dropTable($res);
225 if(!$res) return;
227 $TABLE_NAME = stats::$tableName;
228 $query = "SELECT * FROM {$TABLE_NAME} ORDER BY MTIMESTAMP";
229 $query = "SELECT PLUGIN, ACTION, MAX(DURATION) as 'DURATION' FROM {$TABLE_NAME} WHERE ACTION='modify' GROUP BY PLUGIN,ACTION ";
230 $query = "SELECT * FROM {$TABLE_NAME} ORDER BY ID DESC LIMIT 30";
231 $query = "SELECT * FROM {$TABLE_NAME} WHERE plugin != 'LDAP' ORDER BY ID DESC LIMIT 30";
232 $ret = sqlite_query($query, $res);
233 echo "<pre>";
235 $colSize = 16;
237 $title = FALSE;
238 foreach(sqlite_fetch_all($ret) as $entry){
239 if(!$title){
240 foreach($entry as $key => $str) {
241 if(is_numeric($key)) continue;
242 echo str_pad($key,$colSize,' ')."|";
243 }
244 echo "\n";
245 foreach($entry as $key => $str) {
246 if(is_numeric($key)) continue;
247 echo str_pad('',$colSize,'-')."-";
248 }
249 echo "\n";
250 $title = TRUE;
251 }
253 foreach($entry as $key => $str){
254 if(is_numeric($key)) continue;
255 if($key == "DURATION" || $key == "MTIMESTAMP" || $key == "CPU_LOAD"){
256 $str = sprintf("%0.4f", preg_replace("/,/",".",$str));
257 echo str_pad($str,$colSize,' ', STR_PAD_LEFT)."|";
258 }else{
259 echo str_pad($str,$colSize,' ')."|";
260 }
261 }
262 echo "\n";
263 }
264 echo sqlite_error_string($ret);
266 echo "\n------ \n";
267 echo "Time spent per plugin-category \n";
268 echo "------ \n";
270 $query = "
271 SELECT SUM(DURATION) AS DUR, CATEGORY
272 FROM {$TABLE_NAME}
273 WHERE plugin != 'LDAP'
274 GROUP BY CATEGORY
275 ORDER BY DUR DESC LIMIT 10";
276 $ret = sqlite_query($query, $res);
278 $colSize = 16;
279 $title = FALSE;
280 foreach(sqlite_fetch_all($ret) as $entry){
281 foreach($entry as $key => $str){
282 if(is_numeric($key)) continue;
283 echo str_pad($str,$colSize,' ')."|";
284 }
285 echo "\n";
286 }
289 echo sqlite_error_string($ret);
291 echo "\n------ \n";
292 echo "Time spent per plugin \n";
293 echo "------ \n";
295 $query = "
296 SELECT SUM(DURATION) AS DUR, PLUGIN, UUID
297 FROM {$TABLE_NAME}
298 WHERE plugin != 'LDAP'
299 GROUP BY PLUGIN, UUID
300 ORDER BY DUR DESC LIMIT 10";
301 $ret = sqlite_query($query, $res);
303 $colSize = 16;
304 $title = FALSE;
305 foreach(sqlite_fetch_all($ret) as $entry){
306 foreach($entry as $key => $str){
307 if(is_numeric($key)) continue;
308 echo str_pad($str,$colSize,' ')."|";
309 }
310 echo "\n";
311 }
312 echo sqlite_error_string($ret);
314 # * Anzahl von Objekttypen
315 # * Anzahl der Löschungen pro Objekttyp
316 # * Anzahl der Erzeugungen pro Objekttyp
317 # * Anzahl der Bearbeitungen pro Objekttyp
318 # * Anzahl der Verschiebungen pro Objekttyp
319 # * Anzahl der Mehrfachbearbeitungen pro Objekttyp
320 # * Antwortzeiten pro aktion
321 # * Anzahl der Passwortänderungen
322 # * Anzahl der unterschiedlichen Anmeldungen
325 echo "\n------ \n";
326 echo "Actions done per plugin \n";
327 echo "------ \n";
329 $query = "
330 SELECT COUNT(ACTION) as CNT, ACTION, PLUGIN
331 FROM {$TABLE_NAME}
332 WHERE TYPE = 'plugin'
333 AND PLUGIN != 'LDAP'
334 GROUP BY ACTION,PLUGIN
335 ORDER BY CNT DESC LIMIT 30";
336 $ret = sqlite_query($query, $res);
338 $colSize = 16;
339 $title = FALSE;
340 foreach(sqlite_fetch_all($ret) as $entry){
341 foreach($entry as $key => $str){
342 if(is_numeric($key)) continue;
343 echo str_pad($str,$colSize,' ')."|";
344 }
345 echo "\n";
346 }
347 echo sqlite_error_string($ret);
349 echo "\n------ \n";
350 echo "'create' actions done per plugin (5 most)\n";
351 echo "------ \n";
353 $query = "
354 SELECT COUNT(ACTION) as CNT, ACTION, PLUGIN
355 FROM {$TABLE_NAME}
356 WHERE TYPE = 'plugin'
357 AND PLUGIN != 'LDAP'
358 AND ACTION = 'create'
359 GROUP BY ACTION,PLUGIN
360 ORDER BY CNT DESC LIMIT 5";
361 $ret = sqlite_query($query, $res);
363 $colSize = 16;
364 $title = FALSE;
365 foreach(sqlite_fetch_all($ret) as $entry){
366 foreach($entry as $key => $str){
367 if(is_numeric($key)) continue;
368 echo str_pad($str,$colSize,' ')."|";
369 }
370 echo "\n";
371 }
372 echo sqlite_error_string($ret);
374 echo "\n------ \n";
375 echo "'move' actions done per plugin (5 most)\n";
376 echo "------ \n";
378 $query = "
379 SELECT COUNT(ACTION) as CNT, ACTION, PLUGIN
380 FROM {$TABLE_NAME}
381 WHERE TYPE = 'plugin'
382 AND PLUGIN != 'LDAP'
383 AND ACTION = 'move'
384 GROUP BY ACTION,PLUGIN
385 ORDER BY CNT DESC LIMIT 5";
386 $ret = sqlite_query($query, $res);
388 $colSize = 16;
389 $title = FALSE;
390 foreach(sqlite_fetch_all($ret) as $entry){
391 foreach($entry as $key => $str){
392 if(is_numeric($key)) continue;
393 echo str_pad($str,$colSize,' ')."|";
394 }
395 echo "\n";
396 }
397 echo sqlite_error_string($ret);
399 echo "\n------ \n";
400 echo "'view' actions done per plugin (5 most)\n";
401 echo "------ \n";
403 $query = "
404 SELECT COUNT(ACTION) as CNT, ACTION, PLUGIN
405 FROM {$TABLE_NAME}
406 WHERE TYPE = 'plugin'
407 AND PLUGIN != 'LDAP'
408 AND ACTION = 'view'
409 GROUP BY ACTION,PLUGIN
410 ORDER BY CNT DESC LIMIT 5";
411 $ret = sqlite_query($query, $res);
413 $colSize = 16;
414 $title = FALSE;
415 foreach(sqlite_fetch_all($ret) as $entry){
416 foreach($entry as $key => $str){
417 if(is_numeric($key)) continue;
418 echo str_pad($str,$colSize,' ')."|";
419 }
420 echo "\n";
421 }
422 echo sqlite_error_string($ret);
424 echo "\n------ \n";
425 echo "'open' actions done per plugin (5 most)\n";
426 echo "------ \n";
428 $query = "
429 SELECT COUNT(ACTION) as CNT, ACTION, PLUGIN, UUID
430 FROM {$TABLE_NAME}
431 WHERE TYPE = 'plugin'
432 AND PLUGIN != 'LDAP'
433 AND ACTION = 'open'
434 GROUP BY ACTION,PLUGIN, UUID
435 ORDER BY CNT DESC LIMIT 5";
436 $ret = sqlite_query($query, $res);
438 $colSize = 16;
439 $title = FALSE;
440 foreach(sqlite_fetch_all($ret) as $entry){
441 foreach($entry as $key => $str){
442 if(is_numeric($key)) continue;
443 echo str_pad($str,$colSize,' ')."|";
444 }
445 echo "\n";
446 }
447 echo sqlite_error_string($ret);
449 echo "\n------ \n";
450 echo "Time per session\n";
451 echo "------ \n";
453 $query = "
454 SELECT SUM(DURATION) as DUR, UUID
455 FROM {$TABLE_NAME}
456 GROUP BY UUID
457 ORDER BY DUR DESC LIMIT 10";
458 $ret = sqlite_query($query, $res);
460 $colSize = 16;
461 $title = FALSE;
462 foreach(sqlite_fetch_all($ret) as $entry){
463 foreach($entry as $key => $str){
464 if(is_numeric($key)) continue;
465 echo str_pad($str,$colSize,' ')."|";
466 }
467 echo "\n";
468 }
469 echo sqlite_error_string($ret);
471 echo "\n------ \n";
472 echo "Most used password hashes\n";
473 echo "------ \n";
475 $query = "
476 SELECT DISTINCT(INFO), COUNT(INFO) as CNT
477 FROM {$TABLE_NAME}
478 WHERE ACTION = 'change_password'
479 GROUP BY INFO
480 ORDER BY INFO DESC LIMIT 10";
481 $ret = sqlite_query($query, $res);
483 $colSize = 16;
484 $title = FALSE;
485 foreach(sqlite_fetch_all($ret) as $entry){
486 foreach($entry as $key => $str){
487 if(is_numeric($key)) continue;
488 echo str_pad($str,$colSize,' ')."|";
489 }
490 echo "\n";
491 }
492 echo sqlite_error_string($ret);
494 echo "\n------ \n";
495 echo "Actions at all\n";
496 echo "------ \n";
498 $query = "
499 SELECT DISTINCT(ACTION), COUNT(ACTION) AS CNT
500 FROM {$TABLE_NAME}
501 GROUP BY ACTION
502 ORDER BY CNT DESC LIMIT 10";
503 $ret = sqlite_query($query, $res);
505 $colSize = 16;
506 $title = FALSE;
507 foreach(sqlite_fetch_all($ret) as $entry){
508 foreach($entry as $key => $str){
509 if(is_numeric($key)) continue;
510 echo str_pad($str,$colSize,' ')."|";
511 }
512 echo "\n";
513 }
514 echo sqlite_error_string($ret);
516 echo "\n------ \n";
517 echo "Time spent per action\n";
518 echo "------ \n";
520 $query = "
521 SELECT DISTINCT(ACTION), SUM(DURATION) AS DUR
522 FROM {$TABLE_NAME}
523 GROUP BY ACTION
524 ORDER BY DUR DESC LIMIT 10";
525 $ret = sqlite_query($query, $res);
527 $colSize = 16;
528 $title = FALSE;
529 foreach(sqlite_fetch_all($ret) as $entry){
530 foreach($entry as $key => $str){
531 if(is_numeric($key)) continue;
532 echo str_pad($str,$colSize,' ')."|";
533 }
534 echo "\n";
535 }
536 echo sqlite_error_string($ret);
538 echo "\n------ \n";
539 echo "Average time per action\n";
540 echo "------ \n";
542 $query = "
543 SELECT DISTINCT(ACTION), AVG(DURATION) AS DUR
544 FROM {$TABLE_NAME}
545 GROUP BY ACTION
546 ORDER BY DUR DESC LIMIT 10";
547 $ret = sqlite_query($query, $res);
549 $colSize = 16;
550 $title = FALSE;
551 foreach(sqlite_fetch_all($ret) as $entry){
552 foreach($entry as $key => $str){
553 if(is_numeric($key)) continue;
554 echo str_pad($str,$colSize,' ')."|";
555 }
556 echo "\n";
557 }
558 echo sqlite_error_string($ret);
561 echo "\n------ \n";
562 echo "Rendertime per plugin\n";
563 echo "------ \n";
565 $query = "
566 SELECT PLUGIN, RENDER_TIME * 1000000 AS RM
567 FROM {$TABLE_NAME}
568 GROUP BY PLUGIN
569 ";
570 $ret = sqlite_query($query, $res);
572 $colSize = 16;
573 $title = FALSE;
574 foreach(sqlite_fetch_all($ret) as $entry){
575 foreach($entry as $key => $str){
576 if(is_numeric($key)) continue;
577 echo str_pad($str,$colSize,' ')."|";
578 }
579 echo "\n";
580 }
581 echo sqlite_error_string($ret);
583 echo "</pre>";
584 }
585 }
588 ?>