[GH-ISSUE #1936] Support for logging exception instances #834

Closed
opened 2026-03-04 03:01:11 +03:00 by kerem · 3 comments
Owner

Originally created by @delacry on GitHub (Jan 29, 2025).
Original GitHub issue: https://github.com/Seldaek/monolog/issues/1936

Hi, I would love to add better support for logging exception instances, for example Logger::info(new Exception()), it's useful in try-catch block where you don't want to throw an error 500, but just log the exception. It's useful later in handlers, where some library can generate HTML dump of that exception (like Tracy).

Since PHP 8.0, Throwable extends Stringable, so instances can be used as $message parameter.

Currently, there is a problem, that exception instance is lost in Logger::log, because it's converted to string when passing to addRecord.

It would be great if there was instanceof check for Throwable and $message would then be added to $context['exception'] (if not set previously).

Maybe it would be better (but we would also add it to context for BC) to have Throwable $throwable as a constructor property of LogRecord, so it's type-safe in handlers and easier to access, also when logging messages, we could check for Throwable instance of $context['exception'] and add it to LogRecord as that new $throwable parameter, to ensure better backwards compatibility.

Originally created by @delacry on GitHub (Jan 29, 2025). Original GitHub issue: https://github.com/Seldaek/monolog/issues/1936 Hi, I would love to add better support for logging exception instances, for example `Logger::info(new Exception())`, it's useful in try-catch block where you don't want to throw an error 500, but just log the exception. It's useful later in handlers, where some library can generate HTML dump of that exception (like [Tracy](https://github.com/nette/tracy)). Since PHP 8.0, `Throwable` extends `Stringable`, so instances can be used as `$message` parameter. Currently, there is a problem, that exception instance is lost in [Logger::log](https://github.com/Seldaek/monolog/blob/3.8.1/src/Monolog/Logger.php#L581), because it's converted to string when passing to addRecord. It would be great if there was instanceof check for `Throwable` and `$message` would then be added to `$context['exception']` (if not set previously). Maybe it would be better (but we would also add it to context for BC) to have `Throwable $throwable` as a constructor property of `LogRecord`, so it's type-safe in handlers and easier to access, also when logging messages, we could check for `Throwable` instance of `$context['exception']` and add it to LogRecord as that new `$throwable` parameter, to ensure better backwards compatibility.
kerem 2026-03-04 03:01:11 +03:00
  • closed this issue
  • added the
    Feature
    label
Author
Owner

@stof commented on GitHub (Jan 29, 2025):

Stringable are supported as message by being casted to string, not by being passed untransformed inside the whole Monolog stack (PSR-3 has added a union type for \Stringable in the interface only because of the behavior of strict_types in PHP, AFAICT).

The recommended usage of PSR-3 is to pass it as the exception key of the context (which implementation are expected to handle fine). Doing that in your try-catch block would make your code compatible with any PSR-3 logger.

<!-- gh-comment-id:2621904663 --> @stof commented on GitHub (Jan 29, 2025): Stringable are supported as message by being casted to string, not by being passed untransformed inside the whole Monolog stack (PSR-3 has added a union type for `\Stringable` in the interface only because of the behavior of `strict_types` in PHP, AFAICT). The recommended usage of PSR-3 is to pass it as the `exception` key of the context (which implementation are expected to handle fine). Doing that in your try-catch block would make your code compatible with any PSR-3 logger.
Author
Owner

@delacry commented on GitHub (Jan 29, 2025):

Stringable are supported as message by being casted to string, not by being passed untransformed inside the whole Monolog stack

I know, I'm talking just about Logger class, where log() accepts string|Stringable, and we can then check for Throwable instance and add it to $context['exception'] or add it to LogRecord as another property so handler implementations can access it with type-safety.

The recommended usage of PSR-3 is to pass it as the exception key of the context (which implementation are expected to handle fine). Doing that in your try-catch block would make your code compatible with any PSR-3 logger.

True, but when someone is using the monolog library, he could log exceptions more easily. Instead of typing:

$this->logger->info($e, ['exception' => $e]);

They would type:

$this->logger->info($e);

So handlers receive the exception instance.

<!-- gh-comment-id:2621938474 --> @delacry commented on GitHub (Jan 29, 2025): > Stringable are supported as message by being casted to string, not by being passed untransformed inside the whole Monolog stack I know, I'm talking just about `Logger` class, where `log()` accepts `string|Stringable`, and we can then check for `Throwable` instance and add it to `$context['exception']` or add it to `LogRecord` as another property so handler implementations can access it with type-safety. > The recommended usage of PSR-3 is to pass it as the exception key of the context (which implementation are expected to handle fine). Doing that in your try-catch block would make your code compatible with any PSR-3 logger. True, but when someone is using the monolog library, he could log exceptions more easily. Instead of typing: ``` $this->logger->info($e, ['exception' => $e]); ``` They would type: ``` $this->logger->info($e); ``` So handlers receive the exception instance.
Author
Owner

@Seldaek commented on GitHub (Mar 16, 2025):

While I see this technically could be done, I do believe the explicit $this->logger->info($e, ['exception' => $e]); is better as it is more interoperable and it's not really that long to type.. so I think I'd rather not add a shortcut here.

I'd also argue that in most cases logging some more human-readable details and context in the message is usually very valuable, and logging $e->getMessage() as log message tends to result in unactionable logs because exception messages are garbage in many libs.

So I usually would encourage $this->logger->error('Failed to do x', ['exception' => $e]);

<!-- gh-comment-id:2727381767 --> @Seldaek commented on GitHub (Mar 16, 2025): While I see this technically could be done, I do believe the explicit `$this->logger->info($e, ['exception' => $e]);` is better as it is more interoperable and it's not really that long to type.. so I think I'd rather not add a shortcut here. I'd also argue that in most cases logging some more human-readable details and context in the message is usually very valuable, and logging `$e->getMessage()` as log message tends to result in unactionable logs because exception messages are garbage in many libs. So I usually would encourage `$this->logger->error('Failed to do x', ['exception' => $e]);`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/monolog#834
No description provided.