Skip to content

Commit fb9a311

Browse files
committed
normalize Throwable only in the exception context key per PSR-3
1 parent f01de0f commit fb9a311

File tree

5 files changed

+45
-23
lines changed

5 files changed

+45
-23
lines changed

app/Config/Logger.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ class Logger extends BaseConfig
7373
* --------------------------------------------------------------------------
7474
*
7575
* When enabled, context keys not used as placeholders in the message are
76-
* passed to handlers as structured data. Any Throwable instances found in
77-
* the context are automatically normalized to an array representation.
76+
* passed to handlers as structured data. Per PSR-3, any ``Throwable`` instance
77+
* in the ``exception`` key is automatically normalized to an array representation.
7878
*/
7979
public bool $logContext = false;
8080

@@ -83,8 +83,8 @@ class Logger extends BaseConfig
8383
* Whether to include the stack trace for Throwables in context
8484
* --------------------------------------------------------------------------
8585
*
86-
* When enabled, the stack trace is included when a Throwable is found in
87-
* the context and normalized. Only relevant when $logContext is true.
86+
* When enabled, the stack trace is included when normalizing a Throwable
87+
* in the ``exception`` context key. Only relevant when $logContext is true.
8888
*/
8989
public bool $logContextTrace = false;
9090

system/Log/Logger.php

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -334,30 +334,32 @@ public function log($level, string|Stringable $message, array $context = []): vo
334334

335335
/**
336336
* Normalizes context values for structured logging.
337-
* Converts any Throwable instances into an array representation.
337+
* Per PSR-3, if an Exception is given to produce a stack trace, it MUST be
338+
* in a key named "exception". Only that key is converted into an array
339+
* representation.
338340
*
339341
* @param array<string, mixed> $context
340342
*
341343
* @return array<string, mixed>
342344
*/
343345
protected function normalizeContext(array $context): array
344346
{
345-
foreach ($context as $key => $value) {
346-
if ($value instanceof Throwable) {
347-
$normalized = [
348-
'class' => $value::class,
349-
'message' => $value->getMessage(),
350-
'code' => $value->getCode(),
351-
'file' => clean_path($value->getFile()),
352-
'line' => $value->getLine(),
353-
];
354-
355-
if ($this->logContextTrace) {
356-
$normalized['trace'] = $value->getTraceAsString();
357-
}
358-
359-
$context[$key] = $normalized;
347+
if (isset($context['exception']) && $context['exception'] instanceof Throwable) {
348+
$value = $context['exception'];
349+
350+
$normalized = [
351+
'class' => $value::class,
352+
'message' => $value->getMessage(),
353+
'code' => $value->getCode(),
354+
'file' => clean_path($value->getFile()),
355+
'line' => $value->getLine(),
356+
];
357+
358+
if ($this->logContextTrace) {
359+
$normalized['trace'] = $value->getTraceAsString();
360360
}
361+
362+
$context['exception'] = $normalized;
361363
}
362364

363365
return $context;

tests/system/Log/LoggerTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,25 @@ public function testLogContextNormalizesThrowable(): void
590590
$this->assertArrayNotHasKey('trace', $normalized);
591591
}
592592

593+
public function testLogContextDoesNotNormalizeThrowableUnderArbitraryKey(): void
594+
{
595+
$config = new LoggerConfig();
596+
$config->logContext = true;
597+
598+
$logger = new Logger($config);
599+
600+
try {
601+
throw new RuntimeException('Something went wrong');
602+
} catch (RuntimeException $e) {
603+
$logger->log('error', 'An error occurred', ['error' => $e]);
604+
}
605+
606+
$contexts = TestHandler::getContexts();
607+
608+
// Per PSR-3, only the 'exception' key is normalized; other keys are left as-is.
609+
$this->assertInstanceOf(RuntimeException::class, $contexts[0]['error']);
610+
}
611+
593612
public function testLogContextNormalizesThrowableWithTrace(): void
594613
{
595614
$config = new LoggerConfig();

user_guide_src/source/changelogs/v4.8.0.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ Libraries
176176

177177
- **Context**: This new feature allows you to easily set and retrieve normal or hidden contextual data for the current request. See :ref:`Context <context>` for details.
178178
- **Logging:** Log handlers now receive the full context array as a third argument to ``handle()``. When ``$logGlobalContext`` is enabled, the CI global context is available under the ``HandlerInterface::GLOBAL_CONTEXT_KEY`` key. Built-in handlers append it to the log output; custom handlers can use it for structured logging.
179-
- **Logging:** Added :ref:`per-call context logging <logging-per-call-context>` with three new ``Config\Logger`` options (``$logContext``, ``$logContextTrace``, ``$logContextUsedKeys``). ``Throwable`` instances in context are automatically normalized to a meaningful array. All options default to ``false``.
179+
- **Logging:** Added :ref:`per-call context logging <logging-per-call-context>` with three new ``Config\Logger`` options (``$logContext``, ``$logContextTrace``, ``$logContextUsedKeys``). Per PSR-3, a ``Throwable`` in the ``exception`` context key is automatically normalized to a meaningful array. All options default to ``false``.
180180

181181
Helpers and Functions
182182
=====================

user_guide_src/source/general/logging.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,9 @@ text), but you can keep them by setting ``$logContextUsedKeys = true``.
169169

170170
**Throwable normalization**
171171

172-
Any ``Throwable`` instance (exception or error) found in the context is automatically
173-
normalized into a meaningful array instead of being serialized as an empty object:
172+
Per PSR-3, a ``Throwable`` instance must be passed under the ``exception`` key to be
173+
handled specially. When found there, it is automatically normalized into a meaningful
174+
array instead of being serialized as an empty object:
174175

175176
.. literalinclude:: logging/008.php
176177

0 commit comments

Comments
 (0)