Appearance
Telemetry Monitors
Beta
Telemetry monitors are in beta, on paid plans. Limits are subject to change.
A telemetry monitor watches ingested data: the number of error logs, a service's p95 latency, a metric crossing a line, or a job that stops reporting. Each monitor runs every minute (or less often), keeps a state per group, and alerts the same contacts as check monitors.
Create monitors under Telemetry → Monitors → New Monitor, or from anywhere a query already exists: Create Monitor in Explore, on a log pattern, or on a derived metric.
The live preview
While editing, the editor evaluates the unsaved monitor against real data:
- Right now: what each group would be, and the closest one to its threshold.
- The chart: the value at each evaluation (one every interval, each over its own window) with the fail and degraded thresholds, and their recovery values, drawn across.
- Backtest: those evaluations replayed through the current settings: how many times the monitor would have failed or degraded over the chart's range, and when.
- Cost: what one evaluation reads, so a heavy query shows up before it runs every minute.
- Sample alert: the SMS, email and webhook it would send, rendered from a real group's value.
What to measure
Each monitor has up to eight queries, a to h, over one Stream:
| Source | Measures | Example |
|---|---|---|
| Logs, traces, events | count, count_distinct, sum, avg, min, max, p50 to p99, count_per_min of a field, over a search | count where level:error |
| Metrics | A metric read as rate, increase, avg, p95 and so on, combined across series | http.server.duration as p95 |
A metric is many series, one per set of tags (each host, worker or route). Each series is read over the window first (Over time), then they combine into the one value the thresholds judge (Across series): avg is the typical series, max the worst one, min the lowest, sum all of them together. Left on auto, counters and counts add up, min and max stay as they are, and the rest average. An average hides a single series: a gauge that is 1 on one worker and 0 on three reads 0.25. To alert when any one crosses, use max (or min), or judge each on its own with For each. Histograms merge exactly, so this doesn't apply to them.
With more than one query, a formula combines them, for example an error rate: a / b * 100 where a counts errors and b counts all requests. Formulas also compare (a > bool 100), combine series (a unless b) and call functions (clamp_max(a / b * 100, 100)); see formulas.
One alert per group
For each (group by) up to four fields to get one state, and one alert, per distinct value: service alerts separately for checkout and search. A group that stops reporting is forgotten after a day: its incident closes with a note, and no recovery alert goes out, since nothing recovered.
When it alerts
| Setting | What it does |
|---|---|
| Over the last | The window each evaluation aggregates, 1 minute to 1 day. |
| Every | How often it evaluates (the plan sets a 1 minute floor). |
| Delay | Evaluate this far behind now, so late data has landed first. |
| Fail / Degraded | The thresholds, above or below (optionally "or equal"). Crossing Fail makes the monitor FAILING; Degraded is optional and sits before it. |
| Recover at | Stay at a level until the value passes back through this point, so a value hovering at the line doesn't flap. |
| Alert / recover after | Evaluations in a row that must cross (or clear) before the state changes. |
No data
A setting decides what a group with no data does: keep the last state (the default), treat the group as OK, evaluate as 0, or fail after a chosen silence. Counts and sums are already 0 over an empty window, so a silent group reads 0 for them either way. The same goes for metrics: a counter's rate or increase and a histogram's count read 0 when nothing was reported, so a monitor on an error counter recovers once the errors stop. Gauges, averages and percentiles have no value then, and follow this setting.
Heartbeats
A heartbeat alerts when something that should keep arriving stops: a nightly job, a cron, a queue consumer. Pick Heartbeat, a search that matches the job's "done" record, and how often it should appear. The monitor fails when a window passes without one. With For each host, every host has its own heartbeat. Heartbeat Monitors has setup, examples for cron, GitHub Actions and Kubernetes, and how to size the window.
Composite monitors
A composite is a condition over other monitors, failing while it holds:
checkout_errors && (latency || !payments_up)Each reference is true while the referenced monitor is failing (or degraded, when degraded counts too). and, or and not work as well as &&, || and !. A composite can combine check and telemetry monitors, and lives with the kind of page it was created on. Use one to page only when a symptom and its likely cause agree. It's checked once a minute, so Fail after and Recover after are the minutes the condition must hold, or stay clear, in a row.
A status page monitor is one of the check monitors a composite can combine, so a condition can read "Stripe reports a problem and checkout is failing".
Watching the same service twice
Two of a composite's monitors that watch the same service fail together: a status page monitor on Stripe and a check that depends on Stripe, say, or two monitors on the same component. A condition over both counts one outage twice, and a && b stops being a second opinion. The composite shows a warning that names the service and the monitors sharing the service, beside the monitors and again on save. The warning never blocks saving, and is fine for "either of them". Whole services overlap with any of their components, and different components of one service don't overlap. Paused monitors don't count.
Notifications
Every monitor, check or telemetry, shares the same alert settings:
- Priority, P1 (most urgent) to P5. P1 and P2 open major incidents. A contact method can take only P1, or P1 to P3, and so on.
- Alert on degraded, and when it recovers. A recovery alert goes out when a monitor that alerted is healthy again. Without degraded alerts, a drop from failing to degraded stays part of the same incident until it's healthy. With them, that drop is its own alert ("no longer failing"), and going back to healthy from a warning sends a recovery too.
- While failing, alert once, or every 15 minutes to every day, at most a number of times.
- Mute a monitor, or one group, for an hour to a week or until unmuted. States and incidents keep updating; only the alerts are held back. If it's still failing when the mute ends, the alert it held back goes out then.
Message templates
Custom alert text takes variables in double braces and replaces the default wording on every channel.
{{#is_recovery}}Resolved: {{/is_recovery}}{{monitor.name}} for {{group.service}} is {{state}}: {{value}} {{unit}} (limit {{threshold}})| Variable | |
|---|---|
monitor.name, monitor.url, monitor.priority | The monitor, a link to it, and its priority |
state, previous_state | FAILING, DEGRADED or OK, and the state before |
cause | Why, in words |
value, threshold, unit | The evaluated value and the threshold it crossed |
group, group.<label> | The group (service=checkout), or one of its labels |
target | The host a check monitor watches |
duration, at | How long it was (or has been) failing, and when |
Sections show text only when a condition holds, and {{^...}} when it doesn't: is_failing, is_degraded, is_recovery, is_renotify, is_nodata, is_error.
Webhook payload
Webhooks receive JSON with the fields a receiver needs to route and dedupe:
json
{
"kind": "incident.failing",
"event": "failing",
"message": "Checkout errors is failing for service=checkout: 67 > 40",
"monitorId": "mon_...",
"monitorName": "Checkout errors",
"monitorKind": "TELEMETRY",
"priority": 2,
"state": "FAILING",
"previousState": "DEGRADED",
"cause": "67 > 40",
"group": { "key": "service=checkout", "labels": { "service": "checkout" } },
"value": 67,
"threshold": 40,
"incidentId": "inc_...",
"url": "https://console.latency.app/...",
"at": "2026-09-28T23:42:25.000Z"
}kind is incident.failing, incident.recovered, incident.renotify, monitor.degraded, check.failed (a check monitor's first failure, before it is confirmed) or monitor.error (the monitor couldn't be evaluated). Status page and dependency alerts also carry the service and what it said: service is its slug, name and domain, and serviceStatus holds its condition (operational, maintenance, degraded, incident, major_incident, outage), phase (investigating, identified, monitoring, ...) and incident, the leading incident's title, url, since and updatedAt (null when there is none). A dependency alert's serviceStatus also lists the components that tripped.
Monitor detail
A monitor's page shows the value against the thresholds (per group, when groups are picked for charting), each group's state and how far it is into confirming or recovering, the run log with what each evaluation read, its incidents, and runs live as they happen.
Limits
| Plan | Telemetry monitors |
|---|---|
| Hobby | 5 |
| Pro, Founders | 25 |
| Team | 200 |
| Enterprise | 1,000 |
Composites count toward the kind of page they were created on.
API
Everything the console does is in the API (and the CLI):
Telemetry monitors: list | List telemetry monitors |
Telemetry monitors: create, update | Create or change one |
Telemetry monitors: preview | Evaluate, chart and backtest a definition without saving |
GET /v1/monitors/groups, /runs | A monitor's groups, and its evaluations per group |
POST /v1/monitors/mute | Mute a monitor or one group |
POST /v1/monitors/createComposite, /updateComposite, /previewComposite | Composites; each returns warnings for services two of its monitors share |
POST /v1/monitors/createStatusPage, /updateStatusPage, /previewStatusPage | Status page monitors |
POST /v1/monitors/previewAlert, GET /v1/monitors/templateHelp | Render a sample alert, and the template variables |