Skip to content

Commit 491e505

Browse files
committed
Refactor exception logging
1 parent 7401ca9 commit 491e505

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

system/Debug/Exceptions.php

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,11 @@ public function exceptionHandler(Throwable $exception)
102102
[$statusCode, $exitCode] = $this->determineCodes($exception);
103103

104104
if ($this->config->log === true && ! in_array($statusCode, $this->config->ignoreCodes, true)) {
105-
log_message('critical', $exception->getMessage() . "\n{trace}", [
106-
'trace' => $exception->getTraceAsString(),
105+
log_message('critical', "{message}\nin {exFile} on line {exLine}.\n{trace}", [
106+
'message' => $exception->getMessage(),
107+
'exFile' => clean_path($exception->getFile()), // {file} refers to THIS file
108+
'exLine' => $exception->getLine(), // {line} refers to THIS line
109+
'trace' => self::renderBacktrace($exception->getTrace()),
107110
]);
108111
}
109112

@@ -434,4 +437,52 @@ public static function highlightFile(string $file, int $lineNumber, int $lines =
434437

435438
return '<pre><code>' . $out . '</code></pre>';
436439
}
440+
441+
private static function renderBacktrace(array $backtrace): string
442+
{
443+
$backtraces = [];
444+
445+
foreach ($backtrace as $index => $trace) {
446+
$frame = $trace + ['file' => '[internal function]', 'line' => '', 'class' => '', 'type' => '', 'args' => []];
447+
448+
if ($frame['file'] !== '[internal function]') {
449+
$frame['file'] = sprintf('%s(%s)', $frame['file'], $frame['line']);
450+
}
451+
452+
unset($frame['line']);
453+
$idx = $index;
454+
$idx = str_pad((string) ++$idx, 2, ' ', STR_PAD_LEFT);
455+
456+
$args = implode(', ', array_map(static function ($value): string {
457+
switch (true) {
458+
case is_object($value):
459+
return sprintf('Object(%s)', get_class($value));
460+
461+
case is_array($value):
462+
return $value !== [] ? '[...]' : '[]';
463+
464+
case $value === null:
465+
return 'null';
466+
467+
case is_resource($value):
468+
return sprintf('resource (%s)', get_resource_type($value));
469+
470+
default:
471+
return var_export($value, true);
472+
}
473+
}, $frame['args']));
474+
475+
$backtraces[] = sprintf(
476+
'%s %s: %s%s%s(%s)',
477+
$idx,
478+
clean_path($frame['file']),
479+
$frame['class'],
480+
$frame['type'],
481+
$frame['function'],
482+
$args
483+
);
484+
}
485+
486+
return implode("\n", $backtraces);
487+
}
437488
}

tests/system/Debug/ExceptionsTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,20 @@ public function testDetermineCodes(): void
6161
$this->assertSame([500, 1], $determineCodes(new RuntimeException('That.', 600)));
6262
$this->assertSame([404, 1], $determineCodes(new RuntimeException('There.', 404)));
6363
}
64+
65+
public function testRenderBacktrace(): void
66+
{
67+
$renderer = self::getPrivateMethodInvoker(Exceptions::class, 'renderBacktrace');
68+
$exception = new RuntimeException('This.');
69+
70+
$renderedBacktrace = $renderer($exception->getTrace());
71+
$renderedBacktrace = explode("\n", $renderedBacktrace);
72+
73+
foreach ($renderedBacktrace as $trace) {
74+
$this->assertMatchesRegularExpression(
75+
'/^\s*\d* .+(?:\(\d+\))?: \S+(?:(?:\->|::)\S+)?\(.*\)$/',
76+
$trace
77+
);
78+
}
79+
}
6480
}

0 commit comments

Comments
 (0)