# Dev: debug → dev.log only; info and above → dev.log + stderr. # Prod: debug–notice → prod.log only; warning+ → prod.log + stderr. Deprecations: stderr (JSON) only. # Log rotation: Monolog’s rotating_file rolls daily and keeps the last N files (caps growth; not a strict MB cap). monolog: channels: - deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists when@dev: monolog: handlers: # Each member gets every record; level filters which are actually written. main: type: group members: [file, docker] channels: ["!event"] file: type: rotating_file path: "%kernel.logs_dir%/%kernel.environment%.log" level: debug max_files: 14 docker: type: stream path: "php://stderr" # Min level info: debug stays out of stderr (file only). level: info console: type: console process_psr_3_messages: false channels: ["!event", "!doctrine", "!console"] when@test: monolog: handlers: main: type: fingers_crossed action_level: error handler: nested excluded_http_codes: [404, 405] channels: ["!event"] nested: type: stream path: "%kernel.logs_dir%/%kernel.environment%.log" level: debug when@prod: monolog: handlers: # No fingers_crossed: we split explicitly between file (all) and stderr (warning+ only). main: type: group members: [file, stderr] channels: ["!deprecation", "!event"] file: type: rotating_file path: "%kernel.logs_dir%/%kernel.environment%.log" level: debug max_files: 30 stderr: type: stream path: php://stderr level: warning formatter: monolog.formatter.json console: type: console process_psr_3_messages: false channels: ["!event", "!doctrine"] deprecation: type: stream channels: [deprecation] path: php://stderr formatter: monolog.formatter.json