Configuration reference
Configuration reference
The package ships a fully-commented config/telemetry-ui.php. It works out of
the box with three env vars (metrics/traces/logs URLs); everything else has a
sensible default. Publish it only if you need to change something not reachable
by an env var:
php artisan vendor:publish --tag=telemetry-ui-config
This page is the exhaustive reference. Each key lists its default and the env var (if any) that overrides it without publishing.
Core
| Key | Env | Default | Notes |
|---|---|---|---|
enabled |
TELEMETRY_UI_ENABLED |
true |
Master switch. When off, the package registers no routes (SPA, API or assets) or MCP server — completely inert (e.g. on queue workers). Boot stays cheap either way. |
path |
TELEMETRY_UI_PATH |
telemetry-ui |
URL prefix the dashboard is served from; the API lives under {path}/api/v2 and the built assets under {path}/build. Deliberately not telemetry so it doesn't clash with the /telemetry/metrics scrape endpoint cboxdk/laravel-telemetry registers. |
ignore_own_requests |
TELEMETRY_UI_IGNORE_OWN_REQUESTS |
true |
Asks cboxdk/laravel-telemetry (Telemetry::ignorePaths()) not to trace the dashboard's own page loads and API calls ({path} and {path}/*), so browsing the dashboard never floods the app's request data. Registered when the telemetry manager resolves; no effect when mounted at the site root. |
domain |
TELEMETRY_UI_DOMAIN |
null |
Optional domain to pin the routes to. |
middleware |
— | ['web'] |
Middleware on every dashboard and API route. The package always appends its own Authorize middleware (checks the viewTelemetryUi gate), so you don't list it. The build/* asset route skips the gate and the throttle. |
throttle |
TELEMETRY_UI_THROTTLE |
600,1 |
Rate limit as maxAttempts,decayMinutes. The SPA sends one API request per panel, facet list and Explore query (and again on each auto-refresh tick), so the budget is per request, not per page. Set to null / empty to disable. |
copy_link |
TELEMETRY_UI_COPY_LINK |
true |
The header button that copies a shareable URL for the current view. Turn it off where the URL can't travel — a desktop host on 127.0.0.1:<random port> copies a link only that machine can open. |
brand.name / brand.logo / brand.accent |
TELEMETRY_UI_BRAND_NAME / _LOGO / _ACCENT |
app name / — / — | White-label the shell: rail name, logo image URL, accent colour. There are no views to override in v2; for more, read the JSON API. |
dimensions.label_ttl |
TELEMETRY_UI_LABEL_TTL |
300 |
How long a name from TelemetryUi::resolve() is cached per value (misses included). 0 disables caching. See dimensions. |
analytics.internal_hosts |
TELEMETRY_UI_INTERNAL_HOSTS |
— | Comma-separated hosts that count as your own site, so a self-referral is classified as "Internal" instead of "Referral". Subdomains count. |
host-services |
— | built-ins | The exporter tiles on a host's detail page: each entry is a service name (mysql, redis, postgres, node) with an up metric and the tiles to show, where {host} is substituted with the host being viewed. Add an entry to surface your own exporter. |
The gate
Access is governed by the viewTelemetryUi gate. The default definition
allows access only in the local environment; open it up in your own
AppServiceProvider (app providers boot after the package, so your definition
wins):
Gate::define('viewTelemetryUi', fn ($user) => $user?->isAdmin() ?? false);
The gate also supports per-page restriction and a separate write ability
(manageTelemetryUi) — see authorization.
Query cache & retries
Every panel issues live backend queries each time the SPA fetches it (on load, on a scope change and on each auto-refresh tick).
| Key | Env | Default | Notes |
|---|---|---|---|
cache.ttl |
TELEMETRY_UI_CACHE_TTL |
5 |
Seconds to cache decoded GET responses (plain arrays — never DTOs, so it's safe on any store). Keep it short so data stays fresh; 0 disables. A connection may set its own cache to override. |
retries |
TELEMETRY_UI_RETRIES |
2 |
Retries for a transient connection blip before giving up. |
Backend failures are never cached, and their full detail (URL, response body) is logged server-side while the dashboard shows only a generic message — see connections.
Connections
Named connections to your backends live under connections. The keys
metrics, traces and logs are the defaults; add more named connections and
request them explicitly (e.g. a per-tenant Mimir). Drivers: prometheus /
mimir (metrics), tempo (traces), loki (logs). See
connections and the Grafana proxy
recipe for the full story; the
env-var surface is:
| Connection | URL env | Token env | Tenant env | Extras |
|---|---|---|---|---|
| metrics | TELEMETRY_UI_METRICS_URL |
TELEMETRY_UI_METRICS_TOKEN (falls back to TELEMETRY_UI_TOKEN) |
TELEMETRY_UI_METRICS_TENANT |
TELEMETRY_UI_METRICS_DRIVER, TELEMETRY_UI_METRICS_PREFIX, TELEMETRY_UI_METRICS_BASIC_AUTH, TELEMETRY_UI_METRICS_TIMEOUT |
| traces | TELEMETRY_UI_TEMPO_URL |
TELEMETRY_UI_TEMPO_TOKEN (→ TELEMETRY_UI_TOKEN) |
TELEMETRY_UI_TEMPO_TENANT |
TELEMETRY_UI_TEMPO_BASIC_AUTH, TELEMETRY_UI_TEMPO_TIMEOUT |
| logs | TELEMETRY_UI_LOKI_URL |
TELEMETRY_UI_LOKI_TOKEN (→ TELEMETRY_UI_TOKEN) |
TELEMETRY_UI_LOKI_TENANT |
TELEMETRY_UI_LOKI_BASIC_AUTH, TELEMETRY_UI_LOKI_TIMEOUT |
tenantsets theX-Scope-OrgIDheader (multi-tenant Mimir/Tempo/Loki).tokenbecomes a BearerAuthorizationheader;basic_auth(user:pass) becomes a Basic one. Add arbitrary headers under a connection'sheaders.prefix(metrics) is the API path prefix —mimiris justprometheusunder a prefix (default/prometheus).verify(TELEMETRY_UI_METRICS_CA_BUNDLE,_TEMPO_,_LOKI_) points at a CA bundle for a backend behind a private certificate authority. It takes a path; leave it unset to use the system trust store.
Issue tracker (optional)
Setting connections.issues.driver adds an Issues page. Disabled by
default. See issue trackers.
| Key | Env |
|---|---|
connections.issues.driver |
TELEMETRY_UI_ISSUES_DRIVER (github / sentry / linear) |
connections.issues.repo |
TELEMETRY_UI_GITHUB_REPO |
connections.issues.url |
TELEMETRY_UI_ISSUES_URL |
connections.issues.token |
TELEMETRY_UI_ISSUES_TOKEN |
View state
| Key | Env | Default | Notes |
|---|---|---|---|
state.enabled |
TELEMETRY_UI_STATE |
true |
Remember the reader's time window, auto-refresh interval and scope between requests. false restores URL-or-default with nothing carried. |
state.cookie |
TELEMETRY_UI_STATE_COOKIE |
telemetry_ui_view |
Cookie name. Excluded from cookie encryption — the auto-refresh control writes it from the browser. It is a preference, never an authorization input. |
state.lifetime |
TELEMETRY_UI_STATE_LIFETIME |
525600 |
Cookie lifetime in minutes (a year). |
See view state for the precedence rules and the host API.
Discovery caches
| Key | Env | Default | Notes |
|---|---|---|---|
detection.ttl |
TELEMETRY_UI_DETECTION_TTL |
300 |
Seconds to cache the one probe query that decides whether a metric-detected page (e.g. the Statamic page) is visible. |
fleet.ttl |
TELEMETRY_UI_FLEET_TTL |
60 |
Seconds to cache the service/environment list behind the sidebar scope switcher. |
Signal context (correlation)
Correlates a trace with the host/runtime signals recorded around it. Full treatment in correlation.
| Key | Env | Default | Notes |
|---|---|---|---|
context.enabled |
TELEMETRY_UI_CONTEXT |
true |
Show the context strip beside the trace waterfall. |
context.window |
TELEMETRY_UI_CONTEXT_WINDOW |
600 |
Seconds padded around a trace so surrounding metric samples land in view. |
context.baseline_window |
TELEMETRY_UI_CONTEXT_BASELINE |
21600 |
Lookback (seconds) for each signal's "typical" value — the number the tile flags against ("95%, typical 30%"). |
context.baseline_ttl |
TELEMETRY_UI_CONTEXT_BASELINE_TTL |
120 |
How long a computed baseline is cached. Baselines are multi-hour averages that barely move, so this is well beyond the live cache and shared across nearby traces. |
context.signals |
— | 5 built-ins | The signal list — each a label / group / unit / PromQL query with a {scope} token (or {host}, {service}, {environment}), and optionally keep_zero. See correlation to add your own. |
hosts.cpu / hosts.memory |
TELEMETRY_UI_HOSTS_CPU / TELEMETRY_UI_HOSTS_MEMORY |
— | PromQL for the Hosts table's CPU and memory columns, one series per host, when the OTel host metrics aren't there (node_exporter). {environment} expands to the viewer's environments for an =~ matcher. |
hosts.host_label |
TELEMETRY_UI_HOSTS_HOST_LABEL |
metrics host label | The label those queries carry the host in (nodename for node_exporter). |
scope.labels.<signal>.<dimension> |
TELEMETRY_UI_METRICS_ENVIRONMENT_LABEL, … |
laravel-telemetry's names | What service, environment and host are called in each backend. See authorization. |
MCP server
The local stdio server (php artisan mcp:start telemetry-ui) always works.
The keys below only gate the optional HTTP transport. See the MCP
cookbook.
| Key | Env | Default | Notes |
|---|---|---|---|
mcp.web.enabled |
TELEMETRY_UI_MCP_WEB |
false |
Expose the server over HTTP. |
mcp.web.path |
TELEMETRY_UI_MCP_PATH |
telemetry-ui/mcp |
HTTP endpoint path. |
mcp.web.middleware |
— | ['auth:api', 'throttle:60,1'] |
The only auth on this endpoint (the dashboard gate does not cover it). Keep an auth guard here. |
mcp.web.oauth |
TELEMETRY_UI_MCP_OAUTH |
true |
Register the OAuth 2.1 + Dynamic Client Registration endpoints laravel/mcp provides on top of laravel/passport. If this is true and Passport is not installed, the app throws at boot rather than expose a half-configured authorization server — install Passport, or set this to false and front the endpoint with your own auth middleware. |
Annotations
Point-in-time markers drawn as vertical lines on every chart. Full treatment in the annotations cookbook.
| Key | Env | Default | Notes |
|---|---|---|---|
annotations.enabled |
TELEMETRY_UI_ANNOTATIONS |
true |
Read + draw annotations. |
annotations.ttl |
TELEMETRY_UI_ANNOTATIONS_TTL |
30 |
Seconds to cache the annotation read. |
annotations.markers |
— | 8 built-ins | Map of marker key → { event, label, color, id_label, notes_label }. Each is both read (matched in Loki by event) and written (php artisan telemetry-ui:annotate <key>). Add your own. |
annotations.auto_version.enabled |
TELEMETRY_UI_AUTO_VERSION |
false |
Let telemetry-ui:scan-versions auto-annotate a newly-seen laravel_version. |
annotations.auto_version.metric |
TELEMETRY_UI_AUTO_VERSION_METRIC |
system_cpu_utilization_ratio |
The metric carrying the laravel_version label to scan. |
annotations.auto_version.lookback_days |
TELEMETRY_UI_AUTO_VERSION_LOOKBACK |
30 |
How far back the scan looks for versions. |
Panels
panels is the ordered list of dashboard panels (classes extending
Cbox\TelemetryUi\Panels\Panel). Entries here render first; packages append
their own at runtime with TelemetryUi::panel(MyPanel::class). This key was
cards in 1.x; a leftover cards key is ignored. See pages &
panels.
Live tail
The SSE live-tail endpoint reads two keys, both in the published config and both with env vars: Add them if you need other values:
| Key | Default | Notes |
|---|---|---|
stream.interval |
2 |
Seconds between backend polls on an open stream. |
stream.window |
25 |
Seconds a stream connection lives before it ends and the browser reconnects (resuming from Last-Event-ID). |