> For the complete documentation index, see [llms.txt](https://core-foundation-doc.rupeshstha.com.np/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://core-foundation-doc.rupeshstha.com.np/apm-and-devtools/server-timing.md).

# Server Timing

Core Foundation includes built-in support for **Server-Timing** headers, allowing you to monitor the performance of your API requests directly in the browser's DevTools Network tab.

## Enabling APM

Ensure the profiling middleware is registered in your `bootstrap/app.php` (for Laravel 11+) or `Http/Kernel.php`:

```php
$middleware->append(CoreFoundation\Http\Middlewares\ServerTimingMiddleware::class);
```

You can control APM via the `config/core-foundation.php` or `.env`:

```env
CORE_FOUNDATION_PROFILING_ENABLED=true
```

## Automatic Measurements

When `ServerTimingMiddleware` is active, the following are measured automatically:

* **Database Queries**: Aggregate count and total duration via `DatabasePerformanceListener`.
* **Request bootstrap**: Time from process start to first middleware, recorded as `app`.

All other measurements are **opt-in** — see below.

## Opt-in: Controller Dispatch Timing

Register `ProfilingMiddleware` to measure full controller dispatch time and receive a `slow-Controller` warning when a configurable threshold is exceeded:

```php
$middleware->append(CoreFoundation\Http\Middlewares\ProfilingMiddleware::class);
```

Configure in `config/profiling.php`:

```php
'enabled'      => env('PROFILING_ENABLED', false),
'environments' => ['local', 'staging'],
'layers'       => ['controllers' => true],
'thresholds'   => ['controller' => 200], // ms
```

## Opt-in: Service Pipeline Timing (`MeasuresPerformance`)

Add to any service to automatically wrap every `throughPipes()` call in a Server-Timing metric:

```php
use CoreFoundation\Traits\Devtools\MeasuresPerformance;

class OrderService extends BaseService
{
    use MeasuresPerformance;

    public function place(array $data): PlaceOrderData
    {
        // Measured as "OrderService.place" automatically
        return $this->throughPipes('place', $data, function ($payload) {
            // ...
        });
    }

    public function expensiveReport(): ReportData
    {
        // Manual block measurement
        return $this->measure('order-report', fn () => $this->buildReport());
    }
}
```

## Opt-in: Cache Hit/Miss Timing (`MeasuresCachePerformance`)

Add to any service that uses `cacheForever()` or `cacheTtl()` to record whether each cache call was a hit or miss:

```php
use CoreFoundation\Traits\Devtools\MeasuresCachePerformance;

class OrderService extends BaseService
{
    use MeasuresCachePerformance; // replaces HasCacheable — no other change needed

    public function find(int $id): PlaceOrderData
    {
        return $this->cacheForever(
            tags:    ['orders'],
            key:     "orders.detail.{$id}",
            closure: fn () => PlaceOrderData::fromArray(Order::findOrFail($id)->toArray()),
        );
        // Recorded as "cache:orders.detail.42;desc=Cache hit: orders.detail.42;dur=0.3"
    }
}
```

## Viewing Results

Open your browser's **DevTools > Network**, select an API request, and look at the **Timing** tab. You will see a "Server-Timing" section with entries like:

* `app;desc="Bootstrap";dur=3.1`
* `db;desc="Database Queries (4)";dur=12.5`
* `Controller;desc="Controller dispatch";dur=88.1`
* `OrderService.place;dur=72.4`
* `cache:orders.detail.42;desc="Cache hit: orders.detail.42";dur=0.3`

Server-Timing headers add negligible overhead. Gate them behind `PROFILING_ENABLED=false` in production if preferred.
