ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
DeduplicationHandler.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the Monolog package.
5  *
6  * (c) Jordi Boggiano <j.boggiano@seld.be>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11 
12 namespace Monolog\Handler;
13 
14 use Monolog\Logger;
15 
37 {
42 
47 
51  protected $time;
52 
56  private $gc = false;
57 
66  {
67  parent::__construct($handler, 0, Logger::DEBUG, $bubble, false);
68 
69  $this->deduplicationStore = $deduplicationStore === null ? sys_get_temp_dir() . '/monolog-dedup-' . substr(md5(__FILE__), 0, 20) .'.log' : $deduplicationStore;
70  $this->deduplicationLevel = Logger::toMonologLevel($deduplicationLevel);
71  $this->time = $time;
72  }
73 
74  public function flush()
75  {
76  if ($this->bufferSize === 0) {
77  return;
78  }
79 
80  $passthru = null;
81 
82  foreach ($this->buffer as $record) {
83  if ($record['level'] >= $this->deduplicationLevel) {
84 
85  $passthru = $passthru || !$this->isDuplicate($record);
86  if ($passthru) {
87  $this->appendRecord($record);
88  }
89  }
90  }
91 
92  // default of null is valid as well as if no record matches duplicationLevel we just pass through
93  if ($passthru === true || $passthru === null) {
94  $this->handler->handleBatch($this->buffer);
95  }
96 
97  $this->clear();
98 
99  if ($this->gc) {
100  $this->collectLogs();
101  }
102  }
103 
104  private function isDuplicate(array $record)
105  {
106  if (!file_exists($this->deduplicationStore)) {
107  return false;
108  }
109 
110  $store = file($this->deduplicationStore, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
111  if (!is_array($store)) {
112  return false;
113  }
114 
115  $yesterday = time() - 86400;
116  $timestampValidity = $record['datetime']->getTimestamp() - $this->time;
117  $expectedMessage = preg_replace('{[\r\n].*}', '', $record['message']);
118 
119  for ($i = count($store) - 1; $i >= 0; $i--) {
120  list($timestamp, $level, $message) = explode(':', $store[$i], 3);
121 
122  if ($level === $record['level_name'] && $message === $expectedMessage && $timestamp > $timestampValidity) {
123  return true;
124  }
125 
126  if ($timestamp < $yesterday) {
127  $this->gc = true;
128  }
129  }
130 
131  return false;
132  }
133 
134  private function collectLogs()
135  {
136  if (!file_exists($this->deduplicationStore)) {
137  return false;
138  }
139 
140  $handle = fopen($this->deduplicationStore, 'rw+');
141  flock($handle, LOCK_EX);
142  $validLogs = array();
143 
144  $timestampValidity = time() - $this->time;
145 
146  while (!feof($handle)) {
147  $log = fgets($handle);
148  if (substr($log, 0, 10) >= $timestampValidity) {
149  $validLogs[] = $log;
150  }
151  }
152 
153  ftruncate($handle, 0);
154  rewind($handle);
155  foreach ($validLogs as $log) {
156  fwrite($handle, $log);
157  }
158 
159  flock($handle, LOCK_UN);
160  fclose($handle);
161 
162  $this->gc = false;
163  }
164 
165  private function appendRecord(array $record)
166  {
167  file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . preg_replace('{[\r\n].*}', '', $record['message']) . "\n", FILE_APPEND);
168  }
169 }
const DEBUG
Detailed debug information.
Definition: Logger.php:33
__construct(HandlerInterface $handler, $deduplicationStore=null, $deduplicationLevel=Logger::ERROR, $time=60, $bubble=true)
const ERROR
Runtime errors.
Definition: Logger.php:58
$log
Definition: sabredav.php:21
static toMonologLevel($level)
Converts PSR-3 levels to Monolog ones if necessary.
Definition: Logger.php:528
Buffers all records until closing the handler and then pass them as batch.
if(! $oauthconfig->getBoolean('getUserInfo.enable', FALSE)) $store
Definition: getUserInfo.php:11
catch(Exception $e) $message
Simple handler wrapper that deduplicates log records across multiple requests.
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
$i
Definition: disco.tpl.php:19
Interface that all Monolog Handlers must implement.
clear()
Clears the buffer without flushing any messages down to the wrapped handler.