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