# Requests

A request event is one trip through your application: the route, the status, the time it took and where the time went. It fills the performance pages, and it is the envelope that queries, mail, notifications and cache operations arrive in.

![The Requests page in the panel: every route with its application, its request counts by status and its p95](/images/docs/requests.png)

## Turning it on

```env .env
LB_TRACK_REQUESTS=true
```

Then accept **Requests** on the application in the panel.

> **Note.** It is off by default because it is the one kind of tracking that touches every request you serve. With the switch off the middleware is never pushed and the listeners are never subscribed, so the cost is nothing rather than nearly nothing.

## Sampling

```php config/larabug.php
'sample_rate' => env('LB_REQUEST_SAMPLE_RATE', 0.1),
'exception_sample_rate' => env('LB_REQUEST_EXCEPTION_SAMPLE_RATE', 1.0),
```

One request in ten, decided when the request arrives rather than when it ends: deciding at the end would mean paying to collect everything first, including the nine you throw away.

The decision is revisited twice. Once when the route is known, so the ignore list can drop a request that had already started recording. And once if the request throws, at `exception_sample_rate`, because the request that failed is the one worth having. At the default of `1.0` every failing request is kept, whatever the coin said at the door.

## Ignoring paths

```php config/larabug.php
'ignore_paths' => [
    '/horizon*',
    '/telescope*',
    '/_debugbar*',
    '/up',
    '/health*',
],
```

Health checks and dashboards: traffic you serve, but not traffic worth measuring. The pattern matches the path, and `*` is the only wildcard.

## What is recorded

The route and its method, the status, the total duration and the time in each stage: before your middleware, inside the action, after it, and to the response being sent. Then, for the work inside it, a count and the detail of each:

| Kind | Detail kept |
| --- | --- |
| Queries | The normalised statement, the connection, the duration, where in the request it ran. |
| Outgoing HTTP | The method, the host and path, the status, the duration. Query values are stripped. |
| Mail | The mailable, the subject, how many recipients, how long the send took. |
| Notifications | The notification class, the channel, the notifiable type, whether it worked. |
| Cache | The operation, the store, the key prefix, the TTL on a write. |
| Livewire | The component, the method, the parameters and the property updates. |

![One request in the panel: POST /checkout with its timeline, the queries it ran, the call to Mollie, the mail and the notification](/images/docs/request-detail.png)

## Caps

| Key | Default | What it limits |
| --- | --- | --- |
| `max_queries` | `100` | Statements kept per request. |
| `max_outgoing` | `50` | Outgoing HTTP calls. |
| `max_mail` | `50` | Mail messages. |
| `max_notifications` | `50` | Notifications. |
| `max_cache_events` | `100` | Cache operations. |
| `max_livewire_events` | `100` | Livewire updates. |

The counters keep counting past the cap. A request that ran four thousand queries still says four thousand; what stops is the list of statements, because the reason to look at that request is the number rather than the four thousandth statement.

## What is not sent

| Key | Default | What it does |
| --- | --- | --- |
| `capture_ip` | `true` | The client address. |
| `capture_user` | `true` | The authenticated user, through [user context](/docs/laravel/user-context). |
| `capture_headers` | `true` | Request headers, with `redact_headers` replaced by a constant marker. |
| `capture_payload_on_error` | `false` | The request body, and only on a 5xx, and never on a GET. |
| `capture_mail_recipients` | `false` | Full addresses instead of the domains they were sent to. |
| `capture_cache_keys` | `false` | Whole cache keys instead of the part before the first colon. |

`redact_fields` is applied to a captured payload depth first and by substring, so `card[cvv]` and `user.password_confirmation` are both caught by the short list in the config.

## Livewire

```php config/larabug.php
'livewire' => [
    'track_livewire' => env('LB_TRACK_LIVEWIRE', true),
    'capture_parameters' => env('LB_LIVEWIRE_CAPTURE_PARAMETERS', true),
    'capture_updates' => env('LB_LIVEWIRE_CAPTURE_UPDATES', true),
    'max_value_length' => env('LB_LIVEWIRE_MAX_VALUE_LENGTH', 255),
],
```

A Livewire update is an HTTP request to one endpoint, which on its own tells you nothing. With this on, the request says which component was addressed and which method ran, and the waterfall reads as the interaction rather than as another POST to `/livewire/update`.

## Across applications

A request and the jobs it queued are already one trace. A call from one of your applications to another can join the same trace, when both report to LaraBug, but only once the calling side is told which hosts are yours:

```env .env
LB_TRACE_PROPAGATION_TARGETS=billing.example.com,*.internal.example.com
```

That fills `requests.trace_propagation_targets`, which is empty by default and so sends nothing anywhere. With hosts in it, the client adds a W3C `traceparent` header to calls made through Laravel's `Http` client to those hosts, and the application on the other end records its request as a child of yours. The trace page then shows both, with whatever each of them went on to start.

* List only applications you run yourself. A trace id has no business reaching a payment provider, a mail service or somebody's webhook.
* A host is matched on its name, without the port. `*.example.com` covers every host below `example.com` but not `example.com` itself, so list both if you want both.
* Guzzle used directly, outside the `Http` facade, sends nothing.
* The calling application needs client 4.0.0-beta.12 or newer, and the receiving one needs request tracking on.

The trace only crosses into applications you can open. If the other application is one you are not on, the trace stops at your side of the call, and nothing of the other side is shown.

## Batching

Requests are sent in batches of `batch_size`, twenty by default, and a batch that fails is retried `max_retries` times before it is dropped. Nothing is sent inside the request being measured: the flush happens after the response has gone.