Skip to main content

icydb_core/metrics/state/
summary.rs

1//! Module: metrics::state::summary
2//! Responsibility: rich per-entity metrics summary DTO and projection.
3//! Does not own: mutable metrics state updates or top-level report windows.
4//! Boundary: keeps per-entity rich report payload shape separate from raw state.
5
6use candid::CandidType;
7use serde::Deserialize;
8
9use super::{EntityCounters, MetricRatio, ratio};
10
11#[cfg_attr(doc, doc = "EntitySummary\n\nPer-entity metrics summary.")]
12#[derive(CandidType, Clone, Debug, Default, Deserialize)]
13pub struct EntitySummary {
14    path: String,
15    load_calls: u64,
16    save_calls: u64,
17    delete_calls: u64,
18    save_insert_calls: u64,
19    save_update_calls: u64,
20    save_replace_calls: u64,
21    exec_success: u64,
22    exec_error_corruption: u64,
23    exec_error_incompatible_persisted_format: u64,
24    exec_error_not_found: u64,
25    exec_error_internal: u64,
26    exec_error_conflict: u64,
27    exec_error_unsupported: u64,
28    exec_error_invariant_violation: u64,
29    exec_aborted: u64,
30    cache_shared_query_plan_hits: u64,
31    cache_shared_query_plan_misses: u64,
32    cache_shared_query_plan_inserts: u64,
33    cache_shared_query_plan_miss_cold: u64,
34    cache_shared_query_plan_miss_distinct_key: u64,
35    cache_shared_query_plan_miss_schema_fingerprint: u64,
36    cache_shared_query_plan_miss_visibility: u64,
37    cache_sql_compiled_command_hits: u64,
38    cache_sql_compiled_command_misses: u64,
39    cache_sql_compiled_command_inserts: u64,
40    cache_sql_compiled_command_miss_cold: u64,
41    cache_sql_compiled_command_miss_distinct_key: u64,
42    cache_sql_compiled_command_miss_schema_fingerprint: u64,
43    cache_sql_compiled_command_miss_surface: u64,
44    schema_reconcile_checks: u64,
45    schema_reconcile_exact_match: u64,
46    schema_reconcile_first_create: u64,
47    schema_reconcile_latest_snapshot_corrupt: u64,
48    schema_reconcile_rejected_field_slot: u64,
49    schema_reconcile_rejected_other: u64,
50    schema_reconcile_rejected_row_layout: u64,
51    schema_reconcile_rejected_schema_version: u64,
52    schema_reconcile_store_write_error: u64,
53    schema_transition_checks: u64,
54    schema_transition_add_expression_index: u64,
55    schema_transition_add_field_path_index: u64,
56    schema_transition_append_only_nullable_fields: u64,
57    schema_transition_exact_match: u64,
58    schema_transition_metadata_only_index_rename: u64,
59    schema_transition_rejected_entity_identity: u64,
60    schema_transition_rejected_field_contract: u64,
61    schema_transition_rejected_field_slot: u64,
62    schema_transition_rejected_row_layout: u64,
63    schema_transition_rejected_schema_version: u64,
64    schema_transition_rejected_snapshot: u64,
65    schema_store_snapshots: u64,
66    schema_store_encoded_bytes: u64,
67    schema_store_latest_snapshot_bytes: u64,
68    accepted_schema_fields: u64,
69    accepted_schema_nested_leaf_facts: u64,
70    sql_compile_rejects: u64,
71    sql_compile_reject_cache_key: u64,
72    sql_compile_reject_parse: u64,
73    sql_compile_reject_semantic: u64,
74    plan_by_key: u64,
75    plan_by_keys: u64,
76    plan_key_range: u64,
77    plan_index_branch_set: u64,
78    plan_index_prefix: u64,
79    plan_index_multi_lookup: u64,
80    plan_index_range: u64,
81    plan_explicit_full_scan: u64,
82    plan_union: u64,
83    plan_intersection: u64,
84    plan_grouped_hash_materialized: u64,
85    plan_grouped_ordered_materialized: u64,
86    plan_choice_conflicting_primary_key_children_access_preferred: u64,
87    plan_choice_constant_false_predicate: u64,
88    plan_choice_empty_child_access_preferred: u64,
89    plan_choice_full_scan_access: u64,
90    plan_choice_intent_key_access_override: u64,
91    plan_choice_limit_zero_window: u64,
92    plan_choice_non_index_access: u64,
93    plan_choice_planner_composite_non_index: u64,
94    plan_choice_planner_full_scan_fallback: u64,
95    plan_choice_planner_key_set_access: u64,
96    plan_choice_planner_primary_key_lookup: u64,
97    plan_choice_planner_primary_key_range: u64,
98    plan_choice_required_order_primary_key_range_preferred: u64,
99    plan_choice_singleton_primary_key_child_access_preferred: u64,
100    prepared_shape_already_finalized: u64,
101    rows_loaded: u64,
102    rows_saved: u64,
103    rows_inserted: u64,
104    rows_updated: u64,
105    rows_replaced: u64,
106    rows_scanned: u64,
107    rows_filtered: u64,
108    rows_aggregated: u64,
109    rows_emitted: u64,
110    load_candidate_rows_scanned: u64,
111    load_candidate_rows_filtered: u64,
112    load_result_rows_emitted: u64,
113    rows_deleted: u64,
114    sql_insert_calls: u64,
115    sql_insert_select_calls: u64,
116    sql_update_calls: u64,
117    sql_delete_calls: u64,
118    sql_write_staged_rows: u64,
119    sql_write_matched_rows: u64,
120    sql_write_mutated_rows: u64,
121    sql_write_returning_rows: u64,
122    sql_write_error_insert: u64,
123    sql_write_error_insert_select: u64,
124    sql_write_error_update: u64,
125    sql_write_error_delete: u64,
126    sql_write_error_corruption: u64,
127    sql_write_error_incompatible_persisted_format: u64,
128    sql_write_error_not_found: u64,
129    sql_write_error_internal: u64,
130    sql_write_error_conflict: u64,
131    sql_write_error_unsupported: u64,
132    sql_write_error_invariant_violation: u64,
133    index_inserts: u64,
134    index_removes: u64,
135    reverse_index_inserts: u64,
136    reverse_index_removes: u64,
137    relation_reverse_lookups: u64,
138    relation_delete_blocks: u64,
139    write_rows_touched: u64,
140    write_index_entries_changed: u64,
141    write_reverse_index_entries_changed: u64,
142    write_relation_checks: u64,
143    unique_violations: u64,
144    non_atomic_partial_commits: u64,
145    non_atomic_partial_rows_committed: u64,
146}
147
148impl EntitySummary {
149    #[must_use]
150    pub const fn path(&self) -> &str {
151        self.path.as_str()
152    }
153
154    #[must_use]
155    pub const fn load_calls(&self) -> u64 {
156        self.load_calls
157    }
158
159    #[must_use]
160    pub const fn save_calls(&self) -> u64 {
161        self.save_calls
162    }
163
164    #[must_use]
165    pub const fn delete_calls(&self) -> u64 {
166        self.delete_calls
167    }
168
169    #[must_use]
170    pub const fn save_insert_calls(&self) -> u64 {
171        self.save_insert_calls
172    }
173
174    #[must_use]
175    pub const fn save_update_calls(&self) -> u64 {
176        self.save_update_calls
177    }
178
179    #[must_use]
180    pub const fn save_replace_calls(&self) -> u64 {
181        self.save_replace_calls
182    }
183
184    #[must_use]
185    pub const fn exec_success(&self) -> u64 {
186        self.exec_success
187    }
188
189    #[must_use]
190    pub const fn exec_error_corruption(&self) -> u64 {
191        self.exec_error_corruption
192    }
193
194    #[must_use]
195    pub const fn exec_error_incompatible_persisted_format(&self) -> u64 {
196        self.exec_error_incompatible_persisted_format
197    }
198
199    #[must_use]
200    pub const fn exec_error_not_found(&self) -> u64 {
201        self.exec_error_not_found
202    }
203
204    #[must_use]
205    pub const fn exec_error_internal(&self) -> u64 {
206        self.exec_error_internal
207    }
208
209    #[must_use]
210    pub const fn exec_error_conflict(&self) -> u64 {
211        self.exec_error_conflict
212    }
213
214    #[must_use]
215    pub const fn exec_error_unsupported(&self) -> u64 {
216        self.exec_error_unsupported
217    }
218
219    #[must_use]
220    pub const fn exec_error_invariant_violation(&self) -> u64 {
221        self.exec_error_invariant_violation
222    }
223
224    #[must_use]
225    pub const fn exec_aborted(&self) -> u64 {
226        self.exec_aborted
227    }
228
229    #[must_use]
230    pub const fn cache_shared_query_plan_hits(&self) -> u64 {
231        self.cache_shared_query_plan_hits
232    }
233
234    #[must_use]
235    pub const fn cache_shared_query_plan_misses(&self) -> u64 {
236        self.cache_shared_query_plan_misses
237    }
238
239    #[must_use]
240    pub const fn cache_shared_query_plan_inserts(&self) -> u64 {
241        self.cache_shared_query_plan_inserts
242    }
243
244    #[must_use]
245    pub const fn cache_shared_query_plan_miss_cold(&self) -> u64 {
246        self.cache_shared_query_plan_miss_cold
247    }
248
249    #[must_use]
250    pub const fn cache_shared_query_plan_miss_distinct_key(&self) -> u64 {
251        self.cache_shared_query_plan_miss_distinct_key
252    }
253
254    #[must_use]
255    pub const fn cache_shared_query_plan_miss_schema_fingerprint(&self) -> u64 {
256        self.cache_shared_query_plan_miss_schema_fingerprint
257    }
258
259    #[must_use]
260    pub const fn cache_shared_query_plan_miss_visibility(&self) -> u64 {
261        self.cache_shared_query_plan_miss_visibility
262    }
263
264    #[must_use]
265    pub const fn cache_sql_compiled_command_hits(&self) -> u64 {
266        self.cache_sql_compiled_command_hits
267    }
268
269    #[must_use]
270    pub const fn cache_sql_compiled_command_misses(&self) -> u64 {
271        self.cache_sql_compiled_command_misses
272    }
273
274    #[must_use]
275    pub const fn cache_sql_compiled_command_inserts(&self) -> u64 {
276        self.cache_sql_compiled_command_inserts
277    }
278
279    #[must_use]
280    pub const fn cache_sql_compiled_command_miss_cold(&self) -> u64 {
281        self.cache_sql_compiled_command_miss_cold
282    }
283
284    #[must_use]
285    pub const fn cache_sql_compiled_command_miss_distinct_key(&self) -> u64 {
286        self.cache_sql_compiled_command_miss_distinct_key
287    }
288
289    #[must_use]
290    pub const fn cache_sql_compiled_command_miss_schema_fingerprint(&self) -> u64 {
291        self.cache_sql_compiled_command_miss_schema_fingerprint
292    }
293
294    #[must_use]
295    pub const fn cache_sql_compiled_command_miss_surface(&self) -> u64 {
296        self.cache_sql_compiled_command_miss_surface
297    }
298
299    #[must_use]
300    pub const fn schema_reconcile_checks(&self) -> u64 {
301        self.schema_reconcile_checks
302    }
303
304    #[must_use]
305    pub const fn schema_reconcile_exact_match(&self) -> u64 {
306        self.schema_reconcile_exact_match
307    }
308
309    #[must_use]
310    pub const fn schema_reconcile_first_create(&self) -> u64 {
311        self.schema_reconcile_first_create
312    }
313
314    #[must_use]
315    pub const fn schema_reconcile_latest_snapshot_corrupt(&self) -> u64 {
316        self.schema_reconcile_latest_snapshot_corrupt
317    }
318
319    #[must_use]
320    pub const fn schema_reconcile_rejected_field_slot(&self) -> u64 {
321        self.schema_reconcile_rejected_field_slot
322    }
323
324    #[must_use]
325    pub const fn schema_reconcile_rejected_other(&self) -> u64 {
326        self.schema_reconcile_rejected_other
327    }
328
329    #[must_use]
330    pub const fn schema_reconcile_rejected_row_layout(&self) -> u64 {
331        self.schema_reconcile_rejected_row_layout
332    }
333
334    #[must_use]
335    pub const fn schema_reconcile_rejected_schema_version(&self) -> u64 {
336        self.schema_reconcile_rejected_schema_version
337    }
338
339    #[must_use]
340    pub const fn schema_reconcile_store_write_error(&self) -> u64 {
341        self.schema_reconcile_store_write_error
342    }
343
344    #[must_use]
345    pub const fn schema_transition_checks(&self) -> u64 {
346        self.schema_transition_checks
347    }
348
349    #[must_use]
350    pub const fn schema_transition_add_expression_index(&self) -> u64 {
351        self.schema_transition_add_expression_index
352    }
353
354    #[must_use]
355    pub const fn schema_transition_add_field_path_index(&self) -> u64 {
356        self.schema_transition_add_field_path_index
357    }
358
359    #[must_use]
360    pub const fn schema_transition_append_only_nullable_fields(&self) -> u64 {
361        self.schema_transition_append_only_nullable_fields
362    }
363
364    #[must_use]
365    pub const fn schema_transition_exact_match(&self) -> u64 {
366        self.schema_transition_exact_match
367    }
368
369    #[must_use]
370    pub const fn schema_transition_metadata_only_index_rename(&self) -> u64 {
371        self.schema_transition_metadata_only_index_rename
372    }
373
374    #[must_use]
375    pub const fn schema_transition_rejected_entity_identity(&self) -> u64 {
376        self.schema_transition_rejected_entity_identity
377    }
378
379    #[must_use]
380    pub const fn schema_transition_rejected_field_contract(&self) -> u64 {
381        self.schema_transition_rejected_field_contract
382    }
383
384    #[must_use]
385    pub const fn schema_transition_rejected_field_slot(&self) -> u64 {
386        self.schema_transition_rejected_field_slot
387    }
388
389    #[must_use]
390    pub const fn schema_transition_rejected_row_layout(&self) -> u64 {
391        self.schema_transition_rejected_row_layout
392    }
393
394    #[must_use]
395    pub const fn schema_transition_rejected_schema_version(&self) -> u64 {
396        self.schema_transition_rejected_schema_version
397    }
398
399    #[must_use]
400    pub const fn schema_transition_rejected_snapshot(&self) -> u64 {
401        self.schema_transition_rejected_snapshot
402    }
403
404    #[must_use]
405    pub const fn schema_store_snapshots(&self) -> u64 {
406        self.schema_store_snapshots
407    }
408
409    #[must_use]
410    pub const fn schema_store_encoded_bytes(&self) -> u64 {
411        self.schema_store_encoded_bytes
412    }
413
414    #[must_use]
415    pub const fn schema_store_latest_snapshot_bytes(&self) -> u64 {
416        self.schema_store_latest_snapshot_bytes
417    }
418
419    #[must_use]
420    pub const fn accepted_schema_fields(&self) -> u64 {
421        self.accepted_schema_fields
422    }
423
424    #[must_use]
425    pub const fn accepted_schema_nested_leaf_facts(&self) -> u64 {
426        self.accepted_schema_nested_leaf_facts
427    }
428
429    #[must_use]
430    pub const fn sql_compile_rejects(&self) -> u64 {
431        self.sql_compile_rejects
432    }
433
434    #[must_use]
435    pub const fn sql_compile_reject_cache_key(&self) -> u64 {
436        self.sql_compile_reject_cache_key
437    }
438
439    #[must_use]
440    pub const fn sql_compile_reject_parse(&self) -> u64 {
441        self.sql_compile_reject_parse
442    }
443
444    #[must_use]
445    pub const fn sql_compile_reject_semantic(&self) -> u64 {
446        self.sql_compile_reject_semantic
447    }
448
449    #[must_use]
450    pub const fn plan_by_key(&self) -> u64 {
451        self.plan_by_key
452    }
453
454    #[must_use]
455    pub const fn plan_by_keys(&self) -> u64 {
456        self.plan_by_keys
457    }
458
459    #[must_use]
460    pub const fn plan_key_range(&self) -> u64 {
461        self.plan_key_range
462    }
463
464    #[must_use]
465    pub const fn plan_index_branch_set(&self) -> u64 {
466        self.plan_index_branch_set
467    }
468
469    #[must_use]
470    pub const fn plan_index_prefix(&self) -> u64 {
471        self.plan_index_prefix
472    }
473
474    #[must_use]
475    pub const fn plan_index_multi_lookup(&self) -> u64 {
476        self.plan_index_multi_lookup
477    }
478
479    #[must_use]
480    pub const fn plan_index_range(&self) -> u64 {
481        self.plan_index_range
482    }
483
484    #[must_use]
485    pub const fn plan_explicit_full_scan(&self) -> u64 {
486        self.plan_explicit_full_scan
487    }
488
489    #[must_use]
490    pub const fn plan_union(&self) -> u64 {
491        self.plan_union
492    }
493
494    #[must_use]
495    pub const fn plan_intersection(&self) -> u64 {
496        self.plan_intersection
497    }
498
499    #[must_use]
500    pub const fn plan_grouped_hash_materialized(&self) -> u64 {
501        self.plan_grouped_hash_materialized
502    }
503
504    #[must_use]
505    pub const fn plan_grouped_ordered_materialized(&self) -> u64 {
506        self.plan_grouped_ordered_materialized
507    }
508
509    #[must_use]
510    pub const fn plan_choice_conflicting_primary_key_children_access_preferred(&self) -> u64 {
511        self.plan_choice_conflicting_primary_key_children_access_preferred
512    }
513
514    #[must_use]
515    pub const fn plan_choice_constant_false_predicate(&self) -> u64 {
516        self.plan_choice_constant_false_predicate
517    }
518
519    #[must_use]
520    pub const fn plan_choice_empty_child_access_preferred(&self) -> u64 {
521        self.plan_choice_empty_child_access_preferred
522    }
523
524    #[must_use]
525    pub const fn plan_choice_full_scan_access(&self) -> u64 {
526        self.plan_choice_full_scan_access
527    }
528
529    #[must_use]
530    pub const fn plan_choice_intent_key_access_override(&self) -> u64 {
531        self.plan_choice_intent_key_access_override
532    }
533
534    #[must_use]
535    pub const fn plan_choice_limit_zero_window(&self) -> u64 {
536        self.plan_choice_limit_zero_window
537    }
538
539    #[must_use]
540    pub const fn plan_choice_non_index_access(&self) -> u64 {
541        self.plan_choice_non_index_access
542    }
543
544    #[must_use]
545    pub const fn plan_choice_planner_composite_non_index(&self) -> u64 {
546        self.plan_choice_planner_composite_non_index
547    }
548
549    #[must_use]
550    pub const fn plan_choice_planner_full_scan_fallback(&self) -> u64 {
551        self.plan_choice_planner_full_scan_fallback
552    }
553
554    #[must_use]
555    pub const fn plan_choice_planner_key_set_access(&self) -> u64 {
556        self.plan_choice_planner_key_set_access
557    }
558
559    #[must_use]
560    pub const fn plan_choice_planner_primary_key_lookup(&self) -> u64 {
561        self.plan_choice_planner_primary_key_lookup
562    }
563
564    #[must_use]
565    pub const fn plan_choice_planner_primary_key_range(&self) -> u64 {
566        self.plan_choice_planner_primary_key_range
567    }
568
569    #[must_use]
570    pub const fn plan_choice_required_order_primary_key_range_preferred(&self) -> u64 {
571        self.plan_choice_required_order_primary_key_range_preferred
572    }
573
574    #[must_use]
575    pub const fn plan_choice_singleton_primary_key_child_access_preferred(&self) -> u64 {
576        self.plan_choice_singleton_primary_key_child_access_preferred
577    }
578
579    #[must_use]
580    pub const fn prepared_shape_already_finalized(&self) -> u64 {
581        self.prepared_shape_already_finalized
582    }
583
584    #[must_use]
585    pub const fn rows_loaded(&self) -> u64 {
586        self.rows_loaded
587    }
588
589    #[must_use]
590    pub const fn rows_saved(&self) -> u64 {
591        self.rows_saved
592    }
593
594    #[must_use]
595    pub const fn rows_inserted(&self) -> u64 {
596        self.rows_inserted
597    }
598
599    #[must_use]
600    pub const fn rows_updated(&self) -> u64 {
601        self.rows_updated
602    }
603
604    #[must_use]
605    pub const fn rows_replaced(&self) -> u64 {
606        self.rows_replaced
607    }
608
609    #[must_use]
610    pub const fn rows_scanned(&self) -> u64 {
611        self.rows_scanned
612    }
613
614    #[must_use]
615    pub const fn rows_filtered(&self) -> u64 {
616        self.rows_filtered
617    }
618
619    #[must_use]
620    pub const fn rows_aggregated(&self) -> u64 {
621        self.rows_aggregated
622    }
623
624    #[must_use]
625    pub const fn rows_emitted(&self) -> u64 {
626        self.rows_emitted
627    }
628
629    #[must_use]
630    pub const fn load_candidate_rows_scanned(&self) -> u64 {
631        self.load_candidate_rows_scanned
632    }
633
634    #[must_use]
635    pub const fn load_candidate_rows_filtered(&self) -> u64 {
636        self.load_candidate_rows_filtered
637    }
638
639    #[must_use]
640    pub const fn load_result_rows_emitted(&self) -> u64 {
641        self.load_result_rows_emitted
642    }
643
644    #[must_use]
645    pub const fn rows_deleted(&self) -> u64 {
646        self.rows_deleted
647    }
648
649    #[must_use]
650    pub const fn sql_insert_calls(&self) -> u64 {
651        self.sql_insert_calls
652    }
653
654    #[must_use]
655    pub const fn sql_insert_select_calls(&self) -> u64 {
656        self.sql_insert_select_calls
657    }
658
659    #[must_use]
660    pub const fn sql_update_calls(&self) -> u64 {
661        self.sql_update_calls
662    }
663
664    #[must_use]
665    pub const fn sql_delete_calls(&self) -> u64 {
666        self.sql_delete_calls
667    }
668
669    #[must_use]
670    pub const fn sql_write_staged_rows(&self) -> u64 {
671        self.sql_write_staged_rows
672    }
673
674    #[must_use]
675    pub const fn sql_write_matched_rows(&self) -> u64 {
676        self.sql_write_matched_rows
677    }
678
679    #[must_use]
680    pub const fn sql_write_mutated_rows(&self) -> u64 {
681        self.sql_write_mutated_rows
682    }
683
684    #[must_use]
685    pub const fn sql_write_returning_rows(&self) -> u64 {
686        self.sql_write_returning_rows
687    }
688
689    #[must_use]
690    pub const fn sql_write_error_insert(&self) -> u64 {
691        self.sql_write_error_insert
692    }
693
694    #[must_use]
695    pub const fn sql_write_error_insert_select(&self) -> u64 {
696        self.sql_write_error_insert_select
697    }
698
699    #[must_use]
700    pub const fn sql_write_error_update(&self) -> u64 {
701        self.sql_write_error_update
702    }
703
704    #[must_use]
705    pub const fn sql_write_error_delete(&self) -> u64 {
706        self.sql_write_error_delete
707    }
708
709    #[must_use]
710    pub const fn sql_write_error_corruption(&self) -> u64 {
711        self.sql_write_error_corruption
712    }
713
714    #[must_use]
715    pub const fn sql_write_error_incompatible_persisted_format(&self) -> u64 {
716        self.sql_write_error_incompatible_persisted_format
717    }
718
719    #[must_use]
720    pub const fn sql_write_error_not_found(&self) -> u64 {
721        self.sql_write_error_not_found
722    }
723
724    #[must_use]
725    pub const fn sql_write_error_internal(&self) -> u64 {
726        self.sql_write_error_internal
727    }
728
729    #[must_use]
730    pub const fn sql_write_error_conflict(&self) -> u64 {
731        self.sql_write_error_conflict
732    }
733
734    #[must_use]
735    pub const fn sql_write_error_unsupported(&self) -> u64 {
736        self.sql_write_error_unsupported
737    }
738
739    #[must_use]
740    pub const fn sql_write_error_invariant_violation(&self) -> u64 {
741        self.sql_write_error_invariant_violation
742    }
743
744    #[must_use]
745    pub const fn index_inserts(&self) -> u64 {
746        self.index_inserts
747    }
748
749    #[must_use]
750    pub const fn index_removes(&self) -> u64 {
751        self.index_removes
752    }
753
754    #[must_use]
755    pub const fn reverse_index_inserts(&self) -> u64 {
756        self.reverse_index_inserts
757    }
758
759    #[must_use]
760    pub const fn reverse_index_removes(&self) -> u64 {
761        self.reverse_index_removes
762    }
763
764    #[must_use]
765    pub const fn relation_reverse_lookups(&self) -> u64 {
766        self.relation_reverse_lookups
767    }
768
769    #[must_use]
770    pub const fn relation_delete_blocks(&self) -> u64 {
771        self.relation_delete_blocks
772    }
773
774    #[must_use]
775    pub const fn write_rows_touched(&self) -> u64 {
776        self.write_rows_touched
777    }
778
779    #[must_use]
780    pub const fn write_index_entries_changed(&self) -> u64 {
781        self.write_index_entries_changed
782    }
783
784    #[must_use]
785    pub const fn write_reverse_index_entries_changed(&self) -> u64 {
786        self.write_reverse_index_entries_changed
787    }
788
789    #[must_use]
790    pub const fn write_relation_checks(&self) -> u64 {
791        self.write_relation_checks
792    }
793
794    #[must_use]
795    pub const fn unique_violations(&self) -> u64 {
796        self.unique_violations
797    }
798
799    #[must_use]
800    pub const fn non_atomic_partial_commits(&self) -> u64 {
801        self.non_atomic_partial_commits
802    }
803
804    #[must_use]
805    pub const fn non_atomic_partial_rows_committed(&self) -> u64 {
806        self.non_atomic_partial_rows_committed
807    }
808
809    /// Returns result rows emitted per load candidate row scanned.
810    #[must_use]
811    pub const fn load_selectivity_ratio(&self) -> Option<MetricRatio> {
812        ratio(
813            self.load_result_rows_emitted,
814            self.load_candidate_rows_scanned,
815        )
816    }
817
818    /// Returns candidate rows filtered per load candidate row scanned.
819    #[must_use]
820    pub const fn load_filter_ratio(&self) -> Option<MetricRatio> {
821        ratio(
822            self.load_candidate_rows_filtered,
823            self.load_candidate_rows_scanned,
824        )
825    }
826
827    /// Returns SQL-mutated rows per SQL-matched row.
828    #[must_use]
829    pub const fn sql_write_mutation_ratio(&self) -> Option<MetricRatio> {
830        ratio(self.sql_write_mutated_rows, self.sql_write_matched_rows)
831    }
832
833    /// Returns SQL `RETURNING` rows per SQL-mutated row.
834    #[must_use]
835    pub const fn sql_write_returning_ratio(&self) -> Option<MetricRatio> {
836        ratio(self.sql_write_returning_rows, self.sql_write_mutated_rows)
837    }
838
839    /// Returns primary index entries changed per write row touched.
840    #[must_use]
841    pub const fn write_index_entries_per_row(&self) -> Option<MetricRatio> {
842        ratio(self.write_index_entries_changed, self.write_rows_touched)
843    }
844
845    /// Returns reverse-index entries changed per write row touched.
846    #[must_use]
847    pub const fn write_reverse_index_entries_per_row(&self) -> Option<MetricRatio> {
848        ratio(
849            self.write_reverse_index_entries_changed,
850            self.write_rows_touched,
851        )
852    }
853
854    /// Returns relation checks performed per write row touched.
855    #[must_use]
856    pub const fn write_relation_checks_per_row(&self) -> Option<MetricRatio> {
857        ratio(self.write_relation_checks, self.write_rows_touched)
858    }
859
860    // Rank entity summaries by all visible activity so write-heavy or
861    // maintenance-heavy entities are not hidden below read-heavy entities.
862    #[expect(clippy::too_many_lines)]
863    pub(in crate::metrics) const fn activity_score(&self) -> u64 {
864        self.load_calls
865            .saturating_add(self.save_calls)
866            .saturating_add(self.delete_calls)
867            .saturating_add(self.save_insert_calls)
868            .saturating_add(self.save_update_calls)
869            .saturating_add(self.save_replace_calls)
870            .saturating_add(self.exec_success)
871            .saturating_add(self.exec_error_corruption)
872            .saturating_add(self.exec_error_incompatible_persisted_format)
873            .saturating_add(self.exec_error_not_found)
874            .saturating_add(self.exec_error_internal)
875            .saturating_add(self.exec_error_conflict)
876            .saturating_add(self.exec_error_unsupported)
877            .saturating_add(self.exec_error_invariant_violation)
878            .saturating_add(self.exec_aborted)
879            .saturating_add(self.cache_shared_query_plan_hits)
880            .saturating_add(self.cache_shared_query_plan_misses)
881            .saturating_add(self.cache_shared_query_plan_inserts)
882            .saturating_add(self.cache_shared_query_plan_miss_cold)
883            .saturating_add(self.cache_shared_query_plan_miss_distinct_key)
884            .saturating_add(self.cache_shared_query_plan_miss_schema_fingerprint)
885            .saturating_add(self.cache_shared_query_plan_miss_visibility)
886            .saturating_add(self.cache_sql_compiled_command_hits)
887            .saturating_add(self.cache_sql_compiled_command_misses)
888            .saturating_add(self.cache_sql_compiled_command_inserts)
889            .saturating_add(self.cache_sql_compiled_command_miss_cold)
890            .saturating_add(self.cache_sql_compiled_command_miss_distinct_key)
891            .saturating_add(self.cache_sql_compiled_command_miss_schema_fingerprint)
892            .saturating_add(self.cache_sql_compiled_command_miss_surface)
893            .saturating_add(self.schema_reconcile_checks)
894            .saturating_add(self.schema_reconcile_exact_match)
895            .saturating_add(self.schema_reconcile_first_create)
896            .saturating_add(self.schema_reconcile_latest_snapshot_corrupt)
897            .saturating_add(self.schema_reconcile_rejected_field_slot)
898            .saturating_add(self.schema_reconcile_rejected_other)
899            .saturating_add(self.schema_reconcile_rejected_row_layout)
900            .saturating_add(self.schema_reconcile_rejected_schema_version)
901            .saturating_add(self.schema_reconcile_store_write_error)
902            .saturating_add(self.schema_transition_checks)
903            .saturating_add(self.schema_transition_add_expression_index)
904            .saturating_add(self.schema_transition_add_field_path_index)
905            .saturating_add(self.schema_transition_append_only_nullable_fields)
906            .saturating_add(self.schema_transition_exact_match)
907            .saturating_add(self.schema_transition_metadata_only_index_rename)
908            .saturating_add(self.schema_transition_rejected_entity_identity)
909            .saturating_add(self.schema_transition_rejected_field_contract)
910            .saturating_add(self.schema_transition_rejected_field_slot)
911            .saturating_add(self.schema_transition_rejected_row_layout)
912            .saturating_add(self.schema_transition_rejected_schema_version)
913            .saturating_add(self.schema_transition_rejected_snapshot)
914            .saturating_add(self.schema_store_snapshots)
915            .saturating_add(self.schema_store_encoded_bytes)
916            .saturating_add(self.schema_store_latest_snapshot_bytes)
917            .saturating_add(self.accepted_schema_fields)
918            .saturating_add(self.accepted_schema_nested_leaf_facts)
919            .saturating_add(self.sql_compile_rejects)
920            .saturating_add(self.sql_compile_reject_cache_key)
921            .saturating_add(self.sql_compile_reject_parse)
922            .saturating_add(self.sql_compile_reject_semantic)
923            .saturating_add(self.plan_by_key)
924            .saturating_add(self.plan_by_keys)
925            .saturating_add(self.plan_key_range)
926            .saturating_add(self.plan_index_branch_set)
927            .saturating_add(self.plan_index_prefix)
928            .saturating_add(self.plan_index_multi_lookup)
929            .saturating_add(self.plan_index_range)
930            .saturating_add(self.plan_explicit_full_scan)
931            .saturating_add(self.plan_union)
932            .saturating_add(self.plan_intersection)
933            .saturating_add(self.plan_grouped_hash_materialized)
934            .saturating_add(self.plan_grouped_ordered_materialized)
935            .saturating_add(self.plan_choice_conflicting_primary_key_children_access_preferred)
936            .saturating_add(self.plan_choice_constant_false_predicate)
937            .saturating_add(self.plan_choice_empty_child_access_preferred)
938            .saturating_add(self.plan_choice_full_scan_access)
939            .saturating_add(self.plan_choice_intent_key_access_override)
940            .saturating_add(self.plan_choice_limit_zero_window)
941            .saturating_add(self.plan_choice_non_index_access)
942            .saturating_add(self.plan_choice_planner_composite_non_index)
943            .saturating_add(self.plan_choice_planner_full_scan_fallback)
944            .saturating_add(self.plan_choice_planner_key_set_access)
945            .saturating_add(self.plan_choice_planner_primary_key_lookup)
946            .saturating_add(self.plan_choice_planner_primary_key_range)
947            .saturating_add(self.plan_choice_required_order_primary_key_range_preferred)
948            .saturating_add(self.plan_choice_singleton_primary_key_child_access_preferred)
949            .saturating_add(self.prepared_shape_already_finalized)
950            .saturating_add(self.rows_loaded)
951            .saturating_add(self.rows_saved)
952            .saturating_add(self.rows_inserted)
953            .saturating_add(self.rows_updated)
954            .saturating_add(self.rows_replaced)
955            .saturating_add(self.rows_scanned)
956            .saturating_add(self.rows_filtered)
957            .saturating_add(self.rows_aggregated)
958            .saturating_add(self.rows_emitted)
959            .saturating_add(self.load_candidate_rows_scanned)
960            .saturating_add(self.load_candidate_rows_filtered)
961            .saturating_add(self.load_result_rows_emitted)
962            .saturating_add(self.rows_deleted)
963            .saturating_add(self.sql_insert_calls)
964            .saturating_add(self.sql_insert_select_calls)
965            .saturating_add(self.sql_update_calls)
966            .saturating_add(self.sql_delete_calls)
967            .saturating_add(self.sql_write_staged_rows)
968            .saturating_add(self.sql_write_matched_rows)
969            .saturating_add(self.sql_write_mutated_rows)
970            .saturating_add(self.sql_write_returning_rows)
971            .saturating_add(self.sql_write_error_insert)
972            .saturating_add(self.sql_write_error_insert_select)
973            .saturating_add(self.sql_write_error_update)
974            .saturating_add(self.sql_write_error_delete)
975            .saturating_add(self.sql_write_error_corruption)
976            .saturating_add(self.sql_write_error_incompatible_persisted_format)
977            .saturating_add(self.sql_write_error_not_found)
978            .saturating_add(self.sql_write_error_internal)
979            .saturating_add(self.sql_write_error_conflict)
980            .saturating_add(self.sql_write_error_unsupported)
981            .saturating_add(self.sql_write_error_invariant_violation)
982            .saturating_add(self.index_inserts)
983            .saturating_add(self.index_removes)
984            .saturating_add(self.reverse_index_inserts)
985            .saturating_add(self.reverse_index_removes)
986            .saturating_add(self.relation_reverse_lookups)
987            .saturating_add(self.relation_delete_blocks)
988            .saturating_add(self.write_rows_touched)
989            .saturating_add(self.write_index_entries_changed)
990            .saturating_add(self.write_reverse_index_entries_changed)
991            .saturating_add(self.write_relation_checks)
992            .saturating_add(self.unique_violations)
993            .saturating_add(self.non_atomic_partial_commits)
994            .saturating_add(self.non_atomic_partial_rows_committed)
995    }
996}
997
998// Project mutable per-entity counters into the stable report DTO.
999//
1000// Keeping this projection out of `report_window_start` leaves the window
1001// filtering logic readable while still making every report field explicit.
1002#[expect(clippy::too_many_lines)]
1003pub(in crate::metrics) fn entity_summary_from_counters(
1004    path: &str,
1005    ops: &EntityCounters,
1006) -> EntitySummary {
1007    EntitySummary {
1008        path: path.to_string(),
1009        load_calls: ops.load_calls,
1010        save_calls: ops.save_calls,
1011        delete_calls: ops.delete_calls,
1012        save_insert_calls: ops.save_insert_calls,
1013        save_update_calls: ops.save_update_calls,
1014        save_replace_calls: ops.save_replace_calls,
1015        exec_success: ops.exec_success,
1016        exec_error_corruption: ops.exec_error_corruption,
1017        exec_error_incompatible_persisted_format: ops.exec_error_incompatible_persisted_format,
1018        exec_error_not_found: ops.exec_error_not_found,
1019        exec_error_internal: ops.exec_error_internal,
1020        exec_error_conflict: ops.exec_error_conflict,
1021        exec_error_unsupported: ops.exec_error_unsupported,
1022        exec_error_invariant_violation: ops.exec_error_invariant_violation,
1023        exec_aborted: ops.exec_aborted,
1024        cache_shared_query_plan_hits: ops.cache_shared_query_plan_hits,
1025        cache_shared_query_plan_misses: ops.cache_shared_query_plan_misses,
1026        cache_shared_query_plan_inserts: ops.cache_shared_query_plan_inserts,
1027        cache_shared_query_plan_miss_cold: ops.cache_shared_query_plan_miss_cold,
1028        cache_shared_query_plan_miss_distinct_key: ops.cache_shared_query_plan_miss_distinct_key,
1029        cache_shared_query_plan_miss_schema_fingerprint: ops
1030            .cache_shared_query_plan_miss_schema_fingerprint,
1031        cache_shared_query_plan_miss_visibility: ops.cache_shared_query_plan_miss_visibility,
1032        cache_sql_compiled_command_hits: ops.cache_sql_compiled_command_hits,
1033        cache_sql_compiled_command_misses: ops.cache_sql_compiled_command_misses,
1034        cache_sql_compiled_command_inserts: ops.cache_sql_compiled_command_inserts,
1035        cache_sql_compiled_command_miss_cold: ops.cache_sql_compiled_command_miss_cold,
1036        cache_sql_compiled_command_miss_distinct_key: ops
1037            .cache_sql_compiled_command_miss_distinct_key,
1038        cache_sql_compiled_command_miss_schema_fingerprint: ops
1039            .cache_sql_compiled_command_miss_schema_fingerprint,
1040        cache_sql_compiled_command_miss_surface: ops.cache_sql_compiled_command_miss_surface,
1041        schema_reconcile_checks: ops.schema_reconcile_checks,
1042        schema_reconcile_exact_match: ops.schema_reconcile_exact_match,
1043        schema_reconcile_first_create: ops.schema_reconcile_first_create,
1044        schema_reconcile_latest_snapshot_corrupt: ops.schema_reconcile_latest_snapshot_corrupt,
1045        schema_reconcile_rejected_field_slot: ops.schema_reconcile_rejected_field_slot,
1046        schema_reconcile_rejected_other: ops.schema_reconcile_rejected_other,
1047        schema_reconcile_rejected_row_layout: ops.schema_reconcile_rejected_row_layout,
1048        schema_reconcile_rejected_schema_version: ops.schema_reconcile_rejected_schema_version,
1049        schema_reconcile_store_write_error: ops.schema_reconcile_store_write_error,
1050        schema_transition_checks: ops.schema_transition_checks,
1051        schema_transition_add_expression_index: ops.schema_transition_add_expression_index,
1052        schema_transition_add_field_path_index: ops.schema_transition_add_field_path_index,
1053        schema_transition_append_only_nullable_fields: ops
1054            .schema_transition_append_only_nullable_fields,
1055        schema_transition_exact_match: ops.schema_transition_exact_match,
1056        schema_transition_metadata_only_index_rename: ops
1057            .schema_transition_metadata_only_index_rename,
1058        schema_transition_rejected_entity_identity: ops.schema_transition_rejected_entity_identity,
1059        schema_transition_rejected_field_contract: ops.schema_transition_rejected_field_contract,
1060        schema_transition_rejected_field_slot: ops.schema_transition_rejected_field_slot,
1061        schema_transition_rejected_row_layout: ops.schema_transition_rejected_row_layout,
1062        schema_transition_rejected_schema_version: ops.schema_transition_rejected_schema_version,
1063        schema_transition_rejected_snapshot: ops.schema_transition_rejected_snapshot,
1064        schema_store_snapshots: ops.schema_store_snapshots,
1065        schema_store_encoded_bytes: ops.schema_store_encoded_bytes,
1066        schema_store_latest_snapshot_bytes: ops.schema_store_latest_snapshot_bytes,
1067        accepted_schema_fields: ops.accepted_schema_fields,
1068        accepted_schema_nested_leaf_facts: ops.accepted_schema_nested_leaf_facts,
1069        sql_compile_rejects: ops.sql_compile_rejects,
1070        sql_compile_reject_cache_key: ops.sql_compile_reject_cache_key,
1071        sql_compile_reject_parse: ops.sql_compile_reject_parse,
1072        sql_compile_reject_semantic: ops.sql_compile_reject_semantic,
1073        plan_by_key: ops.plan_by_key,
1074        plan_by_keys: ops.plan_by_keys,
1075        plan_key_range: ops.plan_key_range,
1076        plan_index_branch_set: ops.plan_index_branch_set,
1077        plan_index_prefix: ops.plan_index_prefix,
1078        plan_index_multi_lookup: ops.plan_index_multi_lookup,
1079        plan_index_range: ops.plan_index_range,
1080        plan_explicit_full_scan: ops.plan_explicit_full_scan,
1081        plan_union: ops.plan_union,
1082        plan_intersection: ops.plan_intersection,
1083        plan_grouped_hash_materialized: ops.plan_grouped_hash_materialized,
1084        plan_grouped_ordered_materialized: ops.plan_grouped_ordered_materialized,
1085        plan_choice_conflicting_primary_key_children_access_preferred: ops
1086            .plan_choice_conflicting_primary_key_children_access_preferred,
1087        plan_choice_constant_false_predicate: ops.plan_choice_constant_false_predicate,
1088        plan_choice_empty_child_access_preferred: ops.plan_choice_empty_child_access_preferred,
1089        plan_choice_full_scan_access: ops.plan_choice_full_scan_access,
1090        plan_choice_intent_key_access_override: ops.plan_choice_intent_key_access_override,
1091        plan_choice_limit_zero_window: ops.plan_choice_limit_zero_window,
1092        plan_choice_non_index_access: ops.plan_choice_non_index_access,
1093        plan_choice_planner_composite_non_index: ops.plan_choice_planner_composite_non_index,
1094        plan_choice_planner_full_scan_fallback: ops.plan_choice_planner_full_scan_fallback,
1095        plan_choice_planner_key_set_access: ops.plan_choice_planner_key_set_access,
1096        plan_choice_planner_primary_key_lookup: ops.plan_choice_planner_primary_key_lookup,
1097        plan_choice_planner_primary_key_range: ops.plan_choice_planner_primary_key_range,
1098        plan_choice_required_order_primary_key_range_preferred: ops
1099            .plan_choice_required_order_primary_key_range_preferred,
1100        plan_choice_singleton_primary_key_child_access_preferred: ops
1101            .plan_choice_singleton_primary_key_child_access_preferred,
1102        prepared_shape_already_finalized: ops.prepared_shape_already_finalized,
1103        rows_loaded: ops.rows_loaded,
1104        rows_saved: ops.rows_saved,
1105        rows_inserted: ops.rows_inserted,
1106        rows_updated: ops.rows_updated,
1107        rows_replaced: ops.rows_replaced,
1108        rows_scanned: ops.rows_scanned,
1109        rows_filtered: ops.rows_filtered,
1110        rows_aggregated: ops.rows_aggregated,
1111        rows_emitted: ops.rows_emitted,
1112        load_candidate_rows_scanned: ops.load_candidate_rows_scanned,
1113        load_candidate_rows_filtered: ops.load_candidate_rows_filtered,
1114        load_result_rows_emitted: ops.load_result_rows_emitted,
1115        rows_deleted: ops.rows_deleted,
1116        sql_insert_calls: ops.sql_insert_calls,
1117        sql_insert_select_calls: ops.sql_insert_select_calls,
1118        sql_update_calls: ops.sql_update_calls,
1119        sql_delete_calls: ops.sql_delete_calls,
1120        sql_write_staged_rows: ops.sql_write_staged_rows,
1121        sql_write_matched_rows: ops.sql_write_matched_rows,
1122        sql_write_mutated_rows: ops.sql_write_mutated_rows,
1123        sql_write_returning_rows: ops.sql_write_returning_rows,
1124        sql_write_error_insert: ops.sql_write_error_insert,
1125        sql_write_error_insert_select: ops.sql_write_error_insert_select,
1126        sql_write_error_update: ops.sql_write_error_update,
1127        sql_write_error_delete: ops.sql_write_error_delete,
1128        sql_write_error_corruption: ops.sql_write_error_corruption,
1129        sql_write_error_incompatible_persisted_format: ops
1130            .sql_write_error_incompatible_persisted_format,
1131        sql_write_error_not_found: ops.sql_write_error_not_found,
1132        sql_write_error_internal: ops.sql_write_error_internal,
1133        sql_write_error_conflict: ops.sql_write_error_conflict,
1134        sql_write_error_unsupported: ops.sql_write_error_unsupported,
1135        sql_write_error_invariant_violation: ops.sql_write_error_invariant_violation,
1136        index_inserts: ops.index_inserts,
1137        index_removes: ops.index_removes,
1138        reverse_index_inserts: ops.reverse_index_inserts,
1139        reverse_index_removes: ops.reverse_index_removes,
1140        relation_reverse_lookups: ops.relation_reverse_lookups,
1141        relation_delete_blocks: ops.relation_delete_blocks,
1142        write_rows_touched: ops.write_rows_touched,
1143        write_index_entries_changed: ops.write_index_entries_changed,
1144        write_reverse_index_entries_changed: ops.write_reverse_index_entries_changed,
1145        write_relation_checks: ops.write_relation_checks,
1146        unique_violations: ops.unique_violations,
1147        non_atomic_partial_commits: ops.non_atomic_partial_commits,
1148        non_atomic_partial_rows_committed: ops.non_atomic_partial_rows_committed,
1149    }
1150}