# Proper logging in PHP with PSR-3

DevFeed: [Proper logging in PHP with PSR-3](<https://devfeed.tech/articles/proper-logging-in-php-with-psr-3-21144.md>)

Original publisher: [Read original article](<https://ocramius.github.io/blog/php-logging-with-psr-3/>)

Published: 2026-07-28T00:00:00Z

Content type: article

Language: en

Sources: [Marco Pivetta](<https://devfeed.tech/sources/marco-pivetta.md>)

Topics: [PHP](<https://devfeed.tech/topics/php.md>), [Logging](<https://devfeed.tech/topics/logging.md>), [Exception](<https://devfeed.tech/topics/exception.md>), [log management](<https://devfeed.tech/topics/log-management.md>), [Monitoring](<https://devfeed.tech/topics/monitoring.md>)

Tags: [article](<https://devfeed.tech/tags/article.md>), [code](<https://devfeed.tech/tags/code.md>), [errors](<https://devfeed.tech/tags/errors.md>), [exception](<https://devfeed.tech/tags/exception.md>), [how-to](<https://devfeed.tech/tags/how-to.md>), [logging](<https://devfeed.tech/tags/logging.md>), [monitoring](<https://devfeed.tech/tags/monitoring.md>), [php](<https://devfeed.tech/tags/php.md>)

## AI overview

This article explains practical PHP logging with PSR-3. It focuses on passing exceptions through the logger context, allowing the logger to render exception details, defining exception types for business-specific failures, and logging enough information to understand software behavior in production. It also warns that logging and exceptions can impose CPU, memory, and I/O overhead.

## Source excerpt

Who is this article for? This post is for people that do day-by-day busywork coding, and for team leads that want to direct their peers towards better logging practices. Note that this article comes from my regular need to present these exact points to different people, multiple times a year, in multiple teams, in multiple companies. Also, we will not talk about how to configure a PSR-3 logger, but rather how to use one. Handling errors properly Error/exception handling is the main use-case for logging. When logging exceptions, please pass the Throwable instance to the 'exception' context key. try { // logic here } catch (SomeException $failed) { $this->logger->error('Something went wrong', [ 'exception' => $failed, ]); } Avoid cluttering the logger call with data deriving from the exception: it's not the logger call-site's job, and you are just repeating work. I often see unnecessary code like: try { // logic here } catch (SomeException $failed) { $this->logger->error('Something went wrong', [ // first mistake: we forgot 'exception' 'previous' => $failed->getPrevious(), // let the logger do this! 'line' => $failed->getLine(), // already part of the stack trace 'error' => $failed->getMessage(), // also always rendered 'error_type' => $failed::class, // done by the logger, usually ]); } The logger itself must instead be configured (and usually already is configured) to render: the exception ::class the exception message and code (codes are not really relevant any more, in this century) the stack trace previous exceptions additional exception fields Your responsibility is to instead pass context information that the logger can't infer on its own. What if my code fails gracefully, and does not raise an exception? if (is_wrong($something)) { $this->logger->warn('Something went wrong', ['something' => $something]); } For business-specific failures that deserve a type, we can upcast them to a Throwable anyway: if (is_wrong($something)) { $this->logger->warn('Something wen