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

> Author: [Oussama Ghaieb](https://oussama.ghaieb.com/about-me)
> Canonical: https://oussama.ghaieb.com/posts/laravel-precision-monitoring-break-down-and-analyze-each-step-of-your-code

# <span class="hover:bg-yellow-100">Laravel Precision Monitoring: Break Down and Analyze Each Step of Your Code</span>

## 🔍 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`:

```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.

```php
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:

```php
$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:

```php
$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:

```php
'performance_monitor_enabled' => env('PERFORMANCE_MONITOR_ENABLED', true),
```

Then toggle it in `.env`:

```env
PERFORMANCE_MONITOR_ENABLED=false
```

This keeps your production logs clean when needed.

---

## 🧪 Example in a Controller

```php
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

```json
{
  "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
