This project demonstrates 10 advanced logging techniques and configurations using Monolog in a modern Symfony application. It includes a set of console commands that you can run to see each logging concept in action.
- PHP 8.2+
- Composer
- Symfony CLI (optional, but recommended)
- Clone the repository:
git clone https://github.com/mattleads/MonologPatterns.git cd MonologPatterns - Install dependencies:
composer install
- Set up the local SQLite database for the Messenger queue examples:
php bin/console messenger:setup-transports
Buffers all debug logs in memory during a process. If the process finishes successfully, the buffer is discarded. If an error occurs, the entire buffer (including the previous debug logs) is flushed to the log file.
Test Command:
# Runs successfully, debug logs are discarded
php bin/console app:test-fingers-crossed
# Triggers an error, flushing the preceding debug logs to var/log/dev.log
php bin/console app:test-fingers-crossed --failDemonstrates routing specific logs to a dedicated file (payment.log) while excluding them from the main application log, using Monolog channels and Symfony's #[Target] attribute.
Test Command:
php bin/console app:process-payments
# Check var/log/payment.log and var/log/dev.main.logAutomatically injects global context (like process ID, user ID, or request ID) into every log record without needing to pass it manually in every $logger->info() call.
Test Command:
php bin/console app:test-context
# Check var/log/dev.main.log to see the "pid" and "user" extra fields appendedUses a custom Monolog Processor to scan the log context array and automatically mask sensitive keys (like passwords or credit card numbers) before they are written to disk.
Test Command:
php bin/console app:import-users
# Check var/log/dev.main.log to see "***REDACTED***" valuesOutputs logs as JSON lines (ndjson), which allows log aggregators like ELK or Datadog to natively index fields like context.report_id.
Test Command:
php bin/console app:generate-report
# Check var/log/app.jsonAggregates identical log records that occur rapidly (e.g., during a database outage) and prevents log spam by grouping them into a single summary.
Test Command:
php bin/console app:test-deduplication
# This fires 100 identical errors rapidly.
# Check var/log/dedup.logSimulates dynamic log level activation (typically done via an HTTP header like X-Debug-Session) using a console option.
Test Command:
# Only logs INFO level
php bin/console app:dynamic-debug
# Forces DEBUG level for this specific execution
php bin/console app:dynamic-debug --force-debugInjects the Message Class/ID into the Monolog context specifically for long-running worker processes, making asynchronous logs traceable back to the originating message.
Test Command:
# 1. Dispatch a job to the queue
php bin/console app:dispatch-job
# 2. Run the worker to consume it
php bin/console messenger:consume async --limit=1 -vv
# Check var/log/dev.main.log for "Worker started message"Demonstrates how to keep error logs clean by configuring Monolog to ignore specific expected exceptions or HTTP status codes.
Test Command:
php bin/console app:simulate-traffic
# The simulated 404 error is caught, but excluded from triggering the FingersCrossed error thresholdRoutes critical infrastructure failures directly to a Slack channel immediately, bypassing standard logs, using symfony/notifier bridged with Monolog.
Note: You must configure a valid SLACK_DSN in your .env file to see this send a real message to Slack.
Test Command:
php bin/console app:trigger-critical-alert