Metrics rethink: counters as the primitive, histogram()/gauge() derived (ticket 022)
Every metric declaration is now explicitly documented and modeled as
a counter: a match is an occurrence/increment, optionally labeled.
The bucket representation (BucketValue { values: Vec<(Sequence,
Timestamp, MetricPrimitive)> }) already was this; what it lacked was
any way to capture a *value* distinct from the occurrence-count-of-1
marker. Adds RegexToMetricPrimitiveMatcher::role (ParamRole::Label,
the default, or ParamRole::Value — at most one per metric, enforced
at declare time) so a metric can designate one param's captured
number as its per-event value instead of a label.
promql.rs/engine.rs add two new PromQL-evaluable forms built on top
of that value, both consumed as regular PromqlSeriesDto series like
sum()/avg()/rate():
- histogram(metric_name[width]): buckets matching events' values into
fixed-width buckets, one series per bucket labeled `le`.
- gauge(metric_name): the most-recent value per label combination in
the queried range.
Existing raw counter queries (metrics with only Label-role params,
sum/avg/rate) are unchanged. Profile files saved before this ticket
still load (role defaults to Label via #[serde(default)]). Metrics.tsx
gains a label/value role picker per param, and the Docs panel explains
the model and the two derived query forms.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XFUNZwCvz3kcod3352ZR2o
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
1d0f324c43
commit
0c57ed2953
@@ -128,9 +128,17 @@ const SECTIONS: DocSection[] = [
|
||||
body: (
|
||||
<div className="flex flex-col gap-2">
|
||||
<p>
|
||||
A metric declaration bundles a message-match regex with one or more named param matchers (each with its own
|
||||
capture group and type). Every log line matching the regex produces a <em>bucket value</em>: a timestamped
|
||||
occurrence, tagged with the labels captured from that line.
|
||||
Every metric is fundamentally a <em>counter</em>: a message-match regex paired with one or more named param
|
||||
matchers (each with its own capture group and type). Every log line matching the regex is one counter
|
||||
increment — a timestamped occurrence, tagged with the labels captured from that line.
|
||||
</p>
|
||||
<p>
|
||||
Each param is either a <strong>label</strong> (the default) or the metric's single <strong>value</strong>{' '}
|
||||
param. Label params identify which bucket an occurrence belongs to; a value param's captured number becomes
|
||||
that occurrence's stored value instead of a label — e.g. a <Code>duration</Code> param marked{' '}
|
||||
<em>value</em> lets you query the distribution or latest reading of durations, not just how often they
|
||||
occurred. A metric with only label params still works exactly as before: every occurrence's value defaults
|
||||
to a fixed <Code>1</Code> (a pure occurrence count).
|
||||
</p>
|
||||
<p>
|
||||
Declaring a metric backfills it against everything already ingested, then continues indexing new lines as
|
||||
@@ -139,8 +147,25 @@ const SECTIONS: DocSection[] = [
|
||||
<p>
|
||||
The Metrics panel lets you declare a metric, pick one from the declared list, and see its bucket values
|
||||
grouped by label combination over the active time range — occurrence count per group, plus a small trend
|
||||
sparkline. That same data is what dashboard panels query via PromQL (see below).
|
||||
sparkline. That same data is what dashboard panels query via PromQL (see below), including two forms{' '}
|
||||
<em>derived</em> from a counter's value param rather than stored separately:
|
||||
</p>
|
||||
<ul className="list-disc pl-5">
|
||||
<li>
|
||||
<span className="font-semibold text-text">
|
||||
<Code>histogram(metric_name[width])</Code>
|
||||
</span>{' '}
|
||||
— buckets every matching event's value into fixed-width buckets of size <Code>width</Code>, e.g.{' '}
|
||||
<Code>histogram(durations[10])</Code>.
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-semibold text-text">
|
||||
<Code>gauge(metric_name)</Code>
|
||||
</span>{' '}
|
||||
— the most-recent value per label combination in the active range, i.e. the counter collapsed to its
|
||||
latest reading.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -214,6 +214,15 @@ export function Metrics({ range }: { range: TimeRange | null }) {
|
||||
<option value="number">number</option>
|
||||
<option value="timestamp">timestamp</option>
|
||||
</select>
|
||||
<select
|
||||
className="rounded border border-border-soft bg-surface-1 px-1 py-1 text-xs text-text focus:border-border-strong focus:outline-none"
|
||||
value={matcher.role ?? 'label'}
|
||||
onChange={(e) => updateMatcher(i, { role: e.target.value as MetricParamMatcher['role'] })}
|
||||
title="Label params identify a bucket; at most one Value param becomes the counter's per-event captured value (used by histogram()/gauge())"
|
||||
>
|
||||
<option value="label">label</option>
|
||||
<option value="value">value</option>
|
||||
</select>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => removeMatcher(i)}
|
||||
|
||||
Reference in New Issue
Block a user