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.

Turning it on
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
'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
'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. |
| 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. |

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. |
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
'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:
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.comcovers every host belowexample.combut notexample.comitself, so list both if you want both. - Guzzle used directly, outside the
Httpfacade, 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.