ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Aggregator.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Andreas Åkre Solberg <andreas.solberg@uninett.no>
4  * @package SimpleSAMLphp
5  */
7 {
8  private $statconfig;
9  private $statdir;
10  private $inputfile;
11  private $statrules;
12  private $offset;
13  private $metadata;
14  private $fromcmdline;
15  private $starttime;
16  private $timeres;
17 
21  public function __construct($fromcmdline = false)
22  {
23  $this->fromcmdline = $fromcmdline;
24  $this->statconfig = SimpleSAML_Configuration::getConfig('module_statistics.php');
25 
26  $this->statdir = $this->statconfig->getValue('statdir');
27  $this->inputfile = $this->statconfig->getValue('inputfile');
28  $this->statrules = $this->statconfig->getValue('statrules');
29  $this->timeres = $this->statconfig->getValue('timeres');
30  $this->offset = $this->statconfig->getValue('offset', 0);
31  $this->metadata = null;
32 
33  $this->starttime = time();
34  }
35 
36  public function dumpConfig()
37  {
38  echo 'Statistics directory : ' . $this->statdir . "\n";
39  echo 'Input file : ' . $this->inputfile . "\n";
40  echo 'Offset : ' . $this->offset . "\n";
41  }
42 
43  public function debugInfo()
44  {
45  echo 'Memory usage : ' . number_format(memory_get_usage() / (1024*1024), 2) . " MB\n";
46  }
47 
48  public function loadMetadata()
49  {
50  $filename = $this->statdir . '/.stat.metadata';
51  $metadata = null;
52  if (file_exists($filename)) {
53  $metadata = unserialize(file_get_contents($filename));
54  }
55  $this->metadata = $metadata;
56  }
57 
58  public function getMetadata()
59  {
60  return $this->metadata;
61  }
62 
63  public function saveMetadata()
64  {
65  $this->metadata['time'] = time() - $this->starttime;
66  $this->metadata['memory'] = memory_get_usage();
67  $this->metadata['lastrun'] = time();
68 
69  $filename = $this->statdir . '/.stat.metadata';
70  file_put_contents($filename, serialize($this->metadata), LOCK_EX);
71  }
72 
73  public function aggregate($debug = false) {
74  $this->loadMetadata();
75 
76  if (!is_dir($this->statdir)) {
77  throw new Exception('Statistics module: output dir do not exists [' . $this->statdir . ']');
78  }
79 
80  if (!file_exists($this->inputfile)) {
81  throw new Exception('Statistics module: input file do not exists [' . $this->inputfile . ']');
82  }
83 
84  $file = fopen($this->inputfile, 'r');
85 
86  if ($file === false) {
87  throw new Exception('Statistics module: unable to open file [' . $this->inputfile . ']');
88  }
89 
90  $logparser = new sspmod_statistics_LogParser(
91  $this->statconfig->getValue('datestart', 0), $this->statconfig->getValue('datelength', 15), $this->statconfig->getValue('offsetspan', 44)
92  );
93  $datehandler = array(
94  'default' => new sspmod_statistics_DateHandler($this->offset),
95  'month' => new sspmod_statistics_DateHandlerMonth($this->offset),
96  );
97 
98  $notBefore = 0;
99  $lastRead = 0;
100  $lastlinehash = '-';
101 
102  if (isset($this->metadata)) {
103  $notBefore = $this->metadata['notBefore'];
104  $lastlinehash = $this->metadata['lastlinehash'];
105  }
106 
107  $lastlogline = 'sdfsdf';
108  $lastlineflip = false;
109  $results = array();
110 
111  $i = 0;
112  // Parse through log file, line by line
113  while (!feof($file)) {
114  $logline = fgets($file, 4096);
115 
116  // Continue if STAT is not found on line
117  if (!preg_match('/STAT/', $logline)) {
118  continue;
119  }
120 
121  $i++;
122  $lastlogline = $logline;
123 
124  // Parse log, and extract epoch time and rest of content.
125  $epoch = $logparser->parseEpoch($logline);
126  $content = $logparser->parseContent($logline);
127  $action = trim($content[5]);
128 
129  if ($this->fromcmdline && ($i % 10000) == 0) {
130  echo("Read line " . $i . "\n");
131  }
132 
133  if ($debug) {
134  echo("----------------------------------------\n");
135  echo('Log line: ' . $logline . "\n");
136  echo('Date parse [' . substr($logline, 0, $this->statconfig->getValue('datelength', 15)) . '] to [' . date(DATE_RFC822, $epoch) . ']' . "\n");
137  echo htmlentities(print_r($content, true));
138  if ($i >= 13) {
139  exit;
140  }
141  }
142 
143  if ($epoch > $lastRead) {
144  $lastRead = $epoch;
145  }
146 
147  if ($epoch === $notBefore) {
148  if (!$lastlineflip) {
149  if (sha1($logline) === $lastlinehash) {
150  $lastlineflip = true;
151  }
152  continue;
153  }
154  }
155 
156  if ($epoch < $notBefore) {
157  continue;
158  }
159 
160  // Iterate all the statrules from config.
161  foreach ($this->statrules as $rulename => $rule) {
162  $type = 'aggregate';
163 
164  if (array_key_exists('type', $rule)) {
165  $type = $rule['type'];
166  }
167 
168  if ($type !== 'aggregate') {
169  continue;
170  }
171 
172  foreach ($this->timeres as $tres => $tresconfig ) {
173  $dh = 'default';
174  if (isset($tresconfig['customDateHandler'])) {
175  $dh = $tresconfig['customDateHandler'];
176  }
177 
178  $timeslot = $datehandler['default']->toSlot($epoch, $tresconfig['slot']);
179  $fileslot = $datehandler[$dh]->toSlot($epoch, $tresconfig['fileslot']);
180 
181  if (isset($rule['action']) && ($action !== $rule['action'])) {
182  continue;
183  }
184 
185  $difcol = self::getDifCol($content, $rule['col']);
186 
187  if (!isset($results[$rulename][$tres][$fileslot][$timeslot]['_'])) {
188  $results[$rulename][$tres][$fileslot][$timeslot]['_'] = 0;
189  }
190  if (!isset($results[$rulename][$tres][$fileslot][$timeslot][$difcol])) {
191  $results[$rulename][$tres][$fileslot][$timeslot][$difcol] = 0;
192  }
193 
194  $results[$rulename][$tres][$fileslot][$timeslot]['_']++;
195  $results[$rulename][$tres][$fileslot][$timeslot][$difcol]++;
196  }
197  }
198  }
199  $this->metadata['notBefore'] = $lastRead;
200  $this->metadata['lastline'] = $lastlogline;
201  $this->metadata['lastlinehash'] = sha1($lastlogline);
202  return $results;
203  }
204 
205  private static function getDifCol($content, $colrule)
206  {
207  if (is_int($colrule)) {
208  return trim($content[$colrule]);
209  } elseif (is_array($colrule)) {
210  $difcols = array();
211  foreach ($colrule as $cr) {
212  $difcols[] = trim($content[$cr]);
213  }
214  return join('|', $difcols);
215  } else {
216  return 'NA';
217  }
218  }
219 
220  private function cummulateData($previous, $newdata)
221  {
222  $dataset = array();
223  foreach (func_get_args() as $item) {
224  foreach ($item as $slot => $dataarray) {
225  if (!array_key_exists($slot, $dataset)) {
226  $dataset[$slot] = array();
227  }
228  foreach ($dataarray as $key => $data) {
229  if (!array_key_exists($key, $dataset[$slot])) {
230  $dataset[$slot][$key] = 0;
231  }
232  $dataset[$slot][$key] += $data;
233  }
234  }
235  }
236  return $dataset;
237  }
238 
239  public function store($results)
240  {
241  $datehandler = array(
242  'default' => new sspmod_statistics_DateHandler($this->offset),
243  'month' => new sspmod_statistics_DateHandlerMonth($this->offset),
244  );
245 
246  // Iterate the first level of results, which is per rule, as defined in the config.
247  foreach ($results as $rulename => $timeresdata) {
248  // Iterate over time resolutions
249  foreach ($timeresdata as $tres => $resres) {
250  $dh = 'default';
251  if (isset($this->timeres[$tres]['customDateHandler'])) {
252  $dh = $this->timeres[$tres]['customDateHandler'];
253  }
254 
255  $filenos = array_keys($resres);
256  $lastfile = $filenos[count($filenos) - 1];
257 
258  // Iterate the second level of results, which is the fileslot.
259  foreach ($resres as $fileno => $fileres) {
260  // Slots that have data.
261  $slotlist = array_keys($fileres);
262 
263  // The last slot.
264  $maxslot = $slotlist[count($slotlist) - 1];
265 
266  // Get start and end slot number within the file, based on the fileslot.
267  $start = (int)$datehandler['default']->toSlot(
268  $datehandler[$dh]->fromSlot($fileno, $this->timeres[$tres]['fileslot']),
269  $this->timeres[$tres]['slot']
270  );
271  $end = (int)$datehandler['default']->toSlot(
272  $datehandler[$dh]->fromSlot($fileno+1, $this->timeres[$tres]['fileslot']),
273  $this->timeres[$tres]['slot']
274  );
275 
276  // Fill in missing entries and sort file results
277  $filledresult = array();
278  for ($slot = $start; $slot < $end; $slot++) {
279  if (array_key_exists($slot, $fileres)) {
280  $filledresult[$slot] = $fileres[$slot];
281  } else {
282  if ($lastfile == $fileno && $slot > $maxslot) {
283  $filledresult[$slot] = array('_' => null);
284  } else {
285  $filledresult[$slot] = array('_' => 0);
286  }
287  }
288  }
289 
290  $filename = $this->statdir . '/' . $rulename . '-' . $tres . '-' . $fileno . '.stat';
291  if (file_exists($filename)) {
292  $previousData = unserialize(file_get_contents($filename));
293  $filledresult = $this->cummulateData($previousData, $filledresult);
294  }
295 
296  // store file
297  file_put_contents($filename, serialize($filledresult), LOCK_EX);
298  }
299  }
300  }
301  $this->saveMetadata();
302  }
303 }
cummulateData($previous, $newdata)
Definition: Aggregator.php:220
$action
$type
$fileslot
Definition: showstats.php:78
$start
Definition: bench.php:8
$rule
Definition: showstats.php:43
__construct($fromcmdline=false)
Constructor.
Definition: Aggregator.php:21
static getConfig($filename='config.php', $configSet='simplesaml')
Load a configuration file from a configuration set.
$filename
Definition: buildRTE.php:89
exit
Definition: backend.php:16
$results
Definition: svg-scanner.php:47
static getDifCol($content, $colrule)
Definition: Aggregator.php:205
$i
Definition: disco.tpl.php:19
$key
Definition: croninfo.php:18
$data
Definition: bench.php:6