Symfony Monolog fingers_crossed: keeping pre-error debug records from a failed deployment run
0 reputation · 20 Apr 2025, 12:10 UTC
0 reputation · 20 Apr 2025, 12:10 UTC
My Symfony application uses the default production Monolog setup with a fingers_crossed handler in config/packages/monolog.yaml, writing through a nested stream handler to var/log/prod.log. During a deployment, the console commands (cache:clear, cache:warmup, migrations) log through the same configuration.
The problem: when a deployment step fails without emitting anything at action_level (error by default), the buffered info/debug records that would explain the failure appear to be discarded. I also understand buffer_size drops the oldest records once exceeded, which could remove the earliest deployment context even when an error does eventually trigger the flush.
My goal is to guarantee that a failed deployment always leaves a usable trace in the log file, without flooding production logs with debug output from normal HTTP traffic. I am unsure where the right boundary is: raising passthru_level to warning would preserve warnings, but a deployment that fails silently below warning level would still leave nothing.
Should long-running CLI deployment commands use a separate handler or channel configuration from the HTTP fingers_crossed handler, and how is that scoped in monolog.yaml?
Does passthru_level interact with buffer_size in a way that still risks losing early records during a verbose deployment run?
Is there a documented way to force a buffer flush at the end of a console command even when no error-level record occurred?
31275 reputation · 20 Apr 2025, 18:30 UTC
To guarantee that failed deployment commands leave a usable trace without flooding your production logs, you should separate your CLI logging configuration from your HTTP configuration. The fingers_crossed handler is designed for request-response cycles; using it for long-running deployment scripts creates a risk where logs are discarded if the process exits without hitting the action_level.
The most reliable way to handle this in Symfony is to define a separate handler specifically for the console. This allows you to use a standard stream handler (which writes immediately) or a fingers_crossed handler with a much lower action_level for CLI commands.
In your config/packages/monolog.yaml, you can use the channels configuration to isolate console output:
# config/packages/monolog.yaml
monolog:
handlers:
# Standard production HTTP handler
main:
type: fingers_crossed
action_level: error
handler: nested
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
# Dedicated CLI handler
console:
type: stream
path: "%kernel.logs_dir%/deploy.log"
level: info # Capture everything INFO and above immediately
channels: ["console"]
Yes. buffer_size defines the maximum number of records kept in memory. If your deployment script generates 1,000 debug lines but your buffer_size is 100, the first 900 lines are discarded before the action_level is ever reached. If a failure then triggers the flush, you only see the last 100 records. passthru_level does not prevent this; it only ensures that records at or above that level are written regardless of whether the action_level was triggered.
There is no native monolog.yaml configuration to "force flush on exit" if the activation level wasn't met. To achieve this, you would need to manually inject the logger into your command and call the handler's close/flush method, or more simply, avoid fingers_crossed for CLI tasks entirely.
| Handler Type | Behavior on Success | Behavior on Failure | Risk |
|---|---|---|---|
fingers_crossed |
Logs discarded | Buffer flushed to disk | Buffer overflow (loss of early logs) |
stream |
All logs written | All logs written | Log file bloat |
Diagnostic Detail Needed: Are your deployment failures resulting in PHP Fatal Errors (Segmentation faults/Out of Memory) or Symfony-caught Exceptions? If the process crashes at the PHP engine level, Monolog's shutdown functions may not execute, meaning no buffer will ever be flushed regardless of configuration.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.