Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Monolog Bundle Laravel Package

symfony/monolog-bundle

Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the bundle via Composer:

    composer require symfony/monolog-bundle
    

    Register the bundle in config/bundles.php (Symfony) or config/app.php (Laravel via Symfony integration):

    return [
        // ...
        Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
    ];
    
  2. Basic Configuration Configure handlers in config/packages/monolog.yaml (Symfony) or config/monolog.php (Laravel):

    monolog:
        handlers:
            main:
                type: stream
                path: "%kernel.logs_dir%/%kernel.environment%.log"
                level: debug
    
  3. First Use Case Log a message in a controller or service:

    use Psr\Log\LoggerInterface;
    
    class ExampleController extends AbstractController
    {
        public function index(LoggerInterface $logger)
        {
            $logger->info('User accessed the homepage');
            return new Response('Logged!');
        }
    }
    

Implementation Patterns

Dependency Injection

  • Type-Hint LoggerInterface in constructors/services to leverage dependency injection:

    public function __construct(private LoggerInterface $logger) {}
    
  • Named Loggers (Symfony-specific):

    monolog:
        channels: [auth, security]
    

    Inject by name:

    public function __construct(LoggerInterface $logger, LoggerInterface $authLogger) {}
    

Contextual Logging

  • Add Context for structured logs:

    $logger->info('Order processed', [
        'order_id' => $order->id,
        'user_id' => $order->user_id,
        'amount' => $order->amount,
    ]);
    
  • Bags for Grouped Context:

    $logger->withContext(['user_id' => 123])->info('Event triggered');
    

Handlers and Channels

  • Dynamic Handlers (e.g., Slack, Sentry):

    handlers:
        slack:
            type:         slack
            token:        "%env(SLACK_TOKEN)%"
            channel:      "#logs"
            level:        error
            formatter:    monolog.formatter.json
    
  • Channel-Specific Handlers:

    handlers:
        security:
            type:   stream
            path:   "%kernel.logs_dir%/security.log"
            level:  warning
            channels: [security]
    

Laravel Integration (Symfony Bridge)

  • Use Psr\Log\LoggerInterface in Laravel services:
    public function __construct(private LoggerInterface $logger) {}
    
  • Configure via config/monolog.php:
    return [
        'handlers' => [
            'single' => [
                'type' => 'stream',
                'path' => storage_path('logs/laravel.log'),
                'level' => 'debug',
            ],
        ],
    ];
    

Middleware for HTTP Requests

  • Log Requests/Responses in middleware:
    public function handle($request, Closure $next)
    {
        $logger->info('Incoming request', [
            'method' => $request->method(),
            'path' => $request->path(),
        ]);
    
        $response = $next($request);
    
        $logger->info('Outgoing response', [
            'status' => $response->getStatusCode(),
        ]);
    
        return $response;
    }
    

Gotchas and Tips

Common Pitfalls

  1. Level Overrides

    • Handlers inherit levels from parent handlers. Explicitly set level to avoid unexpected filtering:
      handlers:
          nested:
              type:   group
              members: [stream1, stream2]
              level:  debug  # Override for all members
      
  2. Circular References in Context

    • Avoid logging objects with circular references (e.g., Eloquent models with lazy-loaded relations). Use __debugInfo() or manually extract data:
      $logger->info('User data', $user->toArray());
      
  3. Performance with High-Volume Logs

    • Use null formatter for high-throughput logs to skip serialization:
      handlers:
          high_volume:
              type:   stream
              path:   "%kernel.logs_dir%/high_volume.log"
              level:  info
              formatter: null
      
  4. Symfony vs. Laravel Paths

    • Laravel’s storage_path() differs from Symfony’s %kernel.logs_dir%. Use:
      path: "%kernel.project_dir%/storage/logs/app.log"
      

Debugging

  • Check Log Levels

    • Ensure handlers are not silently dropping logs due to misconfigured levels. Test with:
      $logger->debug('This should appear if level is debug');
      $logger->alert('This should always appear');
      
  • Formatter Issues

    • If logs appear garbled, verify the formatter (e.g., monolog.formatter.json vs. monolog.formatter.line).
  • Handler Activation

    • Use level: debug temporarily to confirm handlers are active:
      handlers:
          test:
              type:   stream
              path:   "%kernel.logs_dir%/test.log"
              level:  debug
      

Extension Points

  1. Custom Handlers

    • Create a handler class implementing Monolog\Handler\AbstractProcessingHandler:
      class MyHandler extends AbstractProcessingHandler
      {
          protected function write(array $record): void
          {
              // Custom logic (e.g., send to external API)
          }
      }
      
    • Register in config:
      handlers:
          my_handler:
              type:   my_handler
              level: info
      
  2. Processors

    • Add processors to enrich logs (e.g., add request IDs):
      processors:
          id: [Symfony\Component\Monolog\Processor\UidProcessor]
      
    • Custom processor:
      class RequestIdProcessor extends Processor
      {
          public function __invoke(array $record): array
          {
              $record['extra']['request_id'] = request()->header('X-Request-ID');
              return $record;
          }
      }
      
  3. Dynamic Handler Configuration

    • Use environment variables or services to conditionally enable handlers:
      handlers:
          error_monitor:
              type:   monitor
              level:  error
              enabled: "%env(bool:MONITOR_ERRORS)%"
      

Laravel-Specific Tips

  • Laravel’s Default Logger

    • Monolog replaces Laravel’s default logger. Ensure no duplicate loggers are configured in AppServiceProvider:
      // Avoid this if using MonologBundle
      $this->app['log'] = Log::class;
      
  • Queue Logs

    • For async logging, use the async handler:
      handlers:
          async:
              type:   async
              handler: buffered
              level:  debug
      
  • Log Channels

    • Laravel’s log channels (e.g., single, stack) map to Monolog handlers. Configure in config/logging.php:
      'channels' => [
          'monolog' => [
              'driver' => 'monolog',
              'level' => 'debug',
              'handler' => 'main', // Matches monolog.yaml
          ],
      ],
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware