Skip to content

Commit 968c027

Browse files
authored
Merge pull request #5684 from paulbalandan/refactor-exception-logging
Improve exception logging
2 parents f8267cb + 825534e commit 968c027

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

system/Debug/Exceptions.php

Lines changed: 56 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,55 @@ 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+
case is_string($value):
471+
return var_export(clean_path($value), true);
472+
473+
default:
474+
return var_export($value, true);
475+
}
476+
}, $frame['args']));
477+
478+
$backtraces[] = sprintf(
479+
'%s %s: %s%s%s(%s)',
480+
$idx,
481+
clean_path($frame['file']),
482+
$frame['class'],
483+
$frame['type'],
484+
$frame['function'],
485+
$args
486+
);
487+
}
488+
489+
return implode("\n", $backtraces);
490+
}
437491
}

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
}

user_guide_src/source/changelogs/v4.2.0.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ Enhancements
2929
- Added new OCI8 driver for database.
3030
- It can access Oracle Database and supports SQL and PL/SQL statements.
3131
- The ``spark routes`` command now shows closure routes, auto routtes, and filters. See :ref:`URI Routing <spark-routes>`.
32+
- Exception information logged through ``log_message()`` has now improved. It now includes the file and line where the exception originated. It also does not truncate the message anymore.
33+
- The log format has also changed. If users are depending on the log format in their apps, the new log format is "<1-based count> <cleaned filepath>(<line>): <class><function><args>"
3234

3335
Changes
3436
*******

0 commit comments

Comments
 (0)