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    IndexBranchSet,
204    IndexMultiLookup,
205    IndexPrefix,
206    IndexRange,
207    Intersection,
208    KeyRange,
209    Union,
210}
211
212///
213/// PlanChoiceReason
214///
215/// Stable selected-route reason buckets for non-index and primary-key access
216/// choices. These counters explain why a query did not land on a secondary
217/// index route without exposing predicates, literals, or index names.
218///
219
220#[derive(Clone, Copy, Debug, Eq, PartialEq)]
221#[remain::sorted]
222pub enum PlanChoiceReason {
223    ConflictingPrimaryKeyChildrenAccessPreferred,
224    ConstantFalsePredicate,
225    EmptyChildAccessPreferred,
226    FullScanAccess,
227    IntentKeyAccessOverride,
228    LimitZeroWindow,
229    NonIndexAccess,
230    PlannerCompositeNonIndex,
231    PlannerFullScanFallback,
232    PlannerKeySetAccess,
233    PlannerPrimaryKeyLookup,
234    PlannerPrimaryKeyRange,
235    RequiredOrderPrimaryKeyRangePreferred,
236    SingletonPrimaryKeyChildAccessPreferred,
237}
238
239///
240/// PreparedShapeFinalizationOutcome
241///
242/// Stable executor authority outcome buckets for prepared static execution-planning contract
243/// finalization. These counters show whether executor lowering preserved an
244/// already-frozen schema-selected shape or applied the generated-model fallback.
245///
246
247#[derive(Clone, Copy, Debug, Eq, PartialEq)]
248#[remain::sorted]
249pub enum PreparedShapeFinalizationOutcome {
250    AlreadyFinalized,
251    GeneratedFallback,
252}
253
254///
255/// GroupedPlanExecutionMode
256///
257/// Canonical grouped-plan mode carried by metrics events.
258/// This keeps grouped metrics classification structured without routing
259/// through string codes that the sink would immediately decode again.
260///
261#[derive(Clone, Copy, Debug, Eq, PartialEq)]
262#[remain::sorted]
263pub enum GroupedPlanExecutionMode {
264    HashMaterialized,
265    OrderedMaterialized,
266}
267
268///
269/// MetricsEvent
270///
271
272#[derive(Clone, Copy, Debug)]
273#[remain::sorted]
274pub enum MetricsEvent {
275    AcceptedSchemaFootprint {
276        entity_path: &'static str,
277        fields: u64,
278        nested_leaf_facts: u64,
279    },
280    Cache {
281        entity_path: &'static str,
282        kind: CacheKind,
283        outcome: CacheOutcome,
284    },
285    CacheEntries {
286        kind: CacheKind,
287        entries: u64,
288    },
289    CacheMissReason {
290        entity_path: &'static str,
291        kind: CacheKind,
292        reason: CacheMissReason,
293    },
294    ExecError {
295        kind: ExecKind,
296        entity_path: &'static str,
297        outcome: ExecOutcome,
298    },
299    ExecFinish {
300        kind: ExecKind,
301        entity_path: &'static str,
302        rows_touched: u64,
303        inst_delta: u64,
304        outcome: ExecOutcome,
305    },
306    ExecStart {
307        kind: ExecKind,
308        entity_path: &'static str,
309    },
310    IndexDelta {
311        entity_path: &'static str,
312        inserts: u64,
313        removes: u64,
314    },
315    LoadRowEfficiency {
316        entity_path: &'static str,
317        candidate_rows_scanned: u64,
318        candidate_rows_filtered: u64,
319        result_rows_emitted: u64,
320    },
321    MutationCommitPlan {
322        entity_path: &'static str,
323        class: MutationCommitClass,
324    },
325    NonAtomicPartialCommit {
326        entity_path: &'static str,
327        committed_rows: u64,
328    },
329    Plan {
330        entity_path: &'static str,
331        kind: PlanKind,
332        grouped_execution_mode: Option<GroupedPlanExecutionMode>,
333    },
334    PlanChoice {
335        entity_path: &'static str,
336        reason: PlanChoiceReason,
337    },
338    PreparedShapeFinalization {
339        entity_path: &'static str,
340        outcome: PreparedShapeFinalizationOutcome,
341    },
342    RelationValidation {
343        entity_path: &'static str,
344        reverse_lookups: u64,
345        blocked_deletes: u64,
346    },
347    ReverseIndexDelta {
348        entity_path: &'static str,
349        inserts: u64,
350        removes: u64,
351    },
352    RowsAggregated {
353        entity_path: &'static str,
354        rows_aggregated: u64,
355    },
356    RowsEmitted {
357        entity_path: &'static str,
358        rows_emitted: u64,
359    },
360    RowsFiltered {
361        entity_path: &'static str,
362        rows_filtered: u64,
363    },
364    RowsScanned {
365        entity_path: &'static str,
366        rows_scanned: u64,
367    },
368    SaveMutation {
369        entity_path: &'static str,
370        kind: SaveMutationKind,
371        rows_touched: u64,
372    },
373    SchemaReconcile {
374        entity_path: &'static str,
375        outcome: SchemaReconcileOutcome,
376    },
377    SchemaStoreFootprint {
378        encoded_bytes: u64,
379        entity_path: &'static str,
380        latest_snapshot_bytes: u64,
381        snapshots: u64,
382    },
383    SchemaTransition {
384        entity_path: &'static str,
385        outcome: SchemaTransitionOutcome,
386    },
387    SqlCompileReject {
388        entity_path: &'static str,
389        phase: SqlCompileRejectPhase,
390    },
391    SqlWrite {
392        entity_path: &'static str,
393        kind: SqlWriteKind,
394        staged_rows: u64,
395        matched_rows: u64,
396        mutated_rows: u64,
397        returning_rows: u64,
398    },
399    SqlWriteError {
400        entity_path: &'static str,
401        kind: SqlWriteKind,
402        class: ErrorClass,
403    },
404    UniqueViolation {
405        entity_path: &'static str,
406    },
407}