[GH-ISSUE #249] Some more guidance on using the logging context properly would be helpful #84

Closed
opened 2026-03-04 02:12:02 +03:00 by kerem · 10 comments
Owner

Originally created by @mpdude on GitHub (Oct 11, 2013).
Original GitHub issue: https://github.com/Seldaek/monolog/issues/249

The logging context is briefly mentioned in the usage.md, but I would like to get some additional guidance on how to best leverage it.

So which is the best way to send log messages?

  1. $logger->info(sprintf("Will have %s for %s", $food, $meal))
  2. $logger->info(sprintf("Will have %s for %s", $food, $meal), array('food' => $food, 'meal' => $meal))
  3. $logger->info("Food chosen", array('food' => $food, 'meal' => $meal))

That is, should I try to keep log messages as "fixed" as possible and add all varying info into the context? Or should the message itself be as clear as possible?

When it comes to 1.) or 2.) above, wouldn't it be handy for the Formatter to expand %var% from the context as well?

Thanks!

Originally created by @mpdude on GitHub (Oct 11, 2013). Original GitHub issue: https://github.com/Seldaek/monolog/issues/249 The logging context is briefly mentioned in the [usage.md](https://github.com/Seldaek/monolog/blob/master/doc/usage.md#using-the-logging-context), but I would like to get some additional guidance on how to best leverage it. So which is the best way to send log messages? 1. `$logger->info(sprintf("Will have %s for %s", $food, $meal))` 2. `$logger->info(sprintf("Will have %s for %s", $food, $meal), array('food' => $food, 'meal' => $meal))` 3. `$logger->info("Food chosen", array('food' => $food, 'meal' => $meal))` That is, should I try to keep log messages as "fixed" as possible and add all varying info into the context? Or should the message itself be as clear as possible? When it comes to 1.) or 2.) above, wouldn't it be handy for the Formatter to expand %var% from the context as well? Thanks!
kerem 2026-03-04 02:12:02 +03:00
Author
Owner

@Seldaek commented on GitHub (Oct 11, 2013):

You can enable the PsrLogMessageProcessor to get PSR-3 compatible placeholder replacement.

I typically just take the 1st approach, but it also depends on how you use the logs. If you store everything in a log backend that lets you search for stuff, having more structured data (3) can be better.

If you'd like to add more info to the docs please feel free, I don't mind answering more questions but I just don't think you can give "one true way", like most things it depends on the context.

<!-- gh-comment-id:26146672 --> @Seldaek commented on GitHub (Oct 11, 2013): You can enable the [PsrLogMessageProcessor](https://github.com/Seldaek/monolog/blob/master/src/Monolog/Processor/PsrLogMessageProcessor.php) to get PSR-3 compatible placeholder replacement. I typically just take the 1st approach, but it also depends on how you use the logs. If you store everything in a log backend that lets you search for stuff, having more structured data (3) can be better. If you'd like to add more info to the docs please feel free, I don't mind answering more questions but I just don't think you can give "one true way", like most things it depends on the context.
Author
Owner

@stof commented on GitHub (Oct 11, 2013):

It also depend of what you are logging. I also use the first way most of the time, but my DB connection logger (actually the Symfony2 one) is passing the SQL query as first argument and the bound parameters in the context. This makes it more useful than trying to inline

<!-- gh-comment-id:26146846 --> @stof commented on GitHub (Oct 11, 2013): It also depend of what you are logging. I also use the first way most of the time, but my DB connection logger (actually the Symfony2 one) is passing the SQL query as first argument and the bound parameters in the context. This makes it more useful than trying to inline
Author
Owner

@mpdude commented on GitHub (Oct 11, 2013):

Thanks for your comments so far!

"It depends" is a tricky answer when trying to teach beginners how to do things the right way(TM). Also open source contributors might be unable to choose what is appropriate for their users.

What if recommending a variant 4:

$logger->info("Will have {food} for {meal}", array('food' => $food, 'meal' => $meal))

If I am not mistaken, that way handlers that push into a powerful backend (log intelligence system) could have "fixed" messages to group similar errors while probably being able to also show/gather the "context" data.

A "local log file" handler could add the PsrLogMessageProcessor to end up with human-readable messages.

Right?

<!-- gh-comment-id:26150242 --> @mpdude commented on GitHub (Oct 11, 2013): Thanks for your comments so far! "It depends" is a tricky answer when trying to teach beginners how to do things the right way(TM). Also open source contributors might be unable to choose what is appropriate for their users. What if recommending a variant 4: `$logger->info("Will have {food} for {meal}", array('food' => $food, 'meal' => $meal))` If I am not mistaken, that way handlers that push into a powerful backend (log intelligence system) could have "fixed" messages to group similar errors while probably being able to also show/gather the "context" data. A "local log file" handler could add the PsrLogMessageProcessor to end up with human-readable messages. Right?
Author
Owner

@Seldaek commented on GitHub (Oct 11, 2013):

Yes that's probably the best "one true way" solution, if there must be one.

<!-- gh-comment-id:26150407 --> @Seldaek commented on GitHub (Oct 11, 2013): Yes that's probably the best "one true way" solution, if there must be one.
Author
Owner

@carlosdagos commented on GitHub (Jan 7, 2015):

To add to this, I normally will write "static" lines as the first argument, and variable data as the second one. This makes it easier to grep if you're logging to files.

Example

 $this->logger->info("Generated url for user", array('url' => $url->toString(), 'user_id' => $user->getID()));

I thought that was the intended use to begin with 😄

<!-- gh-comment-id:69013464 --> @carlosdagos commented on GitHub (Jan 7, 2015): To add to this, I normally will write "static" lines as the first argument, and variable data as the second one. This makes it easier to grep if you're logging to files. Example ``` $this->logger->info("Generated url for user", array('url' => $url->toString(), 'user_id' => $user->getID())); ``` I thought that was the intended use to begin with :smile:
Author
Owner

@Seldaek commented on GitHub (Jan 7, 2015):

@charlydagos it is definitely the initial intended use, but there are other options too like described above.

<!-- gh-comment-id:69027651 --> @Seldaek commented on GitHub (Jan 7, 2015): @charlydagos it is definitely the initial intended use, but there are other options too like described above.
Author
Owner

@adjenks commented on GitHub (Jul 26, 2018):

@carlosdagos That's how I use it. Then I stuff the array into my db as a json. I can parse the json if I have some consistently used fields.

<!-- gh-comment-id:408270525 --> @adjenks commented on GitHub (Jul 26, 2018): @carlosdagos That's how I use it. Then I stuff the array into my db as a json. I can parse the json if I have some consistently used fields.
Author
Owner

@juan-morales commented on GitHub (Jul 27, 2021):

@mpdude - OK old issue, but .... "It depends" is the right answer.

Because the logging context is the data-entry point for processors, etc.

Is not about how you build up the log message .... only.

So ... if you have a processor (for example) that is suppose to expect certain value in the context to do its job ... well ... put it there 🙂

I think this issue can be close.

<!-- gh-comment-id:887562758 --> @juan-morales commented on GitHub (Jul 27, 2021): @mpdude - OK old issue, but .... **"It depends"** is the right answer. Because the logging context is the data-entry point for processors, etc. Is not about how you build up the log message .... **only**. So ... if you have a processor (for example) that is suppose to expect certain value in the context to do its job ... well ... put it there :slightly_smiling_face: I think this issue can be close.
Author
Owner

@mpdude commented on GitHub (Jul 27, 2021):

Over the past years, I mostly followed the approach outlined in https://github.com/Seldaek/monolog/issues/249#issuecomment-26150242. That leaves it up to the configuration of your handler stack and/or processors and is also easy to write in code.

<!-- gh-comment-id:887600167 --> @mpdude commented on GitHub (Jul 27, 2021): Over the past years, I mostly followed the approach outlined in https://github.com/Seldaek/monolog/issues/249#issuecomment-26150242. That leaves it up to the configuration of your handler stack and/or processors and is also easy to write in code.
Author
Owner

@vukanac commented on GitHub (Apr 4, 2022):

Hey guys, @mpdude, can you share your experience with logging events to eg. New Relic?

Logging events is expected to have event name and params.

$logger->info('Log and send event', ['food' => $food, 'meal' => $meal, 'type' => 'event', 'name' => 'Event Name']);

I am considering to have one log line in the code like you described above, but to use two handlers.

One for normal logging eg. stdout and the other for sending to some external services or agents like New Relic.

$log->pushHandler(new StreamHandler('php://stdout', Logger::INFO));
// custom handler to cover use of newrelic_record_custom_event($name, $attributes)
$log->pushHandler(new CustomNewRelicHandler(Logger::INFO, $triggerByContext['type' => 'event']));

Somehow it looks cumbersome to add 'type'=>'event' every time.
The other option more verbose is to introduce and inject additional logger for events only.

$eventLogger->logEvent('Event Name', ['food' => $food, 'meal' => $meal]);

What are your thoughts?

<!-- gh-comment-id:1087504976 --> @vukanac commented on GitHub (Apr 4, 2022): Hey guys, @mpdude, can you share your experience with logging events to eg. New Relic? Logging events is expected to have event name and params. ``` $logger->info('Log and send event', ['food' => $food, 'meal' => $meal, 'type' => 'event', 'name' => 'Event Name']); ``` I am considering to have one log line in the code like you described above, but to use two handlers. One for normal logging eg. stdout and the other for sending to some external services or agents like New Relic. ``` $log->pushHandler(new StreamHandler('php://stdout', Logger::INFO)); // custom handler to cover use of newrelic_record_custom_event($name, $attributes) $log->pushHandler(new CustomNewRelicHandler(Logger::INFO, $triggerByContext['type' => 'event'])); ``` Somehow it looks cumbersome to add `'type'=>'event'` every time. The other option more verbose is to introduce and inject additional logger for events only. ``` $eventLogger->logEvent('Event Name', ['food' => $food, 'meal' => $meal]); ``` What are your thoughts?
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#84
No description provided.