Oussama GHAIEB

Tips, tricks, and code snippets for developers

Laravel Precision Monitoring: Break Down and Analyze Each Step of Your Code

๐Ÿ” Why Performance Monitoring is Essential in Laravel Projects

In todayโ€™s digital landscape, web application performance isn't just a luxuryโ€”it's a necessity. A slow Laravel app can damage user satisfaction, harm your SEO rankings, and reduce conversions.

If you're serious about optimizing your Laravel app, you need more than just guesswork. You need actionable metrics.

In this guide, you'll learn how to implement a robust performance monitoring system in Laravel that:

  • โœ… Tracks total request time
  • โœ… Supports custom timing breakpoints to measure specific operations
  • โœ… Stores performance logs as structured JSON
  • โœ… Can be easily disabled in production
  • โœ… Integrates smoothly with your middleware, controllers, and jobs

Whether you're troubleshooting slow APIs or preparing for high-traffic production, this tool will give you visibility where you need it most.


โš™๏ธ Step 1: Configure a Dedicated JSON Log Channel in Laravel

To store performance metrics separately from your default logs, add a new channel to config/logging.php:

'performance_monitor' => [
    'driver' => 'single',
    'path' => storage_path('logs/performance_monitor.json'),
    'formatter' => \Monolog\Formatter\JsonFormatter::class,
    'formatter_with' => [
        'include_stacktraces' => true,
    ],
    'level' => 'info',
],

This makes it easy to analyze logs using tools like Kibana, Datadog, Grafana, or custom dashboards.


๐Ÿ›ก๏ธ Step 2: Create the Performance Monitoring Middleware

In app/Http/Middleware/PerformanceMonitorMiddleware.php:

This middleware tracks the total request time and allows developers to insert custom breakpoints.

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Log;

class PerformanceMonitorMiddleware
{
    protected $startTime;
    protected $breakpoints = [];
    protected $enabled;

    public function __construct()
    {
        $this->enabled = config('app.performance_monitor_enabled');
    }

    public function handle($request, Closure $next)
    {
        if (!$this->enabled) {
            return $next($request);
        }

        $this->startTime = defined('LARAVEL_START') ? LARAVEL_START : microtime(true);

        // Register shutdown function as backup
        register_shutdown_function(function () {
            $this->logBreakpoints();
        });

        // Make the monitor available throughout the app
        $request->attributes->set('performance_monitor', $this);

        return $next($request);
    }

    public function terminate($request, $response)
    {
        if (!$this->enabled) {
            return;
        }

        $this->logBreakpoints();
    }

    public function addBreakpoint($id)
    {
        if (!$this->enabled) {
            return;
        }

        $this->breakpoints[$id] = microtime(true);
    }

    protected function logBreakpoints()
    {
        if (empty($this->breakpoints)) {
            return;
        }

        $logEntry = [
            'timestamp' => now()->toISOString(),
            'url' => request()->fullUrl(),
            'method' => request()->method(),
            'breakpoints' => [],
            'total_time' => round((microtime(true) - $this->startTime) * 1000, 2) . 'ms',
        ];

        $previousTime = $this->startTime;

        foreach ($this->breakpoints as $id => $time) {
            $elapsed = $time - $previousTime;
            $totalElapsed = $time - $this->startTime;

            $logEntry['breakpoints'][] = [
                'id' => $id,
                'elapsed_since_previous_ms' => round($elapsed * 1000, 2),
                'total_elapsed_ms' => round($totalElapsed * 1000, 2),
                'timestamp' => $time,
            ];

            $previousTime = $time;
        }

        Log::channel('performance_monitor')->info('Performance metrics', $logEntry);
    }
}

Middleware Highlights:

  • โœ… Accurate time tracking with LARAVEL_START
  • ๐Ÿ“Œ Custom breakpoints for detailed insights
  • ๐Ÿ” Works even if terminate() fails (shutdown fallback)
  • ๐ŸŒ Logs full URL and HTTP method

๐Ÿงฉ Step 3: Register the Middleware in Your App

Either apply it globally or only on routes that matter:

$middleware->appendToGroup('web', [
    \App\Http\Middleware\PerformanceMonitorMiddleware::class,
]);

For APIs, consider adding it to the api group or specific controllers.


๐Ÿ”ง Step 4: Add a Global Service for Easy Breakpoint Access

Update AppServiceProvider to bind a simple performance monitor service:

$this->app->singleton('performance_monitor', function () {
    return new class {
        public function addBreakpoint($id)
        {
            if ($monitor = request()->attributes->get('performance_monitor')) {
                $monitor->addBreakpoint($id);
            }
        }
    };
});

You can now use app('performance_monitor')->addBreakpoint('some_point'); anywhere in your app!


๐Ÿ” Step 5: Enable or Disable Performance Tracking via .env

In config/app.php, add:

'performance_monitor_enabled' => env('PERFORMANCE_MONITOR_ENABLED', true),

Then toggle it in .env:

PERFORMANCE_MONITOR_ENABLED=false

This keeps your production logs clean when needed.


๐Ÿงช Example in a Controller

public function getUserData($id)
{
    app('performance_monitor')->addBreakpoint('start');

    $user = User::with('posts')->findOrFail($id);
    app('performance_monitor')->addBreakpoint('after_query');

    $processedData = $this->processUserData($user);
    app('performance_monitor')->addBreakpoint('after_processing');

    return response()->json($processedData);
}

๐Ÿ“ˆ Sample Output: JSON Performance Log

{
  "timestamp": "2025-05-08T12:00:00Z",
  "url": "https://example.com/api/users/123",
  "method": "GET",
  "breakpoints": [
    { "id": "after_query", "elapsed_since_previous_ms": 45.21 },
    { "id": "after_processing", "elapsed_since_previous_ms": 30.15 }
  ],
  "total_time": "75.36ms"
}

๐Ÿง  How to Analyze Performance Logs

  • ๐Ÿ“Š Visualize in Kibana for real-time dashboards
  • โฐ Set up alerts for requests over 500ms
  • ๐Ÿ” Spot bottlenecks by comparing breakpoints
  • ๐Ÿš€ Track improvements after optimization changes

โœ… Conclusion: Take Control of Laravel Performance

By following this tutorial, youโ€™ve added a lightweight, configurable, and insightful performance monitoring tool to your Laravel stack.

๐ŸŽฏ Benefits Recap:

  • Gain visibility into request timing
  • Measure code-level bottlenecks
  • Keep logs structured and searchable
  • Turn off monitoring anytime with .env

๐Ÿ”ฎ Whatโ€™s Next?

Enhance this system with:

  • ๐Ÿ“ฆ Memory usage tracking
  • ๐ŸŒ Frontend performance correlation (via request ID)
  • ๐Ÿ“ฅ Email/Slack alerts for slow requests
Tags: #laravel #performance
Oussama GHAIEB - Laravel Certified Developer in Paris

Oussama GHAIEB

Laravel Certified Developer | Full-Stack Web Developer in Paris

14+ years experience โ€ข 20+ projects
Read more about me โ†’

Comments (0)

No comments yet. Be the first to comment!


Leave a Comment

More Posts :