Commit c025d2e
feat(telemetry): export per-status serve_shape request counter (#4500)
## What
Adds a new unsampled, per-request metric from the shape-serving path:
```
electric.plug.serve_shape.requests.count tags: [status, known_error, live]
```
It hangs off the existing `[:electric, :plug, :serve_shape]` telemetry
event (no new emission point) and threads a `known_error` flag into that
event's metadata, read straight off the `electric-internal-known-error`
response header.
## Why
We sample shape-request **spans** aggressively (head sampling + tail
overrides) to stay within our tracing event budget. That makes the span
dataset great for drill-down but unreliable as a health signal:
- It under-represents true volume (sampled), and
- It **drops some request classes entirely** — admission-control
rejections are marked `known_error` and are intentionally excluded from
span export, so a request plot built from spans can look perfectly
healthy while the system is actually shedding load under overload.
Admission rejection counts already exist as a metric
(`electric.admission_control.reject.count`), but there was no general,
status-dimensioned request counter. The existing `serve_shape` metrics
also (a) drop live/long-poll requests and (b) aren't tagged by response
status, so they can't express request mix or error rate.
This counter fills that gap:
- **Unsampled** — every request is counted, so there's no detection
floor. Errors and rejections are visible the moment they rise, not once
they cross a sampling threshold.
- **Counts live requests too** — unlike the other `serve_shape.*`
metrics, which `keep: live != true`. Cheap to do as an aggregated metric
(the reason we couldn't do it for spans doesn't apply).
- **Admission rejections appear inline** as `status=503,
known_error=true`. `check_admission` halts the conn, but a halt isn't a
raise, so the halted conn still flows through `emit_shape_telemetry/1`
and gets counted.
- **`known_error` matches the wire signal** — it's derived from the
`electric-internal-known-error` response header, the same byte
downstream consumers (e.g. the edge worker's tracing) key on, so the
classification is consistent end to end.
Intended use: this becomes the authoritative "requests by status / error
rate" dashboard panel and alert source, leaving the sampled span dataset
for exemplar drill-down.
## Changes
- `electric-telemetry`: define
`counter("electric.plug.serve_shape.requests.count", tags: [:status,
:known_error, :live])` against the existing event (explicit
`event_name`/`measurement` to avoid colliding with the existing
`serve_shape.count`).
- `sync-service`: add `known_error` to the `serve_shape` event metadata,
derived from the `electric-internal-known-error` response header. The
header check lives next to the code that sets it so the expected values
stay single-sourced.
## Cardinality
Bounded: `status` (~6 codes) × `known_error` (2) × `live` (2), per
stack.
## Notes
- One pre-existing gap is unchanged: the mid-stream re-raise path
(`Plug.Conn.chunk/2` raising after the response is committed) doesn't
emit the `serve_shape` event, so those requests aren't counted here —
same limitation that already affects every `serve_shape.*` metric.
- No rollout/rollback concerns: additive metric only, no behavior change
on the request path.
---------
Co-authored-by: Oleksii Sholik <oleksii@sholik.dev>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent c015163 commit c025d2e
5 files changed
Lines changed: 117 additions & 2 deletions
File tree
- .changeset
- packages
- electric-telemetry/lib/electric/telemetry
- sync-service
- lib/electric
- plug
- shapes/api
- test/electric/plug
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
Lines changed: 5 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
96 | 101 | | |
97 | 102 | | |
98 | 103 | | |
| |||
Lines changed: 2 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
451 | 451 | | |
452 | 452 | | |
453 | 453 | | |
454 | | - | |
| 454 | + | |
| 455 | + | |
455 | 456 | | |
456 | 457 | | |
457 | 458 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
390 | 390 | | |
391 | 391 | | |
392 | 392 | | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
393 | 400 | | |
394 | 401 | | |
395 | 402 | | |
| |||
Lines changed: 97 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
89 | | - | |
| 89 | + | |
| 90 | + | |
90 | 91 | | |
91 | 92 | | |
92 | 93 | | |
| |||
1044 | 1045 | | |
1045 | 1046 | | |
1046 | 1047 | | |
| 1048 | + | |
| 1049 | + | |
| 1050 | + | |
| 1051 | + | |
| 1052 | + | |
| 1053 | + | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
| 1085 | + | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
| 1089 | + | |
| 1090 | + | |
| 1091 | + | |
| 1092 | + | |
| 1093 | + | |
| 1094 | + | |
| 1095 | + | |
| 1096 | + | |
| 1097 | + | |
| 1098 | + | |
| 1099 | + | |
| 1100 | + | |
| 1101 | + | |
| 1102 | + | |
| 1103 | + | |
| 1104 | + | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
| 1108 | + | |
| 1109 | + | |
| 1110 | + | |
| 1111 | + | |
| 1112 | + | |
| 1113 | + | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
| 1124 | + | |
| 1125 | + | |
| 1126 | + | |
| 1127 | + | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
| 1131 | + | |
| 1132 | + | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | + | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
| 1142 | + | |
1047 | 1143 | | |
1048 | 1144 | | |
1049 | 1145 | | |
| |||
0 commit comments