Skip to main content

icydb_core/metrics/state/
ops.rs

1//! Module: metrics::state::ops
2//! Responsibility: global operation metrics DTO and derived-ratio helpers.
3//! Does not own: mutable metrics state storage or report window construction.
4//! Boundary: keeps public operation counter payload shape separate from state.
5
6use candid::CandidType;
7use serde::Deserialize;
8
9///
10/// MetricRatio
11///
12/// MetricRatio carries a derived metric as an exact raw numerator and
13/// denominator pair. Callers can choose their own decimal rendering policy
14/// without losing precision inside the canister metrics layer.
15///
16#[derive(Clone, Copy, Debug, Eq, PartialEq)]
17pub struct MetricRatio {
18    numerator: u64,
19    denominator: u64,
20}
21
22impl MetricRatio {
23    /// Returns the ratio numerator.
24    #[must_use]
25    pub const fn numerator(&self) -> u64 {
26        self.numerator
27    }
28
29    /// Returns the ratio denominator.
30    #[must_use]
31    pub const fn denominator(&self) -> u64 {
32        self.denominator
33    }
34
35    /// Returns the raw numerator and denominator pair.
36    #[must_use]
37    pub const fn into_numerator_and_denominator(self) -> (u64, u64) {
38        (self.numerator, self.denominator)
39    }
40}
41
42// Convert raw counter pairs into optional ratio values without encoding a
43// sentinel for "no activity". Consumers can distinguish absent denominators
44// from legitimate zero-valued work.
45pub(in crate::metrics) const fn ratio(numerator: u64, denominator: u64) -> Option<MetricRatio> {
46    if denominator == 0 {
47        return None;
48    }
49
50    Some(MetricRatio {
51        numerator,
52        denominator,
53    })
54}
55
56#[cfg_attr(doc, doc = "EventOps\n\nOperation counters.")]
57#[derive(CandidType, Clone, Debug, Default, Deserialize)]
58pub struct EventOps {
59    // Executor entrypoints
60    pub(crate) load_calls: u64,
61    pub(crate) save_calls: u64,
62    pub(crate) delete_calls: u64,
63    pub(crate) save_insert_calls: u64,
64    pub(crate) save_update_calls: u64,
65    pub(crate) save_replace_calls: u64,
66    pub(crate) exec_success: u64,
67    pub(crate) exec_error_corruption: u64,
68    pub(crate) exec_error_incompatible_persisted_format: u64,
69    pub(crate) exec_error_not_found: u64,
70    pub(crate) exec_error_internal: u64,
71    pub(crate) exec_error_conflict: u64,
72    pub(crate) exec_error_unsupported: u64,
73    pub(crate) exec_error_invariant_violation: u64,
74    pub(crate) exec_aborted: u64,
75    pub(crate) cache_shared_query_plan_hits: u64,
76    pub(crate) cache_shared_query_plan_misses: u64,
77    pub(crate) cache_shared_query_plan_inserts: u64,
78    pub(crate) cache_shared_query_plan_entries: u64,
79    pub(crate) cache_shared_query_plan_miss_cold: u64,
80    pub(crate) cache_shared_query_plan_miss_distinct_key: u64,
81    pub(crate) cache_shared_query_plan_miss_schema_fingerprint: u64,
82    pub(crate) cache_shared_query_plan_miss_visibility: u64,
83    pub(crate) cache_sql_compiled_command_hits: u64,
84    pub(crate) cache_sql_compiled_command_misses: u64,
85    pub(crate) cache_sql_compiled_command_inserts: u64,
86    pub(crate) cache_sql_compiled_command_entries: u64,
87    pub(crate) cache_sql_compiled_command_miss_cold: u64,
88    pub(crate) cache_sql_compiled_command_miss_distinct_key: u64,
89    pub(crate) cache_sql_compiled_command_miss_schema_fingerprint: u64,
90    pub(crate) cache_sql_compiled_command_miss_surface: u64,
91    pub(crate) schema_reconcile_checks: u64,
92    pub(crate) schema_reconcile_exact_match: u64,
93    pub(crate) schema_reconcile_first_create: u64,
94    pub(crate) schema_reconcile_latest_snapshot_corrupt: u64,
95    pub(crate) schema_reconcile_rejected_field_slot: u64,
96    pub(crate) schema_reconcile_rejected_other: u64,
97    pub(crate) schema_reconcile_rejected_row_layout: u64,
98    pub(crate) schema_reconcile_rejected_schema_version: u64,
99    pub(crate) schema_reconcile_store_write_error: u64,
100    pub(crate) schema_transition_checks: u64,
101    pub(crate) schema_transition_add_expression_index: u64,
102    pub(crate) schema_transition_add_field_path_index: u64,
103    pub(crate) schema_transition_append_only_fields: u64,
104    pub(crate) schema_transition_constraint_activation: u64,
105    pub(crate) schema_transition_exact_match: u64,
106    pub(crate) schema_transition_metadata_only_field_default: u64,
107    pub(crate) schema_transition_metadata_only_index_rename: u64,
108    pub(crate) schema_transition_rejected_entity_identity: u64,
109    pub(crate) schema_transition_rejected_field_contract: u64,
110    pub(crate) schema_transition_rejected_field_slot: u64,
111    pub(crate) schema_transition_rejected_row_layout: u64,
112    pub(crate) schema_transition_rejected_schema_version: u64,
113    pub(crate) schema_transition_rejected_snapshot: u64,
114    pub(crate) schema_store_snapshots: u64,
115    pub(crate) schema_store_encoded_bytes: u64,
116    pub(crate) schema_store_latest_snapshot_bytes: u64,
117    pub(crate) accepted_schema_fields: u64,
118    pub(crate) accepted_schema_nested_leaf_facts: u64,
119    pub(crate) sql_compile_rejects: u64,
120    pub(crate) sql_compile_reject_cache_key: u64,
121    pub(crate) sql_compile_reject_parse: u64,
122    pub(crate) sql_compile_reject_semantic: u64,
123
124    // Planner kinds
125    pub(crate) plan_by_key: u64,
126    pub(crate) plan_by_keys: u64,
127    pub(crate) plan_key_range: u64,
128    pub(crate) plan_index_branch_set: u64,
129    pub(crate) plan_index_prefix: u64,
130    pub(crate) plan_index_multi_lookup: u64,
131    pub(crate) plan_index_range: u64,
132    pub(crate) plan_explicit_full_scan: u64,
133    pub(crate) plan_union: u64,
134    pub(crate) plan_intersection: u64,
135    pub(crate) plan_grouped_hash_materialized: u64,
136    pub(crate) plan_grouped_ordered_streaming: u64,
137    pub(crate) plan_choice_conflicting_primary_key_children_access_preferred: u64,
138    pub(crate) plan_choice_constant_false_predicate: u64,
139    pub(crate) plan_choice_empty_child_access_preferred: u64,
140    pub(crate) plan_choice_full_scan_access: u64,
141    pub(crate) plan_choice_intent_key_access_override: u64,
142    pub(crate) plan_choice_limit_zero_window: u64,
143    pub(crate) plan_choice_non_index_access: u64,
144    pub(crate) plan_choice_planner_composite_non_index: u64,
145    pub(crate) plan_choice_planner_full_scan_fallback: u64,
146    pub(crate) plan_choice_planner_key_set_access: u64,
147    pub(crate) plan_choice_planner_primary_key_lookup: u64,
148    pub(crate) plan_choice_planner_primary_key_range: u64,
149    pub(crate) plan_choice_required_order_primary_key_range_preferred: u64,
150    pub(crate) plan_choice_singleton_primary_key_child_access_preferred: u64,
151    pub(crate) prepared_shape_already_finalized: u64,
152
153    // Rows touched
154    pub(crate) rows_loaded: u64,
155    pub(crate) rows_saved: u64,
156    pub(crate) rows_inserted: u64,
157    pub(crate) rows_updated: u64,
158    pub(crate) rows_replaced: u64,
159    pub(crate) rows_scanned: u64,
160    pub(crate) rows_filtered: u64,
161    pub(crate) rows_aggregated: u64,
162    pub(crate) rows_emitted: u64,
163    pub(crate) load_candidate_rows_scanned: u64,
164    pub(crate) load_candidate_rows_filtered: u64,
165    pub(crate) load_result_rows_emitted: u64,
166    pub(crate) rows_deleted: u64,
167    pub(crate) sql_insert_calls: u64,
168    pub(crate) sql_insert_select_calls: u64,
169    pub(crate) sql_update_calls: u64,
170    pub(crate) sql_delete_calls: u64,
171    pub(crate) sql_write_staged_rows: u64,
172    pub(crate) sql_write_matched_rows: u64,
173    pub(crate) sql_write_mutated_rows: u64,
174    pub(crate) sql_write_returning_rows: u64,
175    pub(crate) sql_write_error_insert: u64,
176    pub(crate) sql_write_error_insert_select: u64,
177    pub(crate) sql_write_error_update: u64,
178    pub(crate) sql_write_error_delete: u64,
179    pub(crate) sql_write_error_corruption: u64,
180    pub(crate) sql_write_error_incompatible_persisted_format: u64,
181    pub(crate) sql_write_error_not_found: u64,
182    pub(crate) sql_write_error_internal: u64,
183    pub(crate) sql_write_error_conflict: u64,
184    pub(crate) sql_write_error_unsupported: u64,
185    pub(crate) sql_write_error_invariant_violation: u64,
186
187    // Index maintenance
188    pub(crate) index_inserts: u64,
189    pub(crate) index_removes: u64,
190    pub(crate) reverse_index_inserts: u64,
191    pub(crate) reverse_index_removes: u64,
192    pub(crate) relation_reverse_lookups: u64,
193    pub(crate) relation_delete_blocks: u64,
194    pub(crate) write_rows_touched: u64,
195    pub(crate) write_index_entries_changed: u64,
196    pub(crate) write_reverse_index_entries_changed: u64,
197    pub(crate) write_relation_checks: u64,
198    pub(crate) unique_violations: u64,
199    pub(crate) non_atomic_partial_commits: u64,
200    pub(crate) non_atomic_partial_rows_committed: u64,
201}
202
203impl EventOps {
204    #[must_use]
205    pub const fn load_calls(&self) -> u64 {
206        self.load_calls
207    }
208
209    #[must_use]
210    pub const fn save_calls(&self) -> u64 {
211        self.save_calls
212    }
213
214    #[must_use]
215    pub const fn delete_calls(&self) -> u64 {
216        self.delete_calls
217    }
218
219    #[must_use]
220    pub const fn save_insert_calls(&self) -> u64 {
221        self.save_insert_calls
222    }
223
224    #[must_use]
225    pub const fn save_update_calls(&self) -> u64 {
226        self.save_update_calls
227    }
228
229    #[must_use]
230    pub const fn save_replace_calls(&self) -> u64 {
231        self.save_replace_calls
232    }
233
234    #[must_use]
235    pub const fn exec_success(&self) -> u64 {
236        self.exec_success
237    }
238
239    #[must_use]
240    pub const fn exec_error_corruption(&self) -> u64 {
241        self.exec_error_corruption
242    }
243
244    #[must_use]
245    pub const fn exec_error_incompatible_persisted_format(&self) -> u64 {
246        self.exec_error_incompatible_persisted_format
247    }
248
249    #[must_use]
250    pub const fn exec_error_not_found(&self) -> u64 {
251        self.exec_error_not_found
252    }
253
254    #[must_use]
255    pub const fn exec_error_internal(&self) -> u64 {
256        self.exec_error_internal
257    }
258
259    #[must_use]
260    pub const fn exec_error_conflict(&self) -> u64 {
261        self.exec_error_conflict
262    }
263
264    #[must_use]
265    pub const fn exec_error_unsupported(&self) -> u64 {
266        self.exec_error_unsupported
267    }
268
269    #[must_use]
270    pub const fn exec_error_invariant_violation(&self) -> u64 {
271        self.exec_error_invariant_violation
272    }
273
274    #[must_use]
275    pub const fn exec_aborted(&self) -> u64 {
276        self.exec_aborted
277    }
278
279    #[must_use]
280    pub const fn cache_shared_query_plan_hits(&self) -> u64 {
281        self.cache_shared_query_plan_hits
282    }
283
284    #[must_use]
285    pub const fn cache_shared_query_plan_misses(&self) -> u64 {
286        self.cache_shared_query_plan_misses
287    }
288
289    #[must_use]
290    pub const fn cache_shared_query_plan_inserts(&self) -> u64 {
291        self.cache_shared_query_plan_inserts
292    }
293
294    #[must_use]
295    pub const fn cache_shared_query_plan_entries(&self) -> u64 {
296        self.cache_shared_query_plan_entries
297    }
298
299    #[must_use]
300    pub const fn cache_shared_query_plan_miss_cold(&self) -> u64 {
301        self.cache_shared_query_plan_miss_cold
302    }
303
304    #[must_use]
305    pub const fn cache_shared_query_plan_miss_distinct_key(&self) -> u64 {
306        self.cache_shared_query_plan_miss_distinct_key
307    }
308
309    #[must_use]
310    pub const fn cache_shared_query_plan_miss_schema_fingerprint(&self) -> u64 {
311        self.cache_shared_query_plan_miss_schema_fingerprint
312    }
313
314    #[must_use]
315    pub const fn cache_shared_query_plan_miss_visibility(&self) -> u64 {
316        self.cache_shared_query_plan_miss_visibility
317    }
318
319    #[must_use]
320    pub const fn cache_sql_compiled_command_hits(&self) -> u64 {
321        self.cache_sql_compiled_command_hits
322    }
323
324    #[must_use]
325    pub const fn cache_sql_compiled_command_misses(&self) -> u64 {
326        self.cache_sql_compiled_command_misses
327    }
328
329    #[must_use]
330    pub const fn cache_sql_compiled_command_inserts(&self) -> u64 {
331        self.cache_sql_compiled_command_inserts
332    }
333
334    #[must_use]
335    pub const fn cache_sql_compiled_command_entries(&self) -> u64 {
336        self.cache_sql_compiled_command_entries
337    }
338
339    #[must_use]
340    pub const fn cache_sql_compiled_command_miss_cold(&self) -> u64 {
341        self.cache_sql_compiled_command_miss_cold
342    }
343
344    #[must_use]
345    pub const fn cache_sql_compiled_command_miss_distinct_key(&self) -> u64 {
346        self.cache_sql_compiled_command_miss_distinct_key
347    }
348
349    #[must_use]
350    pub const fn cache_sql_compiled_command_miss_schema_fingerprint(&self) -> u64 {
351        self.cache_sql_compiled_command_miss_schema_fingerprint
352    }
353
354    #[must_use]
355    pub const fn cache_sql_compiled_command_miss_surface(&self) -> u64 {
356        self.cache_sql_compiled_command_miss_surface
357    }
358
359    #[must_use]
360    pub const fn schema_reconcile_checks(&self) -> u64 {
361        self.schema_reconcile_checks
362    }
363
364    #[must_use]
365    pub const fn schema_reconcile_exact_match(&self) -> u64 {
366        self.schema_reconcile_exact_match
367    }
368
369    #[must_use]
370    pub const fn schema_reconcile_first_create(&self) -> u64 {
371        self.schema_reconcile_first_create
372    }
373
374    #[must_use]
375    pub const fn schema_reconcile_latest_snapshot_corrupt(&self) -> u64 {
376        self.schema_reconcile_latest_snapshot_corrupt
377    }
378
379    #[must_use]
380    pub const fn schema_reconcile_rejected_field_slot(&self) -> u64 {
381        self.schema_reconcile_rejected_field_slot
382    }
383
384    #[must_use]
385    pub const fn schema_reconcile_rejected_other(&self) -> u64 {
386        self.schema_reconcile_rejected_other
387    }
388
389    #[must_use]
390    pub const fn schema_reconcile_rejected_row_layout(&self) -> u64 {
391        self.schema_reconcile_rejected_row_layout
392    }
393
394    #[must_use]
395    pub const fn schema_reconcile_rejected_schema_version(&self) -> u64 {
396        self.schema_reconcile_rejected_schema_version
397    }
398
399    #[must_use]
400    pub const fn schema_reconcile_store_write_error(&self) -> u64 {
401        self.schema_reconcile_store_write_error
402    }
403
404    #[must_use]
405    pub const fn schema_transition_checks(&self) -> u64 {
406        self.schema_transition_checks
407    }
408
409    #[must_use]
410    pub const fn schema_transition_add_expression_index(&self) -> u64 {
411        self.schema_transition_add_expression_index
412    }
413
414    #[must_use]
415    pub const fn schema_transition_add_field_path_index(&self) -> u64 {
416        self.schema_transition_add_field_path_index
417    }
418
419    #[must_use]
420    pub const fn schema_transition_append_only_fields(&self) -> u64 {
421        self.schema_transition_append_only_fields
422    }
423
424    #[must_use]
425    pub const fn schema_transition_constraint_activation(&self) -> u64 {
426        self.schema_transition_constraint_activation
427    }
428
429    #[must_use]
430    pub const fn schema_transition_exact_match(&self) -> u64 {
431        self.schema_transition_exact_match
432    }
433
434    #[must_use]
435    pub const fn schema_transition_metadata_only_field_default(&self) -> u64 {
436        self.schema_transition_metadata_only_field_default
437    }
438
439    #[must_use]
440    pub const fn schema_transition_metadata_only_index_rename(&self) -> u64 {
441        self.schema_transition_metadata_only_index_rename
442    }
443
444    #[must_use]
445    pub const fn schema_transition_rejected_entity_identity(&self) -> u64 {
446        self.schema_transition_rejected_entity_identity
447    }
448
449    #[must_use]
450    pub const fn schema_transition_rejected_field_contract(&self) -> u64 {
451        self.schema_transition_rejected_field_contract
452    }
453
454    #[must_use]
455    pub const fn schema_transition_rejected_field_slot(&self) -> u64 {
456        self.schema_transition_rejected_field_slot
457    }
458
459    #[must_use]
460    pub const fn schema_transition_rejected_row_layout(&self) -> u64 {
461        self.schema_transition_rejected_row_layout
462    }
463
464    #[must_use]
465    pub const fn schema_transition_rejected_schema_version(&self) -> u64 {
466        self.schema_transition_rejected_schema_version
467    }
468
469    #[must_use]
470    pub const fn schema_transition_rejected_snapshot(&self) -> u64 {
471        self.schema_transition_rejected_snapshot
472    }
473
474    #[must_use]
475    pub const fn schema_store_snapshots(&self) -> u64 {
476        self.schema_store_snapshots
477    }
478
479    #[must_use]
480    pub const fn schema_store_encoded_bytes(&self) -> u64 {
481        self.schema_store_encoded_bytes
482    }
483
484    #[must_use]
485    pub const fn schema_store_latest_snapshot_bytes(&self) -> u64 {
486        self.schema_store_latest_snapshot_bytes
487    }
488
489    #[must_use]
490    pub const fn accepted_schema_fields(&self) -> u64 {
491        self.accepted_schema_fields
492    }
493
494    #[must_use]
495    pub const fn accepted_schema_nested_leaf_facts(&self) -> u64 {
496        self.accepted_schema_nested_leaf_facts
497    }
498
499    #[must_use]
500    pub const fn sql_compile_rejects(&self) -> u64 {
501        self.sql_compile_rejects
502    }
503
504    #[must_use]
505    pub const fn sql_compile_reject_cache_key(&self) -> u64 {
506        self.sql_compile_reject_cache_key
507    }
508
509    #[must_use]
510    pub const fn sql_compile_reject_parse(&self) -> u64 {
511        self.sql_compile_reject_parse
512    }
513
514    #[must_use]
515    pub const fn sql_compile_reject_semantic(&self) -> u64 {
516        self.sql_compile_reject_semantic
517    }
518
519    #[must_use]
520    pub const fn plan_by_key(&self) -> u64 {
521        self.plan_by_key
522    }
523
524    #[must_use]
525    pub const fn plan_by_keys(&self) -> u64 {
526        self.plan_by_keys
527    }
528
529    #[must_use]
530    pub const fn plan_key_range(&self) -> u64 {
531        self.plan_key_range
532    }
533
534    #[must_use]
535    pub const fn plan_index_branch_set(&self) -> u64 {
536        self.plan_index_branch_set
537    }
538
539    #[must_use]
540    pub const fn plan_index_prefix(&self) -> u64 {
541        self.plan_index_prefix
542    }
543
544    #[must_use]
545    pub const fn plan_index_multi_lookup(&self) -> u64 {
546        self.plan_index_multi_lookup
547    }
548
549    #[must_use]
550    pub const fn plan_index_range(&self) -> u64 {
551        self.plan_index_range
552    }
553
554    #[must_use]
555    pub const fn plan_explicit_full_scan(&self) -> u64 {
556        self.plan_explicit_full_scan
557    }
558
559    #[must_use]
560    pub const fn plan_union(&self) -> u64 {
561        self.plan_union
562    }
563
564    #[must_use]
565    pub const fn plan_intersection(&self) -> u64 {
566        self.plan_intersection
567    }
568
569    #[must_use]
570    pub const fn plan_grouped_hash_materialized(&self) -> u64 {
571        self.plan_grouped_hash_materialized
572    }
573
574    #[must_use]
575    pub const fn plan_grouped_ordered_streaming(&self) -> u64 {
576        self.plan_grouped_ordered_streaming
577    }
578
579    #[must_use]
580    pub const fn plan_choice_conflicting_primary_key_children_access_preferred(&self) -> u64 {
581        self.plan_choice_conflicting_primary_key_children_access_preferred
582    }
583
584    #[must_use]
585    pub const fn plan_choice_constant_false_predicate(&self) -> u64 {
586        self.plan_choice_constant_false_predicate
587    }
588
589    #[must_use]
590    pub const fn plan_choice_empty_child_access_preferred(&self) -> u64 {
591        self.plan_choice_empty_child_access_preferred
592    }
593
594    #[must_use]
595    pub const fn plan_choice_full_scan_access(&self) -> u64 {
596        self.plan_choice_full_scan_access
597    }
598
599    #[must_use]
600    pub const fn plan_choice_intent_key_access_override(&self) -> u64 {
601        self.plan_choice_intent_key_access_override
602    }
603
604    #[must_use]
605    pub const fn plan_choice_limit_zero_window(&self) -> u64 {
606        self.plan_choice_limit_zero_window
607    }
608
609    #[must_use]
610    pub const fn plan_choice_non_index_access(&self) -> u64 {
611        self.plan_choice_non_index_access
612    }
613
614    #[must_use]
615    pub const fn plan_choice_planner_composite_non_index(&self) -> u64 {
616        self.plan_choice_planner_composite_non_index
617    }
618
619    #[must_use]
620    pub const fn plan_choice_planner_full_scan_fallback(&self) -> u64 {
621        self.plan_choice_planner_full_scan_fallback
622    }
623
624    #[must_use]
625    pub const fn plan_choice_planner_key_set_access(&self) -> u64 {
626        self.plan_choice_planner_key_set_access
627    }
628
629    #[must_use]
630    pub const fn plan_choice_planner_primary_key_lookup(&self) -> u64 {
631        self.plan_choice_planner_primary_key_lookup
632    }
633
634    #[must_use]
635    pub const fn plan_choice_planner_primary_key_range(&self) -> u64 {
636        self.plan_choice_planner_primary_key_range
637    }
638
639    #[must_use]
640    pub const fn plan_choice_required_order_primary_key_range_preferred(&self) -> u64 {
641        self.plan_choice_required_order_primary_key_range_preferred
642    }
643
644    #[must_use]
645    pub const fn plan_choice_singleton_primary_key_child_access_preferred(&self) -> u64 {
646        self.plan_choice_singleton_primary_key_child_access_preferred
647    }
648
649    #[must_use]
650    pub const fn prepared_shape_already_finalized(&self) -> u64 {
651        self.prepared_shape_already_finalized
652    }
653
654    #[must_use]
655    pub const fn rows_loaded(&self) -> u64 {
656        self.rows_loaded
657    }
658
659    #[must_use]
660    pub const fn rows_saved(&self) -> u64 {
661        self.rows_saved
662    }
663
664    #[must_use]
665    pub const fn rows_inserted(&self) -> u64 {
666        self.rows_inserted
667    }
668
669    #[must_use]
670    pub const fn rows_updated(&self) -> u64 {
671        self.rows_updated
672    }
673
674    #[must_use]
675    pub const fn rows_replaced(&self) -> u64 {
676        self.rows_replaced
677    }
678
679    #[must_use]
680    pub const fn rows_scanned(&self) -> u64 {
681        self.rows_scanned
682    }
683
684    #[must_use]
685    pub const fn rows_filtered(&self) -> u64 {
686        self.rows_filtered
687    }
688
689    #[must_use]
690    pub const fn rows_aggregated(&self) -> u64 {
691        self.rows_aggregated
692    }
693
694    #[must_use]
695    pub const fn rows_emitted(&self) -> u64 {
696        self.rows_emitted
697    }
698
699    #[must_use]
700    pub const fn load_candidate_rows_scanned(&self) -> u64 {
701        self.load_candidate_rows_scanned
702    }
703
704    #[must_use]
705    pub const fn load_candidate_rows_filtered(&self) -> u64 {
706        self.load_candidate_rows_filtered
707    }
708
709    #[must_use]
710    pub const fn load_result_rows_emitted(&self) -> u64 {
711        self.load_result_rows_emitted
712    }
713
714    #[must_use]
715    pub const fn rows_deleted(&self) -> u64 {
716        self.rows_deleted
717    }
718
719    #[must_use]
720    pub const fn sql_insert_calls(&self) -> u64 {
721        self.sql_insert_calls
722    }
723
724    #[must_use]
725    pub const fn sql_insert_select_calls(&self) -> u64 {
726        self.sql_insert_select_calls
727    }
728
729    #[must_use]
730    pub const fn sql_update_calls(&self) -> u64 {
731        self.sql_update_calls
732    }
733
734    #[must_use]
735    pub const fn sql_delete_calls(&self) -> u64 {
736        self.sql_delete_calls
737    }
738
739    #[must_use]
740    pub const fn sql_write_staged_rows(&self) -> u64 {
741        self.sql_write_staged_rows
742    }
743
744    #[must_use]
745    pub const fn sql_write_matched_rows(&self) -> u64 {
746        self.sql_write_matched_rows
747    }
748
749    #[must_use]
750    pub const fn sql_write_mutated_rows(&self) -> u64 {
751        self.sql_write_mutated_rows
752    }
753
754    #[must_use]
755    pub const fn sql_write_returning_rows(&self) -> u64 {
756        self.sql_write_returning_rows
757    }
758
759    #[must_use]
760    pub const fn sql_write_error_insert(&self) -> u64 {
761        self.sql_write_error_insert
762    }
763
764    #[must_use]
765    pub const fn sql_write_error_insert_select(&self) -> u64 {
766        self.sql_write_error_insert_select
767    }
768
769    #[must_use]
770    pub const fn sql_write_error_update(&self) -> u64 {
771        self.sql_write_error_update
772    }
773
774    #[must_use]
775    pub const fn sql_write_error_delete(&self) -> u64 {
776        self.sql_write_error_delete
777    }
778
779    #[must_use]
780    pub const fn sql_write_error_corruption(&self) -> u64 {
781        self.sql_write_error_corruption
782    }
783
784    #[must_use]
785    pub const fn sql_write_error_incompatible_persisted_format(&self) -> u64 {
786        self.sql_write_error_incompatible_persisted_format
787    }
788
789    #[must_use]
790    pub const fn sql_write_error_not_found(&self) -> u64 {
791        self.sql_write_error_not_found
792    }
793
794    #[must_use]
795    pub const fn sql_write_error_internal(&self) -> u64 {
796        self.sql_write_error_internal
797    }
798
799    #[must_use]
800    pub const fn sql_write_error_conflict(&self) -> u64 {
801        self.sql_write_error_conflict
802    }
803
804    #[must_use]
805    pub const fn sql_write_error_unsupported(&self) -> u64 {
806        self.sql_write_error_unsupported
807    }
808
809    #[must_use]
810    pub const fn sql_write_error_invariant_violation(&self) -> u64 {
811        self.sql_write_error_invariant_violation
812    }
813
814    #[must_use]
815    pub const fn index_inserts(&self) -> u64 {
816        self.index_inserts
817    }
818
819    #[must_use]
820    pub const fn index_removes(&self) -> u64 {
821        self.index_removes
822    }
823
824    #[must_use]
825    pub const fn reverse_index_inserts(&self) -> u64 {
826        self.reverse_index_inserts
827    }
828
829    #[must_use]
830    pub const fn reverse_index_removes(&self) -> u64 {
831        self.reverse_index_removes
832    }
833
834    #[must_use]
835    pub const fn relation_reverse_lookups(&self) -> u64 {
836        self.relation_reverse_lookups
837    }
838
839    #[must_use]
840    pub const fn relation_delete_blocks(&self) -> u64 {
841        self.relation_delete_blocks
842    }
843
844    #[must_use]
845    pub const fn write_rows_touched(&self) -> u64 {
846        self.write_rows_touched
847    }
848
849    #[must_use]
850    pub const fn write_index_entries_changed(&self) -> u64 {
851        self.write_index_entries_changed
852    }
853
854    #[must_use]
855    pub const fn write_reverse_index_entries_changed(&self) -> u64 {
856        self.write_reverse_index_entries_changed
857    }
858
859    #[must_use]
860    pub const fn write_relation_checks(&self) -> u64 {
861        self.write_relation_checks
862    }
863
864    #[must_use]
865    pub const fn unique_violations(&self) -> u64 {
866        self.unique_violations
867    }
868
869    #[must_use]
870    pub const fn non_atomic_partial_commits(&self) -> u64 {
871        self.non_atomic_partial_commits
872    }
873
874    #[must_use]
875    pub const fn non_atomic_partial_rows_committed(&self) -> u64 {
876        self.non_atomic_partial_rows_committed
877    }
878
879    /// Returns result rows emitted per load candidate row scanned.
880    #[must_use]
881    pub const fn load_selectivity_ratio(&self) -> Option<MetricRatio> {
882        ratio(
883            self.load_result_rows_emitted,
884            self.load_candidate_rows_scanned,
885        )
886    }
887
888    /// Returns candidate rows filtered per load candidate row scanned.
889    #[must_use]
890    pub const fn load_filter_ratio(&self) -> Option<MetricRatio> {
891        ratio(
892            self.load_candidate_rows_filtered,
893            self.load_candidate_rows_scanned,
894        )
895    }
896
897    /// Returns SQL-mutated rows per SQL-matched row.
898    #[must_use]
899    pub const fn sql_write_mutation_ratio(&self) -> Option<MetricRatio> {
900        ratio(self.sql_write_mutated_rows, self.sql_write_matched_rows)
901    }
902
903    /// Returns SQL `RETURNING` rows per SQL-mutated row.
904    #[must_use]
905    pub const fn sql_write_returning_ratio(&self) -> Option<MetricRatio> {
906        ratio(self.sql_write_returning_rows, self.sql_write_mutated_rows)
907    }
908
909    /// Returns primary index entries changed per write row touched.
910    #[must_use]
911    pub const fn write_index_entries_per_row(&self) -> Option<MetricRatio> {
912        ratio(self.write_index_entries_changed, self.write_rows_touched)
913    }
914
915    /// Returns reverse-index entries changed per write row touched.
916    #[must_use]
917    pub const fn write_reverse_index_entries_per_row(&self) -> Option<MetricRatio> {
918        ratio(
919            self.write_reverse_index_entries_changed,
920            self.write_rows_touched,
921        )
922    }
923
924    /// Returns relation checks performed per write row touched.
925    #[must_use]
926    pub const fn write_relation_checks_per_row(&self) -> Option<MetricRatio> {
927        ratio(self.write_relation_checks, self.write_rows_touched)
928    }
929}