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