Skip to main content

icydb_core/metrics/sink/
events.rs

1//! Module: metrics::sink::events
2//! Responsibility: stable instrumentation event taxonomy for metrics sinks.
3//! Does not own: global metrics state mutation or report rendering.
4//! Boundary: exposes event enums consumed by metrics sinks and runtime instrumentation.
5
6use crate::error::{ErrorClass, InternalError};
7
8///
9/// ExecKind
10///
11
12#[derive(Clone, Copy, Debug)]
13#[remain::sorted]
14pub enum ExecKind {
15    Delete,
16    Load,
17    Save,
18}
19
20///
21/// ExecOutcome
22///
23
24#[derive(Clone, Copy, Debug)]
25#[remain::sorted]
26pub enum ExecOutcome {
27    Aborted,
28    ErrorConflict,
29    ErrorCorruption,
30    ErrorIncompatiblePersistedFormat,
31    ErrorInternal,
32    ErrorInvariantViolation,
33    ErrorNotFound,
34    ErrorUnsupported,
35    Success,
36}
37
38///
39/// CacheKind
40///
41
42#[derive(Clone, Copy, Debug)]
43#[remain::sorted]
44pub enum CacheKind {
45    SharedQueryPlan,
46    SqlCompiledCommand,
47}
48
49///
50/// CacheOutcome
51///
52
53#[derive(Clone, Copy, Debug)]
54#[remain::sorted]
55pub enum CacheOutcome {
56    Hit,
57    Insert,
58    Miss,
59}
60
61///
62/// CacheMissReason
63///
64/// Stable cache miss reason buckets for cache identities that already have a
65/// scoped entity path. These categories explain why a lookup missed without
66/// exposing query text, field names, or schema hashes in the metrics report.
67///
68
69#[derive(Clone, Copy, Debug, Eq, PartialEq)]
70#[remain::sorted]
71pub enum CacheMissReason {
72    Cold,
73    DistinctKey,
74    MethodVersion,
75    SchemaFingerprint,
76    SchemaVersion,
77    Surface,
78    Visibility,
79}
80
81impl ExecOutcome {
82    // Map the crate's typed runtime error taxonomy into stable metrics buckets.
83    #[remain::check]
84    pub(super) const fn from_error(error: &InternalError) -> Self {
85        #[remain::sorted]
86        match error.class() {
87            ErrorClass::Conflict => Self::ErrorConflict,
88            ErrorClass::Corruption => Self::ErrorCorruption,
89            ErrorClass::IncompatiblePersistedFormat => Self::ErrorIncompatiblePersistedFormat,
90            ErrorClass::Internal => Self::ErrorInternal,
91            ErrorClass::InvariantViolation => Self::ErrorInvariantViolation,
92            ErrorClass::NotFound => Self::ErrorNotFound,
93            ErrorClass::Unsupported => Self::ErrorUnsupported,
94        }
95    }
96}
97
98///
99/// SaveMutationKind
100///
101
102#[derive(Clone, Copy, Debug)]
103#[remain::sorted]
104pub enum SaveMutationKind {
105    Insert,
106    Replace,
107    Update,
108}
109
110///
111/// MutationCommitClass
112///
113
114#[derive(Clone, Copy, Debug, Eq, PartialEq)]
115#[remain::sorted]
116pub enum MutationCommitClass {
117    DurableOnly,
118    LiveOnly,
119    MixedDurableAndLive,
120}
121
122///
123/// SchemaReconcileOutcome
124///
125/// Stable startup/metadata reconciliation outcomes for the schema trust
126/// boundary. The enum is intentionally low-cardinality so metrics can explain
127/// schema acceptance failures without exposing field names or diagnostic text.
128///
129
130#[derive(Clone, Copy, Debug, Eq, PartialEq)]
131#[remain::sorted]
132pub enum SchemaReconcileOutcome {
133    ExactMatch,
134    FirstCreate,
135    LatestSnapshotCorrupt,
136    RejectedFieldSlot,
137    RejectedOther,
138    RejectedRowLayout,
139    RejectedSchemaVersion,
140    StoreWriteError,
141}
142
143///
144/// SchemaTransitionOutcome
145///
146/// Stable schema transition policy buckets. These counters isolate the policy
147/// decision for an existing accepted snapshot from broader reconciliation
148/// outcomes such as first-create writes, corrupt stores, or store failures.
149///
150
151#[derive(Clone, Copy, Debug, Eq, PartialEq)]
152#[remain::sorted]
153pub enum SchemaTransitionOutcome {
154    AppendOnlyNullableFields,
155    ExactMatch,
156    RejectedEntityIdentity,
157    RejectedFieldContract,
158    RejectedFieldSlot,
159    RejectedRowLayout,
160    RejectedSchemaVersion,
161    RejectedSnapshot,
162}
163
164///
165/// SqlCompileRejectPhase
166///
167/// Stable SQL compile rejection buckets. These counters identify the broad
168/// admission phase that rejected a SQL command without exposing SQL text,
169/// parser diagnostics, field names, or lowered query details.
170///
171
172#[derive(Clone, Copy, Debug, Eq, PartialEq)]
173#[remain::sorted]
174pub enum SqlCompileRejectPhase {
175    CacheKey,
176    Parse,
177    Semantic,
178}
179
180///
181/// SqlWriteKind
182///
183
184#[derive(Clone, Copy, Debug, Eq, PartialEq)]
185#[remain::sorted]
186pub enum SqlWriteKind {
187    Delete,
188    Insert,
189    InsertSelect,
190    Update,
191}
192
193///
194/// PlanKind
195///
196
197#[derive(Clone, Copy, Debug)]
198#[remain::sorted]
199pub enum PlanKind {
200    ByKey,
201    ByKeys,
202    FullScan,
203    IndexMultiLookup,
204    IndexPrefix,
205    IndexRange,
206    Intersection,
207    KeyRange,
208    Union,
209}
210
211///
212/// PlanChoiceReason
213///
214/// Stable selected-route reason buckets for non-index and primary-key access
215/// choices. These counters explain why a query did not land on a secondary
216/// index route without exposing predicates, literals, or index names.
217///
218
219#[derive(Clone, Copy, Debug, Eq, PartialEq)]
220#[remain::sorted]
221pub enum PlanChoiceReason {
222    ConflictingPrimaryKeyChildrenAccessPreferred,
223    ConstantFalsePredicate,
224    EmptyChildAccessPreferred,
225    FullScanAccess,
226    IntentKeyAccessOverride,
227    LimitZeroWindow,
228    NonIndexAccess,
229    PlannerCompositeNonIndex,
230    PlannerFullScanFallback,
231    PlannerKeySetAccess,
232    PlannerPrimaryKeyLookup,
233    PlannerPrimaryKeyRange,
234    RequiredOrderPrimaryKeyRangePreferred,
235    SingletonPrimaryKeyChildAccessPreferred,
236}
237
238///
239/// PreparedShapeFinalizationOutcome
240///
241/// Stable executor authority outcome buckets for prepared static execution-planning contract
242/// finalization. These counters show whether executor lowering preserved an
243/// already-frozen schema-selected shape or applied the generated-model fallback.
244///
245
246#[derive(Clone, Copy, Debug, Eq, PartialEq)]
247#[remain::sorted]
248pub enum PreparedShapeFinalizationOutcome {
249    AlreadyFinalized,
250    GeneratedFallback,
251}
252
253///
254/// GroupedPlanExecutionMode
255///
256/// Canonical grouped-plan mode carried by metrics events.
257/// This keeps grouped metrics classification structured without routing
258/// through string codes that the sink would immediately decode again.
259///
260#[derive(Clone, Copy, Debug, Eq, PartialEq)]
261#[remain::sorted]
262pub enum GroupedPlanExecutionMode {
263    HashMaterialized,
264    OrderedMaterialized,
265}
266
267///
268/// MetricsEvent
269///
270
271#[derive(Clone, Copy, Debug)]
272#[remain::sorted]
273pub enum MetricsEvent {
274    AcceptedSchemaFootprint {
275        entity_path: &'static str,
276        fields: u64,
277        nested_leaf_facts: u64,
278    },
279    Cache {
280        entity_path: &'static str,
281        kind: CacheKind,
282        outcome: CacheOutcome,
283    },
284    CacheEntries {
285        kind: CacheKind,
286        entries: u64,
287    },
288    CacheMissReason {
289        entity_path: &'static str,
290        kind: CacheKind,
291        reason: CacheMissReason,
292    },
293    ExecError {
294        kind: ExecKind,
295        entity_path: &'static str,
296        outcome: ExecOutcome,
297    },
298    ExecFinish {
299        kind: ExecKind,
300        entity_path: &'static str,
301        rows_touched: u64,
302        inst_delta: u64,
303        outcome: ExecOutcome,
304    },
305    ExecStart {
306        kind: ExecKind,
307        entity_path: &'static str,
308    },
309    IndexDelta {
310        entity_path: &'static str,
311        inserts: u64,
312        removes: u64,
313    },
314    LoadRowEfficiency {
315        entity_path: &'static str,
316        candidate_rows_scanned: u64,
317        candidate_rows_filtered: u64,
318        result_rows_emitted: u64,
319    },
320    MutationCommitPlan {
321        entity_path: &'static str,
322        class: MutationCommitClass,
323    },
324    NonAtomicPartialCommit {
325        entity_path: &'static str,
326        committed_rows: u64,
327    },
328    Plan {
329        entity_path: &'static str,
330        kind: PlanKind,
331        grouped_execution_mode: Option<GroupedPlanExecutionMode>,
332    },
333    PlanChoice {
334        entity_path: &'static str,
335        reason: PlanChoiceReason,
336    },
337    PreparedShapeFinalization {
338        entity_path: &'static str,
339        outcome: PreparedShapeFinalizationOutcome,
340    },
341    RelationValidation {
342        entity_path: &'static str,
343        reverse_lookups: u64,
344        blocked_deletes: u64,
345    },
346    ReverseIndexDelta {
347        entity_path: &'static str,
348        inserts: u64,
349        removes: u64,
350    },
351    RowsAggregated {
352        entity_path: &'static str,
353        rows_aggregated: u64,
354    },
355    RowsEmitted {
356        entity_path: &'static str,
357        rows_emitted: u64,
358    },
359    RowsFiltered {
360        entity_path: &'static str,
361        rows_filtered: u64,
362    },
363    RowsScanned {
364        entity_path: &'static str,
365        rows_scanned: u64,
366    },
367    SaveMutation {
368        entity_path: &'static str,
369        kind: SaveMutationKind,
370        rows_touched: u64,
371    },
372    SchemaReconcile {
373        entity_path: &'static str,
374        outcome: SchemaReconcileOutcome,
375    },
376    SchemaStoreFootprint {
377        encoded_bytes: u64,
378        entity_path: &'static str,
379        latest_snapshot_bytes: u64,
380        snapshots: u64,
381    },
382    SchemaTransition {
383        entity_path: &'static str,
384        outcome: SchemaTransitionOutcome,
385    },
386    SqlCompileReject {
387        entity_path: &'static str,
388        phase: SqlCompileRejectPhase,
389    },
390    SqlWrite {
391        entity_path: &'static str,
392        kind: SqlWriteKind,
393        matched_rows: u64,
394        mutated_rows: u64,
395        returning_rows: u64,
396    },
397    SqlWriteError {
398        entity_path: &'static str,
399        kind: SqlWriteKind,
400        class: ErrorClass,
401    },
402    UniqueViolation {
403        entity_path: &'static str,
404    },
405}