paulund

Logging in Your Application

Logging in Your Application

Logging is an essential practice in software development. Without proper logging, debugging issues in production can be incredibly difficult. Logs provide valuable insights into your application's behaviour, helping you diagnose problems, monitor performance, and maintain security.

You should be logging:

  • Errors and Warnings: Capturing unexpected failures or issues.
  • Informational Messages: Events such as user logins, background job completions, or system events.
  • Request and Response Data: HTTP request details, execution times, and response payloads.
  • Resource Usage: Memory, CPU, database queries, and cache hits and misses.

A good logging strategy ensures that you can quickly find relevant information when troubleshooting issues.

Choosing a Logging Solution

There are many tools available for logging, including:

Logging Frugality

Be mindful of the volume of logs your application generates. Excessive logging leads to performance issues and increased storage costs. The following tips will help you log efficiently:

  • Log Levels: Use different log levels (debug, info, warning, error) to categorise logs. This allows you to filter logs based on severity.
  • Structured Logging: Use structured logging formats (such as JSON) to make logs easier to parse and analyse.
  • Avoid Logging Sensitive Data: Be cautious about logging sensitive information such as passwords, credit card numbers, or personally identifiable information (PII).
  • Do Not Log Large Objects: Avoid logging large objects or data structures that will bloat your logs.
  • Pick Attributes Wisely: Log only the attributes that are necessary for debugging or monitoring. Too many attributes make logs hard to read and analyse.

Log Uniqueness

Each log entry should be unique and searchable. This ensures that you can pinpoint exactly where in your code a log entry was created and what it relates to. Avoid interpolating variables directly into the log message. For example, this is problematic:

Log::info('User logged in ' . $user->id);

This message changes with every user, making it difficult to search for in your codebase. Instead, pass variables as context:

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

You can now search for the literal string User logged in and find exactly where in the code this log entry was created.

Logging in Laravel

Laravel ships with a built-in Log facade powered by Monolog, making logging straightforward out of the box.

Here is an example of logging at different levels:

use Illuminate\Support\Facades\Log;

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

Laravel can write logs to files, databases, syslog, or external log management services.

Configuring Log Channels in Laravel

In your config/logging.php file, you can define different log channels:

'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 Logs',
        'emoji' => ':boom:',
        'level' => 'critical',
    ],
],

Log Storage with Loki

If you are looking for a scalable, efficient way to store and query logs, Loki is an excellent choice. Loki is a log aggregation system built by Grafana, optimised for storing logs efficiently and integrating seamlessly with Grafana dashboards.

Why Use Loki?

  • Log Aggregation: Collect logs from multiple sources into a single place.
  • Efficient Storage: Loki indexes logs based on labels rather than full text, making it more cost-effective than traditional log storage.
  • Powerful Search: Query logs using LogQL, a Prometheus-inspired query language.
  • Alerting and Monitoring: Set up alerts when specific log patterns appear.
  • Grafana Integration: Visualise logs alongside metrics in Grafana dashboards.

Setting Up Loki

Run Loki using Docker:

docker run -d --name=loki -p 3100:3100 grafana/loki:latest

Set up Promtail to ship logs to Loki:

docker run -d --name=promtail -v /var/log:/var/log grafana/promtail:latest -config.file=/etc/promtail/config.yml

Then configure your application to send logs to the Loki instance.

Querying Logs in Loki

You can search logs using LogQL in Grafana. Here are a few useful examples.

Fetch all logs for a specific service:

{job="my-app"}

Find errors in logs:

{job="my-app"} |= "error"

Filter logs by duration:

{job="my-app"} | logfmt | duration > 100ms

Metrics and Logging

Logging and metrics serve complementary roles. Logs help you debug specific issues; metrics let you track performance trends over time.

For metrics, Prometheus is a strong choice:

  • It collects system and application metrics.
  • It stores time-series data efficiently.
  • It integrates with Grafana for visualisation.

Example: Exporting Laravel metrics to Prometheus:

use Prometheus\CollectorRegistry;
use Prometheus\Storage\InMemory;

$registry = new CollectorRegistry(new InMemory());
$counter = $registry->getOrRegisterCounter('app', 'requests_total', 'Total Requests');
$counter->inc();

Final Thoughts

Logging is a fundamental part of software development and system observability. A proper logging strategy lets you quickly diagnose issues, monitor performance, and improve application reliability.

If you are looking for a powerful log storage solution, Grafana Loki is an excellent choice -- it offers scalability, cost efficiency, and seamless Grafana integration. Get your logging in place early, and you will save yourself considerable effort when things go wrong in production.