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
50 lines
1.8 KiB
Rust
50 lines
1.8 KiB
Rust
use crate::metric_primitive::MetricPrimitive;
|
|
use crate::timestamp::Timestamp;
|
|
use serde::Serialize;
|
|
use std::collections::BTreeMap;
|
|
|
|
/// Key type for the engine's primary index.
|
|
///
|
|
/// Variants are ordered top to bottom as declared (derived `Ord` compares the
|
|
/// discriminant first), which is what carves the map into contiguous ranges:
|
|
/// logs, then params, then metric declarations, then buckets.
|
|
#[allow(dead_code)]
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)]
|
|
pub enum IndexKey {
|
|
/// Marker for the start of the whole range. Never inserted, only navigated to.
|
|
Start,
|
|
IngestedLog {
|
|
sequence: u64,
|
|
timestamp: Timestamp,
|
|
},
|
|
/// Marker between the log range and the param range.
|
|
LogParamSplit,
|
|
ParamDeclaration {
|
|
name: String,
|
|
},
|
|
/// Marker between the param range and the metric declaration range.
|
|
ParamMetricSplit,
|
|
MetricDeclaration {
|
|
name: String,
|
|
},
|
|
/// Marker between metric declarations and their buckets.
|
|
MetricBucketSplit,
|
|
Bucket {
|
|
metric_name: String,
|
|
labels: BTreeMap<String, MetricPrimitive>,
|
|
},
|
|
/// Ticket 023: internal bookkeeping (never returned by a query) tracking
|
|
/// the timestamp of the most recent counter event for one metric+label
|
|
/// combination, independent of whether that event actually pushed a
|
|
/// `Bucket` value — a `Duration`-kind `Value` param's *first* occurrence
|
|
/// of a label set has no previous event to diff against and pushes no
|
|
/// `Bucket` entry, but must still be recorded here so the *next*
|
|
/// occurrence can compute its elapsed time.
|
|
LastMetricEvent {
|
|
metric_name: String,
|
|
labels: BTreeMap<String, MetricPrimitive>,
|
|
},
|
|
/// Marker for the end of the whole range. Nothing sorts after this.
|
|
End,
|
|
}
|