diff --git a/modules/statistics/bin/loganalyzer.php b/modules/statistics/bin/loganalyzer.php new file mode 100755 index 0000000000000000000000000000000000000000..ec0a813c8f923a61634e4976a79aa4d64f9d3883 --- /dev/null +++ b/modules/statistics/bin/loganalyzer.php @@ -0,0 +1,118 @@ +#!/usr/bin/env php +<?php + +#$logfile = file_get_contents('/Users/andreas/Desktop/simplesamlphp.stat'); +#int mktime ([ int $hour [, int $minute [, int $second [, int $month [, int $day [, int $year [, int $is_dst ]]]]]]] ) +#http://chart.apis.google.com/chart?cht=lc&chs=200x125&chd=s:helloWorld&chxt=x,y&chxl=0:|Mar|Apr|May|June|July|1:||50+Kb + + + +require_once( dirname(dirname(dirname(dirname(__FILE__)))) . '/www/_include.php'); + +$config = SimpleSAML_Configuration::getInstance(); +$statconfig = $config->copyFromBase('statconfig', 'statistics.php'); + + +$statdir = $statconfig->getValue('statdir'); +$offset = $statconfig->getValue('offset'); +$inputfile = $statconfig->getValue('inputfile'); + +echo 'Statistics directory : ' . $statdir . "\n"; +echo 'Input file : ' . $inputfile . "\n"; +echo 'Offset : ' . $offset . "\n"; + +$statrules = $statconfig->getValue('statrules'); + +$file = fopen($inputfile, 'r'); +$logfile = file($inputfile, FILE_IGNORE_NEW_LINES ); + + + +# Aug 27 12:54:25 ssp 5 STAT [5416262207] saml20-sp-SSO urn:mace:feide.no:services:no.uninett.wiki-feide sam.feide.no NA +# +#Oct 30 11:07:14 www1 simplesamlphp-foodle[12677]: 5 STAT [200b4679af] saml20-sp-SLO spinit urn:mace:feide.no:services:no.feide.foodle sam.feide.no + +function parse15($str) { + $di = date_parse($str); + $datestamp = mktime($di['hour'], $di['minute'], $di['second'], $di['month'], $di['day']); + return $datestamp; +} + +function parse23($str) { + $timestamp = strtotime($str); + return $timestamp; +} + +$results = array(); +# Sat, 16 Feb 08 00:55:11 (23 chars) +foreach ($logfile AS $logline) { + $datenumbers = 15; + + $datestr = substr($logline,0,$datenumbers); + #$datestr = substr($logline,0,23); + $timestamp = parse15($datestr) + $offset; + $restofline = substr($logline,$datenumbers+1); + $restcols = split(' ', $restofline); + $action = $restcols[5]; + +# print_r($restcols); exit; + + foreach ($statrules AS $rulename => $rule) { + $timeslot = floor($timestamp/$rule['slot']); + $fileslot = floor($timestamp/$rule['fileslot']); + if ($action !== $rule['action']) continue; + + $difcol = $restcols[$rule['col']]; + $results[$rulename][$fileslot][$timeslot]['_']++; + $results[$rulename][$fileslot][$timeslot][$difcol]++; + } +} + + + + +echo "Results:\n"; +print_r($results); + + + +foreach ($results AS $rulename => $ruleresults) { + foreach ($ruleresults AS $fileno => $fileres) { + + $slotlist = array_keys($fileres); + $start = $slotlist[0]; + $start = $fileno*($statrules[$rulename]['fileslot'] / $statrules[$rulename]['slot']); + #echo 'Start was set to ' . $start . ' instead consider ' . $fileno*($statrules[$rulename]['fileslot'] / $statrules[$rulename]['slot']) . "\n"; + + $end = $slotlist[count($fileres)-1]; + $end = ($fileno+1)*($statrules[$rulename]['fileslot'] / $statrules[$rulename]['slot']); + #echo 'End was set to ' . $end . ' instead consider ' . ($fileno+1)*($statrules[$rulename]['fileslot'] / $statrules[$rulename]['slot']) . "\n"; +// exit; +// echo "From $start to $end \n"; + + $filledresult = array(); + for ($slot = $start; $slot < $end; $slot++) { + $filledresult[$slot] = (isset($fileres[$slot])) ? $fileres[$slot] : array('_' => 0); + } + + file_put_contents($statdir . $rulename . '-' . $fileno . '.stat', serialize($filledresult) ); + } +} + +// foreach ($results AS $rulename => $ruleresults) { +// foreach ($ruleresults AS $fileno => $fileres) { +// file_put_contents($statdir . $rulename . '-' . $fileno . '.stat', serialize($fileres) ); +// } +// } + + +foreach ($results AS $slot => $val) { + echo date($dateformat, ($slot*$granularity)-$offset) . "\t" . $slot . "\t"; + foreach ($val AS $sp => $no) { + echo $sp . " " . $no . " - "; + } + echo "\n"; +} + + + diff --git a/modules/statistics/config-templates/statistics.php b/modules/statistics/config-templates/statistics.php new file mode 100644 index 0000000000000000000000000000000000000000..7c4e68f65a1d82fb0559c75417e8e6ad7320c494 --- /dev/null +++ b/modules/statistics/config-templates/statistics.php @@ -0,0 +1,60 @@ +<?php +/* + * The configuration of simpleSAMLphp statistics package + */ + +$config = array ( + + 'statdir' => '/tmp/stats/', + 'inputfile' => '/Users/andreas/Desktop/stat2.log', +# 'inputfile' => '/Users/andreas/Desktop/simplesamlphp.stat.1', + 'offset' => 60*60*1, // Two hours offset to match epoch and norwegian winter time. + + 'statrules' => array( + 'sso_hoursday' => array( + 'name' => 'Numer of SP logins (per 15 minutes for one day)', + 'descr' => 'The number of Service Provider logins put into slots of one hour.', + + 'action' => 'saml20-sp-SSO', + 'col' => 7, // Service Provider EntityID + 'slot' => 60*15, // Slots of one hour + 'fileslot' => 60*60*24, // 7 days of data in each file + 'axislabelint' => 6*4, // Number of slots per label. 24 is one each day + + 'dateformat-period' => 'j. M', // 4. Mars + 'dateformat-intra' => 'j. M H:i', // 4. Mars 12:30 +# 'dateformat-intra' => 'j. H:i', // 4. Mars 12:30 + ), + 'sso_hoursweek' => array( + 'name' => 'Numer of SP logins (per hour)', + 'descr' => 'The number of Service Provider logins put into slots of one hour.', + + 'action' => 'saml20-sp-SSO', + 'col' => 7, // Service Provider EntityID + 'slot' => 60*60, // Slots of one hour + 'fileslot' => 60*60*24*7, // 7 days of data in each file + 'axislabelint' => 24, // Number of slots per label. 24 is one each day + + 'dateformat-period' => 'j. M', // 4. Mars + 'dateformat-intra' => 'j. M H:i', // 4. Mars 12:30 +# 'dateformat-intra' => 'j. H:i', // 4. Mars 12:30 + ), + 'sso_days' => array( + 'name' => 'Numer of SP logins (per day)', + 'descr' => 'The number of Service Provider logins put into slots of one day.', + + 'action' => 'saml20-sp-SSO', + 'col' => 7, // Service Provider EntityID + 'slot' => 60*60*24, // Slots of one day + 'fileslot' => 60*60*24*30, // 30 days of data in each file + 'axislabelint' => 7, // Number of slots per label. 24 is one each day + + 'dateformat-period' => 'j. M Y H:i', // 4. Mars + 'dateformat-intra' => 'j. M', // 4. Mars 12:30 +# 'dateformat-intra' => 'j. H:i', // 4. Mars 12:30 + ), + ), + +); + +?> \ No newline at end of file diff --git a/modules/statistics/default-disable b/modules/statistics/default-disable new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/modules/statistics/hooks/hook_frontpage.php b/modules/statistics/hooks/hook_frontpage.php new file mode 100644 index 0000000000000000000000000000000000000000..3d3fdd040fc031c827bfc3ac3e710d3d11047272 --- /dev/null +++ b/modules/statistics/hooks/hook_frontpage.php @@ -0,0 +1,17 @@ +<?php +/** + * Hook to add the modinfo module to the frontpage. + * + * @param array &$links The links on the frontpage, split into sections. + */ +function statistics_hook_frontpage(&$links) { + assert('is_array($links)'); + assert('array_key_exists("links", $links)'); + + $links['links'][] = array( + 'href' => SimpleSAML_Module::getModuleURL('statistics/showstats.php'), + 'text' => 'Show statistics', + ); + +} +?> \ No newline at end of file diff --git a/modules/statistics/templates/default/statistics-tpl.php b/modules/statistics/templates/default/statistics-tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..c6f6de98cc3676ca63a6b1501d3c973527bf1d9c --- /dev/null +++ b/modules/statistics/templates/default/statistics-tpl.php @@ -0,0 +1,113 @@ +<?php +$this->data['header'] = 'Statistics'; +$this->includeAtTemplateBase('includes/header.php'); + +echo('<div id="content">'); +echo('<h1>'. $this->data['available.rules'][$this->data['selected.rule']]['name'] . '</h1>'); +echo('<p>' . $this->data['available.rules'][$this->data['selected.rule']]['descr'] . '</p>'); + +echo '<div class="selecttime" style="border: 1px solid #999; background: #ccc; margin: .5em; padding: .5em">'; + + + + +echo '<div style="display: inline">'; +echo '<form style="display: inline"><select onChange="submit();" name="rule">'; +foreach ($this->data['available.rules'] AS $key => $rule) { + if ($key === $this->data['selected.rule']) { + echo '<option selected="selected" value="' . $key . '">' . $rule['name'] . '</option>'; + } else { + echo '<option value="' . $key . '">' . $rule['name'] . '</option>'; + } +} +echo '</select></form>'; +echo '</div>'; + + + +echo '<div style="display: inline">'; +echo '<form style="display: inline">'; +echo '<input type="hidden" name="rule" value="' . $this->data['selected.rule'] . '" />'; +echo '<select onChange="submit();" name="time">'; +foreach ($this->data['available.times'] AS $key => $timedescr) { + if ($key == $this->data['selected.time']) { + echo '<option selected="selected" value="' . $key . '">' . $timedescr . '</option>'; + } else { + echo '<option value="' . $key . '">' . $timedescr . '</option>'; + } +} +echo '</select></form>'; +echo '</div>'; + + +echo '<div style="display: inline">'; +echo '<form style="display: inline">'; +echo '<input type="hidden" name="rule" value="' . $this->data['selected.rule'] . '" />'; +echo '<input type="hidden" name="time" value="' . $this->data['selected.time'] . '" />'; +echo '<select onChange="submit();" name="d">'; +foreach ($this->data['availdelimiters'] AS $key => $delim) { + if ($key == '_') { + echo '<option value="_">Total</option>'; + } elseif ($delim == $_REQUEST['d']) { + echo '<option selected="selected" value="' . $delim . '">' . $delim . '</option>'; + } else { + echo '<option value="' . $delim . '">' . $delim . '</option>'; + } +} +echo '</select></form>'; +echo '</div>'; + + +echo '<br style="clear: both; height: 0px">'; +echo '</div>'; + + + + + +echo '<img src="' . htmlspecialchars($this->data['imgurl']) . '" />'; + + + + + + + + +#echo $this->data['selected.time']; + + + + + + +echo '<h3>Debug information</h3>'; +echo '<input style="width: 80%" value="' . htmlspecialchars($this->data['imgurl']) . '" />'; + +echo '<table style="">'; +foreach ($this->data['debugdata'] AS $dd) { + echo '<tr><td style="padding-right: 2em; border: 1px solid #ccc">' . $dd[0] . '</td><td style="padding-right: 2em; border: 1px solid #ccc">' . $dd[1] . '</td></tr>'; +} +echo '</table>'; +// +// if (count($this->data['sources']) === 0) { +// echo('<p>' . $this->t('{aggregator:dict:no_aggregators}') . '</p>'); +// } else { +// +// echo('<ul>'); +// +// foreach ($this->data['sources'] as $source) { +// $encId = urlencode($source); +// $encName = htmlspecialchars($source); +// echo('<li>'); +// echo('<a href="?id=' . $encId . '">' . $encName . '</a>'); +// echo(' <a href="?id=' . $encId . '&mimetype=text/plain">[' . $this->t('{aggregator:dict:text}') . ']</a>'); +// echo(' <a href="?id=' . $encId . '&mimetype=application/xml">[xml]</a>'); +// echo('</li>'); +// } +// +// echo('</ul>'); +// } + +$this->includeAtTemplateBase('includes/footer.php'); +?> \ No newline at end of file diff --git a/modules/statistics/www/showstats.php b/modules/statistics/www/showstats.php new file mode 100644 index 0000000000000000000000000000000000000000..92246198f918c26c717afad6760385be5e2f0e4b --- /dev/null +++ b/modules/statistics/www/showstats.php @@ -0,0 +1,216 @@ +<?php + + +function encodeaxis($axis) { + return join('|', $axis); +} +# t:10.0,58.0,95.0 +function encodedata($data) { + return 't:' . join(',', $data); +} + +function show($axis, $axispos, $values, $max) { + + $nv = count($values); + + $url = 'http://chart.apis.google.com/chart?' . + 'chs=800x250' . + '&chd=' . encodedata($values) . + '&cht=lc' . + '&chxt=x,y' . + '&chxl=0:|' . encodeaxis($axis) . # . $'|1:||top' . + '&chxp=0,' . join(',', $axispos) . +# '&chxp=0,0.3,0.4' . + '&chxr=0,0,1|1,0,' . $max . +# '&chm=R,CCCCCC,0,0.25,0.5' . + '&chg=' . (2400/(count($values)-1)) . ',20,3,3'; // lines + + return $url; +} + +function prettydate($timeslot, $granularity, $offset, $dateformat) { +# echo 'date: [' . $dateformat . date($dateformat, $timeslot*$granularity-$offset) . ']'; + return date($dateformat, $timeslot*$granularity-$offset); +} + +function roof($in) { + if ($in < 1) return 1; + $base = log10($in); + $r = ceil(5*$in / pow(10, ceil($base))); + return ($r/5)*pow(10, ceil($base)); +} + +// $foo = array(0, 2, 2.3, 2.6, 6, 10, 15, 98, 198, 256, 487, 563, 763, 801, 899, 999, 987, 198234.485, 283746); +// foreach ($foo AS $f) { +// echo '<p>' . $f . ' => ' . roof($f); +// } +// exit; + + +$config = SimpleSAML_Configuration::getInstance(); +$statconfig = $config->copyFromBase('statconfig', 'statistics.php'); + + +$statdir = $statconfig->getValue('statdir'); +$offset = $statconfig->getValue('offset'); +$inputfile = $statconfig->getValue('inputfile'); + +$statrules = $statconfig->getValue('statrules'); + + + +if (!is_dir($statdir)) + throw new Exception('Statisics output directory [' . $statdir . '] does not exists.'); +$filelist = scandir($statdir); + +$available = array(); +foreach ($filelist AS $file) { + if (preg_match('/([a-z_]+)-([0-9]+)\.stat/', $file, $matches)) { + + if (array_key_exists($matches[1], $statrules)) { + $available[$matches[1]][] = $matches[2]; + } + } +} + +$available_rules = array(); +foreach ($available AS $key => $av) { + $available_rules[$key] = array('name' => $statrules[$key]['name'], 'descr' => $statrules[$key]['descr']); +} + +$availrulenames = array_keys($available_rules); +$rule = $availrulenames[0]; +if(array_key_exists('rule', $_GET)) { + if (array_key_exists($_GET['rule'], $available_rules)) { + $rule = $_GET['rule']; + } +} + +$available_times = array(); +foreach ($available[$rule] AS $slot) { + $available_times[$slot] = prettydate($slot, $statrules[$rule]['fileslot'], $offset, $statrules[$rule]['dateformat-period']) . ' to ' . + prettydate($slot+1, $statrules[$rule]['fileslot'], $offset, $statrules[$rule]['dateformat-period']); +} + +#print_r($available_times); exit; + +$fileslot = $available[$rule][count($available[$rule])-1]; + +if (array_key_exists('time', $_GET)) { + if (in_array($_GET['time'], $available[$rule])) { + $fileslot = $_GET['time']; + } +} + +#echo 'fileslot: ' . $fileslot; exit; +#echo '<pre>'; print_r($available_rules); exit; +#echo '<pre>'; print_r($available); exit; + + +$resultfile = file_get_contents($statdir . $rule . '-' . $fileslot . '.stat'); +$results = unserialize($resultfile); + + +// echo '<html><body><pre>'; +// print_r($results); +// echo '</pre>'; + +$dataset = array(); +$axis = array(); +$axispos = array(); +$max = 15; + + +/* + * Get rule specific configuration from the configuration file. + */ +$slotsize = $statrules[$rule]['slot']; +$dateformat_period = $statrules[$rule]['dateformat-period']; +$dateformat_intra = $statrules[$rule]['dateformat-intra']; +$axislabelint = $statrules[$rule]['axislabelint']; + +$delimiter = '_'; +if (isset($_REQUEST['d'])) { + $delimiter = $_REQUEST['d']; +} + +$maxvalue = 0; +$debugdata = array(); +foreach($results AS $slot => $res) { + $maxvalue = max($res[$delimiter],$maxvalue); + $debugdata[] = array( + prettydate($slot, $statrules[$rule]['slot'], $offset, $statrules[$rule]['dateformat-intra']), + $res[$delimiter] + ); +} +$max = roof($maxvalue); + +#echo '<pre>'; print_r($debugdata); exit; + +$availdelimiters = array(); + +$lastslot = 0; +$xentries = count($results); +$i = 0; +foreach($results AS $slot => $res) { + + #echo '<p>' . date($dateformat, $slot*$granularity) . ': ' . (isset($results[$slot]) ? $results[$slot] : 0); + + $dataset[] = 100*$res[$delimiter] / $max; + foreach(array_keys($res) AS $nd) $availdelimiters[$nd] = 1; + + #$dataset[] = (isset($results[$slot]) ? round(($results[$slot]*$perseconds/($granularity*$max))*100) : 0); + if ($slot % $axislabelint == 0) { + $axis[] = date($dateformat_intra, $slot*$slotsize - $offset); + $axispos[] = (($i)/($xentries-1)); + #echo "<p> ". $slot . " = " . date($dateformat_intra, ($slot*$slotsize - $offset) ) . " "; + } + #echo "<p> ". $slot . " = " . date($dateformat_intra, ($slot*$slotsize - $offset) ) . " "; + $lastslot = $slot; + $i++; +} +$axis[] = date($dateformat_intra, ($lastslot*$slotsize) + $slotsize); +#echo "<p> ". ($lastslot+1) . " = " . date($dateformat_intra, (($lastslot+1)*$slotsize - $offset) ) . " "; + +#print_r($axis); + +// echo '<input value="' . htmlspecialchars(show($axis, $dataset, $max)) . '" />'; +// echo '<img src="' . htmlspecialchars() . '" />'; + +$t = new SimpleSAML_XHTML_Template($config, 'statistics:statistics-tpl.php'); +$t->data['header'] = 'stat'; +$t->data['imgurl'] = show($axis, $axispos, $dataset, $max); +$t->data['available.rules'] = $available_rules; +$t->data['available.times'] = $available_times; +$t->data['selected.rule']= $rule; +$t->data['selected.time'] = $fileslot; +$t->data['debugdata'] = $debugdata; +$t->data['availdelimiters'] = array_keys($availdelimiters); +$t->show(); + + +// $slotlist = array_keys($results); +// $start = $slotlist[0]; +// $end = $slotlist[count($results)-1]; +// +// #echo 'from slot ' . $start . ' to ' . $end; +// +// $dataset = array(); +// $axis = array(); +// $max = 10; +// +// $perseconds = 60; +// +// for ($slot = $start; $slot <= $end; $slot++) { +// #echo '<p>' . date($dateformat, $slot*$granularity) . ': ' . (isset($results[$slot]) ? $results[$slot] : 0); +// +// $dataset[] = (isset($results[$slot]) ? round(($results[$slot]*$perseconds/($granularity*$max))*100) : 0); +// if ($slot % 3 == 0) +// $axis[] = date($dateformat, $slot*$granularity); +// } +// +// echo '<input value="' . htmlspecialchars(show($axis, $dataset)) . '" />'; +// echo '<img src="' . htmlspecialchars(show($axis, $dataset, $max)) . '" />'; + + +?> \ No newline at end of file