Add Duration-type metric param: elapsed time since previous same-label match (ticket 023)
MetricPrimitiveKind::Duration/MetricPrimitive::Duration(i64 ms) is a new primitive kind. On a metric's Value-role param (ticket 022), kind Duration is special-cased in apply_metric_to_log: instead of parsing the captured text, the value is derived as elapsed time since the previous counter event with the same label set, using the ingestion timestamp. That "previous event" lookup is tracked via a new IndexKey::LastMetricEvent/DataValue::LastEventTimestamp bookkeeping entry rather than Bucket.values itself, because a label set's first occurrence has nothing to diff against and pushes no Bucket entry at all (per spec: omit, don't emit a bogus zero) — but it still needs to be recorded so the *next* occurrence has something to diff against. Duration values compose with the existing bucket/PromQL surface unchanged (coerce_to_f64, filter comparisons, histogram()/gauge()). On any other param (Label-role metric param, or a standalone ParamDeclaration), Duration kind instead parses captured text as a literal i64 millisecond count, same as Number. Profile round-trip (ProfileMetricPrimitiveKind) and the Metrics.tsx declaration form are updated to match. 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
0c57ed2953
commit
8faf12f819
@@ -213,12 +213,13 @@ export function Metrics({ range }: { range: TimeRange | null }) {
|
||||
<option value="string">string</option>
|
||||
<option value="number">number</option>
|
||||
<option value="timestamp">timestamp</option>
|
||||
<option value="duration">duration</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())"
|
||||
title="Label params identify a bucket; at most one Value param becomes the counter's per-event captured value (used by histogram()/gauge()). A Value param of kind 'duration' is derived automatically — elapsed time since the previous match with the same labels — rather than parsed from the capture group."
|
||||
>
|
||||
<option value="label">label</option>
|
||||
<option value="value">value</option>
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
/// `MetricPrimitive` is a Rust enum with derived `Serialize`, so its JSON
|
||||
/// form is externally tagged, e.g. `{ "String": "info" }`, `{ "Number":
|
||||
/// { "Int": 5 } }`, `{ "Timestamp": 1710000000000 }`.
|
||||
/// { "Int": 5 } }`, `{ "Timestamp": 1710000000000 }`, `{ "Duration": 1500 }`
|
||||
/// (milliseconds, ticket 023).
|
||||
export type MetricPrimitive =
|
||||
| { String: string }
|
||||
| { Number: { Int: number } | { Float: number } }
|
||||
| { Timestamp: number }
|
||||
| { Duration: number }
|
||||
|
||||
export function metricPrimitiveToDisplayString(value: MetricPrimitive): string {
|
||||
if ('String' in value) return value.String
|
||||
if ('Timestamp' in value) return String(value.Timestamp)
|
||||
if ('Duration' in value) return `${value.Duration}ms`
|
||||
if ('Int' in value.Number) return String(value.Number.Int)
|
||||
return String(value.Number.Float)
|
||||
}
|
||||
@@ -27,7 +30,7 @@ export interface ParamDeclaration {
|
||||
name: string
|
||||
message_match_regex: string
|
||||
capture_group: string
|
||||
kind: 'string' | 'number' | 'timestamp'
|
||||
kind: 'string' | 'number' | 'timestamp' | 'duration'
|
||||
}
|
||||
|
||||
export interface TimelineBucket {
|
||||
@@ -49,7 +52,7 @@ export type ParamRole = 'label' | 'value'
|
||||
export interface MetricParamMatcher {
|
||||
param_name: string
|
||||
capture_group: string
|
||||
kind: 'string' | 'number' | 'timestamp'
|
||||
kind: 'string' | 'number' | 'timestamp' | 'duration'
|
||||
/** Defaults to 'label' server-side when omitted. */
|
||||
role?: ParamRole
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user