Interface status: target public API. OTLP decoding, SID resolution, and summary handling exist; complete catalog and execution-plan validation is partial.
OTLP request
|
v
SummaryDecoder -> SeriesIdentityResolver -> SummaryValidator
|
v
SummaryStateApplier
|
v
SummaryStore
Transport decoding is separate from semantic validation. No decoder is allowed to append directly to storage or choose a summary family.
pub trait SummaryDecoder {
type Error;
fn decode(&self, request: OtlpMetricsRequest)
-> Result<Vec<ReceivedSummary>, Self::Error>;
}
pub struct ReceivedSummary {
pub tenant: String,
pub resource: AttributeSet,
pub scope: InstrumentationScope,
pub metric_name: String,
pub attributes: AttributeSet,
pub source_timestamp: Timestamp,
pub envelope: SummaryEnvelope,
}SummaryEnvelope contains plan/materialization/producer/window identity,
family/parameters/encoding, full-or-delta metadata, and payload bytes. Required
identity cannot be inferred from metric-name suffixes.
pub struct SummaryEnvelope {
pub plan_id: String,
pub plan_version: u64,
pub materialization_id: String,
pub producer_id: String,
pub window: LogicalWindow,
pub family: SummaryFamily,
pub algorithm: SummaryAlgorithm,
pub parameters: SummaryParameters,
pub encoding: SummaryEncoding,
pub frame: SummaryFrame,
pub payload: Bytes,
}
pub enum SummaryFrame {
Full { checkpoint_id: String },
Delta {
base_checkpoint_id: String,
sequence: u64,
},
}pub trait SeriesIdentityResolver {
type Error;
fn resolve(&self, key: CanonicalMaterializedSeriesKey)
-> Result<ResolvedSeries, Self::Error>;
}SeriesId, SeriesIdNamespace, CanonicalMaterializedSeriesKey, and ResolvedSeries have
one public definition in
Summary storage and series identity.
pub trait SummaryValidator {
type Error;
fn validate(
&self,
received: ReceivedSummary,
catalog: &SummaryCatalog,
precompute: &PrecomputePlan,
transmission: &TransmissionPlan,
series: ResolvedSeries,
) -> Result<ValidatedSummary, Self::Error>;
}
pub trait SummaryStateApplier {
type Error;
fn apply(&self, summary: ValidatedSummary)
-> Result<IngestResult, Self::Error>;
}
pub struct ValidatedSummary {
pub received: ReceivedSummary,
pub series: ResolvedSeries,
pub materialization: ValidatedMaterialization,
}
pub struct ValidatedMaterialization {
pub plan_id: String,
pub plan_version: u64,
pub materialization_id: String,
pub compatibility_fingerprint: String,
}
pub struct IngestResult {
pub disposition: IngestDisposition,
pub plan_id: String,
pub materialization_id: String,
pub series_id: SeriesId,
pub window: LogicalWindow,
pub queryable_at: Option<Timestamp>,
}
pub enum IngestDisposition {
AppliedFull,
AppliedDelta,
Duplicate,
Rejected,
AwaitingCheckpoint,
}Supporting type definitions:
| Type | Definition |
|---|---|
OtlpMetricsRequest |
Decoded public OTLP ExportMetricsServiceRequest. |
AttributeSet |
Canonically typed OTel attributes with no identity-relevant loss. |
InstrumentationScope |
OTel scope name/version/schema identifying the producer library. |
LogicalWindow |
Start/end plus window identity used by plan, state, and query coverage. |
SummaryEncoding |
Versioned state representation shared by collector/backend capabilities. |
Why these interfaces exist: each stage can reject invalid data without changing
queryable state, and IngestResult gives the MVP harness unambiguous evidence.
- Extend public
SummaryEnvelopeencoding/version definitions. - Implement
SummaryDecoderwithout applying state. - Add compatibility validation against SummaryCatalog, PrecomputePlan, TransmissionPlan, and producer capabilities.
- Implement full/delta application through
SummaryStateApplier. - Verify corrupt bytes return an error and do not change storage.
Define base/checkpoint, sequence scope, duplicate handling, gap behavior, and
recovery full state. Verify AppliedDelta, Duplicate, and
AwaitingCheckpoint are distinguishable outputs for reorder/gap tests.
Add canonical input fields to CanonicalMaterializedSeriesKey, never to SeriesId.value
alone. Verify label-order independence, tenant isolation, cached-ID conflict
recovery, and stable namespace reporting.
Applied*means compatible state was committed.Duplicatemeans idempotent replay with no second mutation.AwaitingCheckpointmeans a visible delta gap and non-queryable state.queryable_atis populated only when coverage/readiness is satisfied.- Freshness uses
source_timestamp -> queryable_at, not receive time.