A plain numeric sample. The shape every number here takes.
| Field | Value |
|---|---|
| Name | measurement |
| Severity | 9 (INFO) |
| Written by | Nothing. You write it. |
Whenever you have a number worth keeping: a queue depth, a resident set size, how long an export took, how many rows somebody selected.
A metric is not a different kind of thing here. There is no metrics table, no counter, no gauge and no histogram: a sample is one row with a name, a severity and an attribute map, exactly like a page view and exactly like a crash. That is the whole reason the query layer needs no special case for numbers, and why web_vital is these same three attributes under a name of its own.
Send one sample per row rather than pre-aggregating. The percentile and the average are read-time questions, and a client that averaged for you would have thrown away the only thing that could answer them differently later.
| Attribute | Type | What it holds |
|---|---|---|
| firstrun.metric | string | What the sample is called: queue_depth, rss_bytes, export_rows. This is what a breakdown groups on. |
| firstrun.value | number | The sample itself. A number, so it is averaged without a cast over every row. |
| firstrun.unit | string | The unit, when it is not obvious from the name: ms, bytes, rows. |
Every entry also carries the resource its client sends once per batch: session.id, user.id once you have called user(), and the rest of the list on the overview. Anything you pass yourself lands in the same map, and your key wins on a collision.
Nothing is derived from it. No entry is computed from another entry anywhere in this product, so there is no rollup table quietly filling in behind this one and no minute a sample is missing from because a job did not run.
A widget is a filter, a group by, an aggregate, a time bucket and a limit. These are those five parts written out, and every one of them is something you can build yourself.
| Question | The query |
|---|---|
| One metric over time | Name is measurement . firstrun.metric is queue_depth . average of firstrun.value . bucket by hour |
| The worst case | Name is measurement . firstrun.metric is queue_depth . maximum of firstrun.value . bucket by hour |
| The tail rather than the mean | Name is measurement . firstrun.metric is export_ms . 95th percentile of firstrun.value |
| Every metric side by side | Name is measurement . group by firstrun.metric . average of firstrun.value |