1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Polder Knowledge / log-module (https://polderknowledge.com) |
4
|
|
|
* |
5
|
|
|
* @link https://github.com/polderknowledge/log-module for the canonical source repository |
6
|
|
|
* @copyright Copyright (c) 2016-2017 Polder Knowledge (https://polderknowledge.com) |
7
|
|
|
* @license https://github.com/polderknowledge/log-module/blob/master/LICENSE.md MIT |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace PolderKnowledge\LogModule\Monolog\Handler; |
11
|
|
|
|
12
|
|
|
use DateTime; |
13
|
|
|
use Monolog\Handler\AbstractProcessingHandler; |
14
|
|
|
use Monolog\Handler\HandlerInterface; |
15
|
|
|
use Monolog\Logger; |
16
|
|
|
|
17
|
|
|
final class CachedInterval extends AbstractProcessingHandler |
18
|
|
|
{ |
19
|
|
|
/** |
20
|
|
|
* The handler to call when flushing. |
21
|
|
|
* |
22
|
|
|
* @var HandlerInterface |
23
|
|
|
*/ |
24
|
|
|
private $handler; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* The interval in seconds before the cache is flushed. |
28
|
|
|
* |
29
|
|
|
* @var int |
30
|
|
|
*/ |
31
|
|
|
private $interval; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* The path to the file which should be used to cache the records. |
35
|
|
|
* |
36
|
|
|
* @var string |
37
|
|
|
*/ |
38
|
|
|
private $store; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Initializes a new instance of this class. |
42
|
|
|
* |
43
|
|
|
* @param HandlerInterface $handler |
44
|
|
|
* @param int $interval |
45
|
|
|
* @param string $store |
46
|
|
|
* @param int $level |
47
|
|
|
* @param bool $bubble |
48
|
|
|
*/ |
49
|
12 |
|
public function __construct( |
50
|
|
|
HandlerInterface $handler, |
51
|
|
|
int $interval, |
52
|
|
|
string $store = null, |
53
|
|
|
int $level = Logger::DEBUG, |
54
|
|
|
bool $bubble = true |
55
|
|
|
) { |
56
|
12 |
|
parent::__construct($level, $bubble); |
57
|
|
|
|
58
|
12 |
|
$this->handler = $handler; |
59
|
12 |
|
$this->interval = $interval; |
60
|
12 |
|
$this->store = $store ?? sys_get_temp_dir() . '/monolog-cachedinterval-' . substr(md5(__FILE__), 0, 20) .'.log'; |
61
|
12 |
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Writes the record down to the log of the implementing handler |
65
|
|
|
* |
66
|
|
|
* @param array $record |
67
|
|
|
* @return void |
68
|
|
|
*/ |
69
|
9 |
|
protected function write(array $record) |
70
|
|
|
{ |
71
|
|
|
// Remove the formatted context, it's not relevant for us. |
72
|
9 |
|
unset($record['formatted']); |
73
|
|
|
|
74
|
9 |
|
if ($this->isExpired()) { |
75
|
3 |
|
$this->flush(); |
76
|
|
|
} else { |
77
|
6 |
|
$this->appendLog($record); |
78
|
|
|
} |
79
|
9 |
|
} |
80
|
|
|
|
81
|
9 |
|
private function isExpired() |
82
|
|
|
{ |
83
|
9 |
|
if (!file_exists($this->store)) { |
84
|
3 |
|
return false; |
85
|
|
|
} |
86
|
|
|
|
87
|
6 |
|
$lines = file($this->store); |
88
|
|
|
|
89
|
6 |
|
if (!$lines) { |
|
|
|
|
90
|
3 |
|
return false; |
91
|
|
|
} |
92
|
|
|
|
93
|
3 |
|
$log = unserialize($lines[0]); |
94
|
|
|
|
95
|
|
|
/** @var DateTime $logDate */ |
96
|
3 |
|
$logDate = $log['datetime']; |
97
|
|
|
|
98
|
3 |
|
return $logDate->getTimestamp() + $this->interval < time(); |
99
|
|
|
} |
100
|
|
|
|
101
|
3 |
|
private function flush() |
102
|
|
|
{ |
103
|
3 |
|
$lines = file($this->store); |
104
|
|
|
|
105
|
3 |
|
$logs = []; |
106
|
|
|
|
107
|
3 |
|
foreach ($lines as $line) { |
108
|
3 |
|
$logs[] = unserialize($line); |
109
|
|
|
} |
110
|
|
|
|
111
|
3 |
|
$this->handler->handleBatch($logs); |
112
|
|
|
|
113
|
3 |
|
unlink($this->store); |
114
|
3 |
|
} |
115
|
|
|
|
116
|
6 |
|
private function appendLog(array $record) |
117
|
|
|
{ |
118
|
6 |
|
file_put_contents($this->store, serialize($record) . "\n", FILE_APPEND); |
119
|
6 |
|
} |
120
|
|
|
} |
121
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.