Get started with 33% off your first certification using code: 33OFFNEW

A Guide to `Log` in Laravel

6 min read
Published on 20th June 2024

Logging is an essential aspect of web application development. It helps developers understand application behavior, track errors, and debug issues effectively. Laravel, a popular PHP framework, offers a robust and flexible logging system that makes logging easy and efficient. This guide delves into the various aspects of logging in Laravel, covering everything from basic usage to advanced features, ensuring you can leverage the full power of Laravel’s logging capabilities.

Introduction to Logging in Laravel

Laravel's logging services are based on the powerful Monolog library, which provides support for various logging handlers, formats, and levels. The default configuration of Laravel logging is stored in the config/logging.php file. This configuration file allows you to customize how and where your logs are written, whether it's to a single log file, multiple files, the system log, or even external services.

Basic Logging

Laravel provides several simple ways to log messages. The most basic method involves using the Log facade.

Using the Log Facade

The Log facade provides a straightforward API for writing log messages. Here’s a basic example of how to use it:

use Illuminate\Support\Facades\Log;

Log::info('This is an informational message.');
Log::warning('This is a warning message.');
Log::error('This is an error message.');

The Log facade supports various log levels defined by the PSR-3 standard:

  • emergency: System is unusable.
  • alert: Action must be taken immediately.
  • critical: Critical conditions.
  • error: Error conditions.
  • warning: Warning conditions.
  • notice: Normal but significant conditions.
  • info: Informational messages.
  • debug: Debug-level messages.

You can log messages at any of these levels using the corresponding methods:

Log::emergency('This is an emergency message.');
Log::alert('This is an alert message.');
Log::critical('This is a critical message.');
Log::error('This is an error message.');
Log::warning('This is a warning message.');
Log::notice('This is a notice message.');
Log::info('This is an informational message.');
Log::debug('This is a debug message.');

Contextual Information

Often, it's useful to log additional context with your messages. Laravel allows you to pass an array of contextual data along with your log message:

Log::info('User login', ['user_id' => $user->id, 'email' => $user->email]);

This additional context can help you better understand the circumstances under which the log message was generated.

Configuring Log Channels

Laravel’s logging system is highly configurable, allowing you to define multiple logging "channels." Each channel represents a specific way of writing log information. The default logging configuration is defined in the config/logging.php file. Here’s a brief overview of the main sections:

Default Log Channel

The default key specifies the default log channel used by the application:

'default' => env('LOG_CHANNEL', 'stack'),

By default, Laravel uses a stack channel, which aggregates multiple log channels into a single channel.

Log Channels

The channels array defines the available log channels. Each channel represents a particular way of writing log information. Here’s a basic example:

'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['single', 'slack'],
    ],

    'single' => [
        'driver' => 'single',
        'path' => storage_path('logs/laravel.log'),
        'level' => 'debug',
    ],

    'slack' => [
        'driver' => 'slack',
        'url' => env('LOG_SLACK_WEBHOOK_URL'),
        'username' => 'Laravel Log',
        'emoji' => ':boom:',
        'level' => 'critical',
    ],
],

Single Channel

The single channel writes log information to a single file. This is the simplest logging setup:

'single' => [
    'driver' => 'single',
    'path' => storage_path('logs/laravel.log'),
    'level' => 'debug',
],

Daily Channel

The daily channel creates a new log file each day. This helps manage log file size and makes it easier to archive logs:

'daily' => [
    'driver' => 'daily',
    'path' => storage_path('logs/laravel.log'),
    'level' => 'debug',
    'days' => 14,
],

Slack Channel

The slack channel sends log messages to a Slack channel. This is useful for alerting your team in real-time about critical issues:

'slack' => [
    'driver' => 'slack',
    'url' => env('LOG_SLACK_WEBHOOK_URL'),
    'username' => 'Laravel Log',
    'emoji' => ':boom:',
    'level' => 'critical',
],

To use the Slack channel, you need to set up a Slack webhook URL and add it to your .env file:

LOG_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/your/webhook/url

Custom Log Channels

Laravel allows you to create custom log channels by extending the logging configuration. For example, you can create a custom channel that logs messages to a database.

Custom Database Log Channel

To create a custom database log channel, follow these steps:

  1. Create a Migration for the Log Table:

    php artisan make:migration create_logs_table --create=logs
    

    In the migration file, define the table structure:

    public function up()
    {
        Schema::create('logs', function (Blueprint $table) {
            $table->id();
            $table->string('level');
            $table->text('message');
            $table->json('context')->nullable();
            $table->timestamps();
        });
    }
    
  2. Run the Migration:

    php artisan migrate
    
  3. Create a Custom Log Channel:

    In config/logging.php, add a custom channel configuration:

    'channels' => [
        // other channels...
        'database' => [
            'driver' => 'custom',
            'via' => App\Logging\CustomLogger::class,
            'level' => 'debug',
        ],
    ],
    
  4. Create the Custom Logger:

    Generate a new logger class:

    php artisan make:class CustomLogger
    

    Implement the logger class:

    namespace App\Logging;
    
    use Monolog\Logger;
    use Monolog\Handler\AbstractProcessingHandler;
    use DB;
    
    class CustomLogger
    {
        public function __invoke(array $config)
        {
            $logger = new Logger('custom');
            $logger->pushHandler(new DatabaseHandler());
            return $logger;
        }
    }
    
    class DatabaseHandler extends AbstractProcessingHandler
    {
        protected function write(array $record): void
        {
            DB::table('logs')->insert([
                'level' => $record['level_name'],
                'message' => $record['message'],
                'context' => json_encode($record['context']),
                'created_at' => now(),
                'updated_at' => now(),
            ]);
        }
    }
    

Now you can log messages to the database:

use Illuminate\Support\Facades\Log;

Log::channel('database')->info('This is a database log message.');

Advanced Logging Techniques

Laravel’s logging system is highly flexible and can be extended to meet advanced requirements. Here are a few advanced techniques you can use.

Contextual Logging with Middleware

You can use middleware to add contextual information to your logs. For example, you might want to log the user ID and IP address with every log message.

  1. Create Middleware:

    php artisan make:middleware LogContext
    

    Implement the middleware:

    namespace App\Http\Middleware;
    
    use Closure;
    use Illuminate\Support\Facades\Log;
    
    class LogContext
    {
        public function handle($request, Closure $next)
        {
            Log::withContext([
                'user_id' => auth()->check() ? auth()->id() : null,
                'ip' => $request->ip(),
            ]);
    
            return $next($request);
        }
    }
    
  2. Register Middleware:

    In app/Http/Kernel.php, register the middleware:

    protected $middlewareGroups = [
        'web' => [
            // other middleware...
            \App\Http\Middleware\LogContext::class,
        ],
    ];
    

Now, every log message will include the user ID and IP address as context.

Custom Log Formatters

Sometimes, you need to customize the format of your log messages. Laravel allows you to define custom formatters.

  1. Create a Custom Formatter:

    Generate a new formatter class:

    php artisan make:class CustomFormatter
    

    Implement the formatter class:

    namespace App\Logging;
    
    use Monolog\Formatter\LineFormatter;
    
    class CustomFormatter extends LineFormatter
    {
        public function __construct()
        {
            $format = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
            parent::__construct($format, null, true, true);
        }
    }
    
  2. Use the Custom Formatter:

    In config/logging.php, configure a channel to use the custom formatter:

    'channels' => [
        // other channels...
        'custom' => [
            'driver' => 'single',
            'path' => storage_path('logs/custom.log'),
            'level' => 'debug',
            'formatter' => App\Logging\CustomFormatter::class,
        ],
    ],
    

Monitoring and Analyzing Logs

To monitor and analyze your logs effectively, you can integrate Laravel logging with third-party log management services like Papertrail, Loggly, or Sentry.

Example: Integrating with Sentry

  1. Install Sentry:

    composer require sentry/sentry-laravel
    
  2. Configure Sentry:

    Add your Sentry DSN to the .env file:

    SENTRY_LARAVEL_DSN=https://[email protected]/0
    

    Publish the Sentry configuration:

    php artisan vendor:publish --provider="Sentry\Laravel\ServiceProvider"
    

    In config/sentry.php, update the DSN setting:

    'dsn' => env('SENTRY_LARAVEL_DSN'),
    
  3. Add Sentry Log Channel:

    In config/logging.php, add a Sentry log channel:

    'channels' => [
        // other channels...
        'sentry' => [
            'driver' => 'sentry',
            'level' => 'error',
        ],
    ],
    

Now, you can log messages to Sentry:

use Illuminate\Support\Facades\Log;

Log::channel('sentry')->error('This is an error message.');

Conclusion

Logging is a critical aspect of any application, providing insights and helping with debugging and monitoring. Laravel’s logging system, built on the powerful Monolog library, offers flexibility and power, enabling developers to log messages in various formats and destinations.

From basic logging to advanced customizations, Laravel provides a comprehensive set of tools to ensure your logging needs are met. By understanding and leveraging these tools, you can enhance the maintainability, reliability, and observability of your Laravel applications.

For further reading and advanced configurations, you can refer to the Laravel Logging Documentation and the Monolog Documentation.