Sampling
Sampling lives inlaravel/nightwatch and runs inside the customer’s PHP process. The trace decision is set at the start of the request and applied at the end — sensors record into the trace either way, but at flush time only sampled-in traces are shipped to the agent. That means the agent only sees and stores what Nightwatch already decided to keep, with no second-pass drop on the agent side.
Configure it in .env:
NIGHTWATCH_EXCEPTION_SAMPLE_RATE=1.0 to keep every exception regardless of the parent request’s sample decision. See the throughput guide for how to pick a rate.
In-code filtering
Use Nightwatch’s filtering API to exclude specific events inline:Context metadata
Attach custom key-value data to traces using Laravel’sContext facade (Laravel 11+):
MAX_PAYLOAD_BYTES) — oversized payloads are rejected with 5:ERROR, not silently truncated — so keep context entries small and structured rather than pushing large blobs through the tracer.
Good things to stash in context:
- Tenant / workspace / organization ID.
- Feature flag decisions that affected this request.
- User role or permission set.
- Deploy-specific debugging flags you set temporarily during an incident.
Context — those entries are passed through verbatim.
Searching log context
The context you attach to a log — the array inLog::error('Payment failed', ['order_id' => 8412]) — is shown on the log’s detail page, but the Logs page search box does not match inside it by default. Log context is stored compressed, and PostgreSQL cannot decompress it while running a query, so the search falls back to the message and the page shows a “Narrowed search” note explaining that.
Set NIGHTOWL_LOG_CONTEXT_SEARCHABLE=true to store it uncompressed and make it searchable. It trades storage for that, and existing logs need converting — see Searchable log context for the sizing check and the conversion command.
Redaction
PII redaction lives inlaravel/nightwatch and runs inside the customer’s PHP process before the payload is shipped to the agent. Configure it in .env:
NIGHTWATCH_REDACT_HEADERS strips named headers from every request record. NIGHTWATCH_REDACT_PAYLOAD_FIELDS recursively replaces matching keys in the request payload with a [N bytes redacted] marker. Both are applied at record-assembly time, so neither the agent’s TCP buffer, SQLite WAL, nor PostgreSQL drain ever see the un-redacted values.
Note: Nightwatch only writes the request payload for HTTP 500 responses, and only for application/json and form-encoded bodies. Response bodies are never written.
Combining the layers
A common production config looks like:Nightwatch::ignore() around health-check endpoints and Context::add() for tenant IDs, you get a dataset that’s lean, safe to store, and actually queryable.