Weave 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

Log Laravel Package

draw/log

Lightweight Laravel logging helper package providing a simple API to write structured log entries and streamline application debugging. Integrates with Laravel’s logger, supports common log levels, and keeps logging consistent across your services.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require draw/log
    
    • Requires PHP 8.5+ and Laravel 10+ (or Symfony 6.4+).
    • Ensure psr/log is installed (included by default in Laravel).
  2. First Use Case: Structured Logging Replace basic Log::debug() with structured logs:

    use Draw\Log\Logger;
    
    // Inject via Laravel's DI or manually
    $logger = new Logger();
    $logger->info('User action', [
        'user_id' => 123,
        'action' => 'login',
        'metadata' => ['ip' => $request->ip(), 'user_agent' => $request->userAgent()]
    ]);
    
    • Outputs JSON-structured logs (e.g., for ELK or custom parsers).
  3. Quick Win: Event-Driven Logging Attach logging to Symfony events (e.g., KernelEvents::REQUEST):

    use Draw\Log\Event\LogEvent;
    use Symfony\Component\HttpKernel\Event\RequestEvent;
    use Symfony\Component\HttpKernel\KernelEvents;
    use Symfony\Component\EventDispatcher\EventDispatcher;
    
    $dispatcher = new EventDispatcher();
    $dispatcher->addListener(KernelEvents::REQUEST, function (RequestEvent $event) {
        $logger = new Logger();
        $logger->dispatch(new LogEvent('Request started', [
            'method' => $event->getRequest()->getMethod(),
            'path' => $event->getRequest()->getPathInfo()
        ]));
    });
    
  4. Leverage Laravel’s Service Provider Bind the logger in AppServiceProvider:

    public function register()
    {
        $this->app->singleton(Logger::class, function ($app) {
            return new Logger($app['log']); // Extend Laravel's logger
        });
    }
    

Implementation Patterns

Core Workflows

  1. Contextual Logging

    • Pattern: Attach metadata to logs dynamically.
    • Example:
      $logger->withContext(['user_id' => auth()->id()])
             ->error('Payment failed', ['amount' => $request->amount]);
      
    • Use Case: Audit trails, user-specific debugging.
  2. Event-Driven Logging

    • Pattern: Log business events via Symfony’s EventDispatcher.
    • Example:
      // In a controller
      $logger->dispatch(new LogEvent('Order created', ['order_id' => $order->id]));
      
      // In a subscriber
      $dispatcher->addListener(LogEvent::class, function (LogEvent $event) {
          // Process log entry (e.g., send to external API)
      });
      
    • Use Case: Decouple logging from business logic (e.g., log after OrderCreated event).
  3. Handler Chaining

    • Pattern: Extend Monolog handlers with custom logic.
    • Example:
      use Draw\Log\Handler\EnrichHandler;
      
      $handler = new EnrichHandler(new StreamHandler(storage_path('logs/app.log')));
      $handler->setEnricher(function ($record) {
          $record['custom_field'] = 'value';
          return $record;
      });
      $logger->pushHandler($handler);
      
    • Use Case: Add request IDs, tenant IDs, or security flags to logs.
  4. Dependency Injection (DI)

    • Pattern: Use draw/dependency-injection to manage loggers.
    • Example:
      // config/draw.php
      'loggers' => [
          'app' => [
              'class' => \Draw\Log\Logger::class,
              'arguments' => ['@logger'], // Laravel's logger
          ],
      ];
      
    • Use Case: Centralize logger configuration in a monolith or microservices.

Integration Tips

  • Laravel-Specific:

    • Override Log::getMonolog() to inject custom handlers:
      use Illuminate\Log\LogManager;
      
      LogManager::extend('custom', function () {
          $monolog = new Monolog\Logger('custom');
          $monolog->pushHandler(new \Draw\Log\Handler\CustomHandler());
          return $monolog;
      });
      
    • Use Log::channel('custom')->info(...) in controllers.
  • Symfony Integration:

    • Replace Laravel’s Log facade with Symfony’s LoggerInterface:
      use Psr\Log\LoggerInterface;
      
      public function __construct(private LoggerInterface $logger) {}
      
    • Inject draw/log's logger via Symfony’s DI container.
  • Testing:

    • Mock LoggerInterface in PHPUnit:
      $mockLogger = $this->createMock(LoggerInterface::class);
      $mockLogger->expects($this->once())
                 ->method('info')
                 ->with('Test log', ['key' => 'value']);
      $this->app->instance(LoggerInterface::class, $mockLogger);
      

Gotchas and Tips

Pitfalls

  1. PHP 8.5+ Requirement

    • Issue: Laravel 9.x or older will fail to install.
    • Fix: Upgrade PHP or fork the package (target PHP 8.1).
  2. Draw Ecosystem Lock-in

    • Issue: Dependencies on draw/dependency-injection and draw/user-bundle may complicate maintenance.
    • Fix: Use only PSR-3/PSR-11 interfaces (avoid draw/* bundles):
      // Avoid this if not using draw/ecosystem
      $logger = new \Draw\Log\Logger($this->app['draw.di.container']);
      
  3. Monolog Handler Conflicts

    • Issue: Custom handlers may override Laravel’s default handlers (e.g., SingleHandler).
    • Fix: Push handlers instead of replacing:
      $logger->pushHandler(new \Draw\Log\Handler\CustomHandler());
      
  4. EventDispatcher Overhead

    • Issue: Dispatching events for every log entry adds latency.
    • Fix: Use async logging or batch events:
      $dispatcher->dispatch(new LogEvent($record), LogEvent::PRIORITY_LOW);
      
  5. Structured Log Parsing

    • Issue: JSON logs may break if not parsed correctly by consumers (e.g., ELK, Datadog).
    • Fix: Validate output format:
      $logger->setFormatter(new \Monolog\Formatter\JsonFormatter());
      

Debugging Tips

  1. Log Not Appearing?

    • Check handler configuration:
      $logger->getHandlers(); // Verify handlers are attached
      
    • Ensure Monolog’s processors are not filtering records:
      $logger->pushProcessor(function ($record) {
          return $record; // Ensure no silent drops
      });
      
  2. Circular References in Logs

    • Issue: Logging objects with circular references (e.g., Eloquent models) may crash.
    • Fix: Use var_export or custom serializers:
      $logger->info('User', [
          'data' => json_decode(json_encode($user), true)
      ]);
      
  3. Performance Bottlenecks

    • Issue: High-volume logging slows down requests.
    • Fix: Use async handlers or batch processing:
      $handler = new \Monolog\Handler\AsyncHandler(new StreamHandler('app.log'));
      $logger->pushHandler($handler);
      

Extension Points

  1. Custom Handlers

    • Extend \Draw\Log\Handler\AbstractHandler to create reusable handlers:
      class DatabaseHandler extends AbstractHandler
      {
          public function write(array $record): void
          {
              DB::table('logs')->insert([
                  'message' => $record['message'],
                  'context' => json_encode($record['context']),
                  'level' => $record['level'],
              ]);
          }
      }
      
  2. Log Formatters

    • Override \Monolog\Formatter\FormatterInterface for custom output:
      class CustomJsonFormatter extends JsonFormatter
      {
          public function format(array $record): string
          {
              $record['extra']['custom_field'] = 'value';
              return parent::format($record);
          }
      }
      
  3. Event Listeners

    • Subscribe to LogEvent for post-processing:
      $dispatcher->addListener(LogEvent::class, function (LogEvent $event) {
          if ($event->getLevel() === LogLevel::ERROR) {
              // Send alert to Slack/PagerDuty
          }
      });
      
  4. Logger Middleware

    • Add logging to Laravel’s middleware stack:
      namespace App\Http\Middleware;
      
      use Draw\Log\Logger;
      use Closure;
      
      class LogMiddleware
      {
          public function __construct(private
      
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel