-
-
Notifications
You must be signed in to change notification settings - Fork 466
Expand file tree
/
Copy pathLogsHandler.php
More file actions
154 lines (133 loc) · 4.36 KB
/
LogsHandler.php
File metadata and controls
154 lines (133 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?php
declare(strict_types=1);
namespace Sentry\Monolog;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\HandlerInterface;
use Monolog\LogRecord;
use Sentry\Logs\LogLevel;
use Sentry\Logs\Logs;
class LogsHandler implements HandlerInterface
{
use CompatibilityLogLevelTrait;
/**
* The minimum logging level at which this handler will be triggered.
*
* @var LogLevel|\Monolog\Level|int
*/
private $logLevel;
/**
* Whether the messages that are handled can bubble up the stack or not.
*
* @var bool
*/
private $bubble;
/**
* Whether to include the channel name as an attribute in the Sentry logs.
*/
private bool $includeChannel;
/**
* Creates a new Monolog handler that converts Monolog logs to Sentry logs.
*
* @param LogLevel|\Monolog\Level|int|null $logLevel the minimum logging level at which this handler will be triggered and collects the logs
* @param bool $bubble whether the messages that are handled can bubble up the stack or not
* @param bool $includeChannel whether to include the channel name as an attribute in the Sentry logs
*/
public function __construct($logLevel = null, bool $bubble = true, bool $includeChannel = false)
{
$this->logLevel = $logLevel ?? LogLevel::debug();
$this->bubble = $bubble;
$this->includeChannel = $includeChannel;
}
/**
* @param array<string, mixed>|LogRecord $record
*/
public function isHandling($record): bool
{
if ($this->logLevel instanceof LogLevel) {
return self::getSentryLogLevelFromMonologLevel($record['level'])->getPriority() >= $this->logLevel->getPriority();
} elseif ($this->logLevel instanceof \Monolog\Level) {
return $record['level'] >= $this->logLevel->value;
}
return $record['level'] >= $this->logLevel;
}
/**
* @param array<string, mixed>|LogRecord $record
*/
public function handle($record): bool
{
if (!$this->isHandling($record)) {
return false;
}
// Do not collect logs for exceptions, they should be handled seperately by the `Handler` or `captureException`
if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
return false;
}
Logs::getInstance()->aggregator()->add(
self::getSentryLogLevelFromMonologLevel($record['level']),
$record['message'],
[],
$this->compileAttributes($record)
);
return $this->bubble === false;
}
/**
* @param array<array<string, mixed>|LogRecord> $records
*/
public function handleBatch(array $records): void
{
foreach ($records as $record) {
$this->handle($record);
}
}
public function close(): void
{
Logs::getInstance()->flush();
}
/**
* @param callable $callback
*/
public function pushProcessor($callback): void
{
// noop, this handler does not support processors
}
/**
* @return callable
*/
public function popProcessor()
{
// Since we do not support processors, we throw an exception if this method is called
throw new \LogicException('You tried to pop from an empty processor stack.');
}
public function setFormatter(FormatterInterface $formatter): void
{
// noop, this handler does not support formatters
}
public function getFormatter(): FormatterInterface
{
// To adhere to the interface we need to return a formatter so we return a default one
return new LineFormatter();
}
public function __destruct()
{
try {
$this->close();
} catch (\Throwable $e) {
// Just in case so that the destructor can never fail.
}
}
/**
* @param array<string,mixed>|LogRecord $record
*
* @return array<string,mixed>
*/
protected function compileAttributes($record): array
{
return array_merge(
$this->includeChannel ? ['channel' => $record['channel']] : [],
$record['context'],
$record['extra'],
['sentry.origin' => 'auto.log.monolog']
);
}
}