Skip to content

Commit a4d510f

Browse files
authored
Improve logging #2
1 parent a0a4d4f commit a4d510f

File tree

1 file changed

+108
-51
lines changed

1 file changed

+108
-51
lines changed

src/DiscordHandler.php

Lines changed: 108 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,29 @@
77
use Monolog\Formatter\LineFormatter;
88
use \Monolog\Logger;
99
use \Monolog\Handler\AbstractProcessingHandler;
10+
use Psr\Log\LogLevel;
1011

1112
class DiscordHandler extends AbstractProcessingHandler
1213
{
13-
private $initialized = false;
1414
private $guzzle;
15-
16-
private $name;
17-
private $subname;
18-
15+
private $suffix;
1916
private $webhook;
20-
private $statement;
21-
private $roleId;
22-
23-
/**
24-
* MonologDiscordHandler constructor.
25-
* @param $webhook
26-
* @param $name
27-
* @param string $subname
28-
* @param int $level
29-
* @param bool $bubble
30-
* @param null $roleId
31-
*/
32-
public function __construct($webhook, $name, $subname = '', $level = Logger::DEBUG, $bubble = true, $roleId = null)
17+
private $message;
18+
private $context;
19+
20+
/**
21+
* MonologDiscordHandler constructor.
22+
* @param array $config
23+
*/
24+
public function __construct($config)
3325
{
34-
$this->name = $name;
35-
$this->subname = $subname;
26+
$this->suffix = $config['suffix'] ?? '';
3627
$this->guzzle = new \GuzzleHttp\Client();
37-
$this->webhook = $webhook;
38-
$this->roleId = $roleId;
39-
parent::__construct($level, $bubble);
28+
$this->webhook = $config['webhook'] ?? false;
29+
$this->message = $config['message'] ?? false;
30+
$this->context = $config['context'] ?? false;
31+
parent::__construct($config['level'] ?? 'debug', $this->bubble);
32+
4033
}
4134

4235
/**
@@ -45,35 +38,99 @@ public function __construct($webhook, $name, $subname = '', $level = Logger::DEB
4538
*/
4639
protected function write($record): void
4740
{
48-
$formatter = new LineFormatter(null, null, true, true);
49-
$formatter->includeStacktraces();
50-
$content = $formatter->format($record);
51-
52-
// Set up the formatted log
53-
$log = [
54-
'embeds' => [
55-
[
56-
'title' => 'Log entry - '.now()->format('d.m.Y H:i:s'),
57-
// Use CSS for the formatter, as it provides the most distinct colouring.
58-
'description' => "```css\n" . substr($content, 0, 2030). '```',
59-
'color' => 0xE74C3C,
60-
],
61-
],
41+
$message = new LineFormatter('%message%', null, true, true);
42+
$message = $message->format($record);
43+
44+
if($this->context) {
45+
$stacktrace = new LineFormatter('%context% %extra%', null, true, true);
46+
$stacktrace->includeStacktraces();
47+
$stacktrace = $stacktrace->format($record);
48+
}
49+
50+
// Add emoji based on the error level
51+
switch ($record->level->toPsrLogLevel()) {
52+
case LogLevel::NOTICE:
53+
$emoji = ':helicopter:';
54+
break;
55+
case LogLevel::WARNING:
56+
$emoji = ':warning:';
57+
break;
58+
case LogLevel::INFO:
59+
$emoji = ':information_source:';
60+
break;
61+
case LogLevel::DEBUG:
62+
$emoji = ':zap:';
63+
break;
64+
default:
65+
$emoji = ':boom:';
66+
break;
67+
}
68+
69+
// Add fields
70+
$fields = [];
71+
72+
$request = request();
73+
74+
// Add the request url if any
75+
$request_url = $request?->fullUrl() ?? false;
76+
if ($request_url && !app()->runningInConsole()) {
77+
$fields[] = [
78+
'name' => 'Visited URL',
79+
'value' => $request?->fullUrl()
80+
];
81+
}
82+
83+
// Add the logged in user id if any
84+
$user_id = $record->context['userId'] ?? false;
85+
if ($user_id) {
86+
$fields[] = [
87+
'name' => 'User ID',
88+
'value' => $user_id
89+
];
90+
}
91+
92+
// Add the file path if exception
93+
if(isset($record->context['exception'])) {
94+
$file_path = $record->context['exception']->getFile() ?? false;
95+
$file_line = $record->context['exception']->getLine() ?? 'n/a';
96+
97+
if ($file_path) {
98+
$fields[] = [
99+
'name' => 'File path',
100+
'value' => '`' . str($file_path)->replace(base_path(), '') . '` at line **' . $file_line . '**'
101+
];
102+
}
103+
}
104+
105+
// Set embeds
106+
$log['embeds'][] = [
107+
'title' => '**[' . now()->format('d.m.Y H:i:s') . ']** '.str($record->level->getName())->lower()->ucfirst().' ' . $emoji.' '.$this->suffix,
108+
'description' => "```css\n" . str($message)->limit('4000') . '```',
109+
'color' => 0xE74C3C,
110+
'fields' => $fields
62111
];
63112

64-
// Tag a role if configured for it
65-
if($this->roleId) $log['content'] = "<@&" . $this->roleId . ">";
66-
67-
if($this->webhook) {
68-
try {
69-
// Send it to discord
70-
$this->guzzle->request('POST', $this->webhook, [
71-
RequestOptions::JSON => $log,
72-
]);
73-
} catch (\Exception $e) {
74-
//silently fail
75-
}
76-
}
113+
// Add full context
114+
if($this->context === true && $stacktrace) {
115+
$log['embeds'][] = [
116+
'title' => 'Full context',
117+
'description' => "```css\n" . str($stacktrace)->limit('4000') . '```',
118+
'color' => 0xE74C3C,
119+
];
120+
}
121+
122+
// Add custom message
123+
if ($this->message) $log['content'] = $this->message;
124+
125+
if ($this->webhook) {
126+
try {
127+
// Send it to discord
128+
$this->guzzle->request('POST', $this->webhook, [
129+
RequestOptions::JSON => $log,
130+
]);
131+
} catch (\Exception $e) {
132+
//silently fail better than killing the whole app
133+
}
134+
}
77135
}
78136
}
79-

0 commit comments

Comments
 (0)