Beacon Observe — product requirements
An observability service for engineering teams: metric time series for services and environments, stat panels, deploy annotations, a searchable log explorer with level facets, and alert rules that evaluate live, with silences. This release exposes the service as an HTTP API over a frozen synthetic dataset whose clock stands at 30 Sep 2026 12:00 UTC.
Problem. During an incident, on-call engineers need to see quickly what changed, when and where, and trust that charts, stats, logs and alerts all tell the same story on the same time axis.
Users
- On-call engineer — See the error spike, the deploy that preceded it and the logs that explain it, then confirm the alert and its state.
- Service owner — Define alert rules that fire only on sustained breaches and silence them during maintenance.
- Dashboard builder — Pull series with a sensible resolution for any time range.
Goals
- Time series are aligned to the requested window and use a resolution that keeps each series to a few hundred points.
- Alerts fire only when the whole for-window breaches the threshold, and silences hide only active alerts.
- Log facets always describe the whole result set for the other filters, not just the visible level.
- Each caller session keeps its own rules, silences and dashboards.
Out of scope
- Dashboard user interface
- Real data ingestion; data is synthetic and frozen
Contents
Environment metadata
Published facts the client needs to build its controls.
- The frozen now is 1790769600000 (30 Sep 2026 12:00:00 UTC)
- Services are api-gateway, checkout, search and auth; environments production and staging; metrics latency_p95, rps, error_rate and cpu
- There are 8 relative ranges from 15m to 7d
- The incident is on service "checkout" from 09:40Z to 10:05Z on that day
Time series
Metric values over a time window, per service and environment.
- 15m: step 15000 ms and 61 points
- 1h: step 15000 ms and 241 points; error_rate carries unit "%"; the last checkout value is 0.61
- 6h: step 60000 ms; without a service filter four series come back, one per service, 361 points each
- 7d: step 900000 ms and 673 points
- Steps are 15 s up to 3 h, then 1 m, 5 m, 15 m and 1 h as the range grows
- For range 1h the first timestamp is now minus 3,600,000 ms and the last timestamp is now (1790769600000)
- Every timestamp is a whole number of steps after the first, so a spike plots at its real time
- Before 09:40Z values are about 0.5-0.7; from 09:40Z to 10:05Z every value is between 7.5 and 11.5 (peak 11.42); after 10:05Z they return to about 0.5-0.7
- In staging there is no spike (maximum 0.62)
- Metric mem: 422 "metric must be one of latency_p95, rps, error_rate, cpu"
- Service billing: 422 Unknown service "billing"
- from after to: 422 "from must be before to"
- An end in the future is returned as now (1790769600000)
- A start earlier than 7 days before now is returned as now minus 7 days
Stat panels
Current, average and maximum of a metric per service over a range.
- error_rate over 6h (current / avg / max): checkout 0.61 / 1.24 / 11.42; api-gateway 0.37 / 0.4 / 0.46; search 0.32 / 0.3 / 0.34; auth 0.19 / 0.2 / 0.23
- Over 1h checkout is 0.61 / 0.59 / 0.68 because the incident is outside the window; other services are unchanged
Deploy annotations
Deploy markers to overlay on charts.
- Over 6h there are two deploys, both of checkout: one by release-bot at 09:38Z and a rollback fix by m.ito at 10:02Z
- Over 7d there are four deploys, adding one for search on 29 Sep and one for auth on 28 Sep
Log explorer
Search logs by service, time, level and text, with level facets.
- Checkout logs from 09:40Z to 10:05Z: 68 items, facets DEBUG 0, INFO 0, WARN 0, ERROR 68
- The first item is level ERROR, message "NullPointerException in CartPricer.apply", traceId "9cfe2913"
- Last hour, level ERROR: 15 items, all ERROR; facets DEBUG 135, INFO 510, WARN 61, ERROR 15
- Text "502" in the last hour: 2 items; facets INFO 1, ERROR 1
- Over 6h with limit 5: exactly 5 items
Alert rules and silences
Rules evaluated live against the series, with a for-window and silences.
- AR-0001 "Checkout error budget burn": OK, current 0.61, last fired 10:05Z (1790762700000)
- AR-0002 "Gateway latency": OK, current 134.45, never fired
- AR-0003 "Search CPU saturation": OK, current 61.25, never fired
- Checkout error_rate > 5 for 5 minutes previews as OK with current 0.61 and last fired 10:05Z
- api-gateway latency_p95 < 1000 for 5 minutes previews as Firing with current 134.45
- An operator other than > or < is rejected with 422 "service, metric, op (> or <) and numeric threshold are required"
- Listing rules afterwards still shows only AR-0001 to AR-0003
- Creating "Auth CPU low" (auth cpu < 100 for 5 minutes) answers 201 with a new id AR-NNNN and the rule is Firing
- Creating a silence with until 2026-09-30T18:00:00Z answers 201 with an id SIL-NNNN
- The rule then shows Silenced with silencedUntil "2026-09-30T18:00:00Z"
- A silence until 2026-09-30T11:00:00Z is accepted with 201
- The rule still shows Firing and silencedUntil is null
- The rule "Auth latency creeping" (auth latency_p95 > 100 for 5 minutes) is OK with current 112.31, because the last two minutes breach 100 but the minutes 11:55 to 11:57 do not
- The rule becomes Firing only once all samples of the 5-minute window breach
- A rule without service, metric, op and threshold: 422 naming the missing fields
- A silence without ruleId and until: 422 naming the missing fields
Session isolation
Callers can keep private rules, silences and dashboards.
- A rule created under session A does not appear under session B, which sees only AR-0001 to AR-0003
Dashboards
Saved collections of panels.
- One dashboard, DB-0001 "Service overview", with panels latency_p95, rps, error_rate and cpu
Non-functional requirements
Glossary and rules
| For-window | The number of minutes a threshold must be breached continuously before a rule fires. |
|---|---|
| Facet | A count of log items per level. |
| Step | The spacing between points in a series, in milliseconds. |