1use candid::CandidType;
11use canic_cdk::utils::time::now_millis;
12use serde::Deserialize;
13use std::{cell::RefCell, collections::BTreeMap};
14
15#[derive(Clone, Debug)]
16pub(crate) struct EventState {
17 pub(crate) ops: EventOps,
18 pub(crate) perf: EventPerf,
19 pub(crate) entities: BTreeMap<String, EntityCounters>,
20 pub(crate) window_start_ms: u64,
21}
22
23impl Default for EventState {
24 fn default() -> Self {
25 Self {
26 ops: EventOps::default(),
27 perf: EventPerf::default(),
28 entities: BTreeMap::new(),
29 window_start_ms: now_millis(),
30 }
31 }
32}
33
34#[derive(Clone, Copy, Debug, Eq, PartialEq)]
42pub struct MetricRatio {
43 numerator: u64,
44 denominator: u64,
45}
46
47impl MetricRatio {
48 #[must_use]
50 pub const fn numerator(&self) -> u64 {
51 self.numerator
52 }
53
54 #[must_use]
56 pub const fn denominator(&self) -> u64 {
57 self.denominator
58 }
59
60 #[must_use]
62 pub const fn into_parts(self) -> (u64, u64) {
63 (self.numerator, self.denominator)
64 }
65}
66
67const fn ratio(numerator: u64, denominator: u64) -> Option<MetricRatio> {
71 if denominator == 0 {
72 return None;
73 }
74
75 Some(MetricRatio {
76 numerator,
77 denominator,
78 })
79}
80
81#[cfg_attr(doc, doc = "EventOps\n\nOperation counters.")]
82#[derive(CandidType, Clone, Debug, Default, Deserialize)]
83pub struct EventOps {
84 pub(crate) load_calls: u64,
86 pub(crate) save_calls: u64,
87 pub(crate) delete_calls: u64,
88 pub(crate) save_insert_calls: u64,
89 pub(crate) save_update_calls: u64,
90 pub(crate) save_replace_calls: u64,
91 pub(crate) exec_success: u64,
92 pub(crate) exec_error_corruption: u64,
93 pub(crate) exec_error_incompatible_persisted_format: u64,
94 pub(crate) exec_error_not_found: u64,
95 pub(crate) exec_error_internal: u64,
96 pub(crate) exec_error_conflict: u64,
97 pub(crate) exec_error_unsupported: u64,
98 pub(crate) exec_error_invariant_violation: u64,
99 pub(crate) exec_aborted: u64,
100 pub(crate) cache_shared_query_plan_hits: u64,
101 pub(crate) cache_shared_query_plan_misses: u64,
102 pub(crate) cache_shared_query_plan_inserts: u64,
103 pub(crate) cache_shared_query_plan_entries: u64,
104 pub(crate) cache_shared_query_plan_miss_cold: u64,
105 pub(crate) cache_shared_query_plan_miss_distinct_key: u64,
106 pub(crate) cache_shared_query_plan_miss_method_version: u64,
107 pub(crate) cache_shared_query_plan_miss_schema_fingerprint: u64,
108 pub(crate) cache_shared_query_plan_miss_visibility: u64,
109 pub(crate) cache_sql_compiled_command_hits: u64,
110 pub(crate) cache_sql_compiled_command_misses: u64,
111 pub(crate) cache_sql_compiled_command_inserts: u64,
112 pub(crate) cache_sql_compiled_command_entries: u64,
113 pub(crate) cache_sql_compiled_command_miss_cold: u64,
114 pub(crate) cache_sql_compiled_command_miss_distinct_key: u64,
115 pub(crate) cache_sql_compiled_command_miss_method_version: u64,
116 pub(crate) cache_sql_compiled_command_miss_schema_fingerprint: u64,
117 pub(crate) cache_sql_compiled_command_miss_surface: u64,
118 pub(crate) schema_reconcile_checks: u64,
119 pub(crate) schema_reconcile_exact_match: u64,
120 pub(crate) schema_reconcile_first_create: u64,
121 pub(crate) schema_reconcile_latest_snapshot_corrupt: u64,
122 pub(crate) schema_reconcile_rejected_field_slot: u64,
123 pub(crate) schema_reconcile_rejected_other: u64,
124 pub(crate) schema_reconcile_rejected_row_layout: u64,
125 pub(crate) schema_reconcile_rejected_schema_version: u64,
126 pub(crate) schema_reconcile_store_write_error: u64,
127 pub(crate) schema_transition_checks: u64,
128 pub(crate) schema_transition_exact_match: u64,
129 pub(crate) schema_transition_rejected_entity_identity: u64,
130 pub(crate) schema_transition_rejected_field_contract: u64,
131 pub(crate) schema_transition_rejected_field_slot: u64,
132 pub(crate) schema_transition_rejected_row_layout: u64,
133 pub(crate) schema_transition_rejected_schema_version: u64,
134 pub(crate) schema_transition_rejected_snapshot: u64,
135 pub(crate) schema_store_snapshots: u64,
136 pub(crate) schema_store_encoded_bytes: u64,
137 pub(crate) schema_store_latest_snapshot_bytes: u64,
138 pub(crate) accepted_schema_fields: u64,
139 pub(crate) accepted_schema_nested_leaf_facts: u64,
140 pub(crate) sql_compile_rejects: u64,
141 pub(crate) sql_compile_reject_cache_key: u64,
142 pub(crate) sql_compile_reject_parse: u64,
143 pub(crate) sql_compile_reject_semantic: u64,
144
145 pub(crate) plan_index: u64,
147 pub(crate) plan_keys: u64,
148 pub(crate) plan_range: u64,
149 pub(crate) plan_full_scan: u64,
150 pub(crate) plan_by_key: u64,
151 pub(crate) plan_by_keys: u64,
152 pub(crate) plan_key_range: u64,
153 pub(crate) plan_index_prefix: u64,
154 pub(crate) plan_index_multi_lookup: u64,
155 pub(crate) plan_index_range: u64,
156 pub(crate) plan_explicit_full_scan: u64,
157 pub(crate) plan_union: u64,
158 pub(crate) plan_intersection: u64,
159 pub(crate) plan_grouped_hash_materialized: u64,
160 pub(crate) plan_grouped_ordered_materialized: u64,
161 pub(crate) plan_choice_conflicting_primary_key_children_access_preferred: u64,
162 pub(crate) plan_choice_constant_false_predicate: u64,
163 pub(crate) plan_choice_empty_child_access_preferred: u64,
164 pub(crate) plan_choice_full_scan_access: u64,
165 pub(crate) plan_choice_intent_key_access_override: u64,
166 pub(crate) plan_choice_limit_zero_window: u64,
167 pub(crate) plan_choice_non_index_access: u64,
168 pub(crate) plan_choice_planner_composite_non_index: u64,
169 pub(crate) plan_choice_planner_full_scan_fallback: u64,
170 pub(crate) plan_choice_planner_key_set_access: u64,
171 pub(crate) plan_choice_planner_primary_key_lookup: u64,
172 pub(crate) plan_choice_planner_primary_key_range: u64,
173 pub(crate) plan_choice_required_order_primary_key_range_preferred: u64,
174 pub(crate) plan_choice_singleton_primary_key_child_access_preferred: u64,
175 pub(crate) prepared_shape_already_finalized: u64,
176 pub(crate) prepared_shape_generated_fallback: u64,
177
178 pub(crate) rows_loaded: u64,
180 pub(crate) rows_saved: u64,
181 pub(crate) rows_inserted: u64,
182 pub(crate) rows_updated: u64,
183 pub(crate) rows_replaced: u64,
184 pub(crate) rows_scanned: u64,
185 pub(crate) rows_filtered: u64,
186 pub(crate) rows_aggregated: u64,
187 pub(crate) rows_emitted: u64,
188 pub(crate) load_candidate_rows_scanned: u64,
189 pub(crate) load_candidate_rows_filtered: u64,
190 pub(crate) load_result_rows_emitted: u64,
191 pub(crate) rows_deleted: u64,
192 pub(crate) sql_insert_calls: u64,
193 pub(crate) sql_insert_select_calls: u64,
194 pub(crate) sql_update_calls: u64,
195 pub(crate) sql_delete_calls: u64,
196 pub(crate) sql_write_matched_rows: u64,
197 pub(crate) sql_write_mutated_rows: u64,
198 pub(crate) sql_write_returning_rows: u64,
199 pub(crate) sql_write_error_insert: u64,
200 pub(crate) sql_write_error_insert_select: u64,
201 pub(crate) sql_write_error_update: u64,
202 pub(crate) sql_write_error_delete: u64,
203 pub(crate) sql_write_error_corruption: u64,
204 pub(crate) sql_write_error_incompatible_persisted_format: u64,
205 pub(crate) sql_write_error_not_found: u64,
206 pub(crate) sql_write_error_internal: u64,
207 pub(crate) sql_write_error_conflict: u64,
208 pub(crate) sql_write_error_unsupported: u64,
209 pub(crate) sql_write_error_invariant_violation: u64,
210
211 pub(crate) index_inserts: u64,
213 pub(crate) index_removes: u64,
214 pub(crate) reverse_index_inserts: u64,
215 pub(crate) reverse_index_removes: u64,
216 pub(crate) relation_reverse_lookups: u64,
217 pub(crate) relation_delete_blocks: u64,
218 pub(crate) write_rows_touched: u64,
219 pub(crate) write_index_entries_changed: u64,
220 pub(crate) write_reverse_index_entries_changed: u64,
221 pub(crate) write_relation_checks: u64,
222 pub(crate) unique_violations: u64,
223 pub(crate) non_atomic_partial_commits: u64,
224 pub(crate) non_atomic_partial_rows_committed: u64,
225}
226
227impl EventOps {
228 #[must_use]
229 pub const fn load_calls(&self) -> u64 {
230 self.load_calls
231 }
232
233 #[must_use]
234 pub const fn save_calls(&self) -> u64 {
235 self.save_calls
236 }
237
238 #[must_use]
239 pub const fn delete_calls(&self) -> u64 {
240 self.delete_calls
241 }
242
243 #[must_use]
244 pub const fn save_insert_calls(&self) -> u64 {
245 self.save_insert_calls
246 }
247
248 #[must_use]
249 pub const fn save_update_calls(&self) -> u64 {
250 self.save_update_calls
251 }
252
253 #[must_use]
254 pub const fn save_replace_calls(&self) -> u64 {
255 self.save_replace_calls
256 }
257
258 #[must_use]
259 pub const fn exec_success(&self) -> u64 {
260 self.exec_success
261 }
262
263 #[must_use]
264 pub const fn exec_error_corruption(&self) -> u64 {
265 self.exec_error_corruption
266 }
267
268 #[must_use]
269 pub const fn exec_error_incompatible_persisted_format(&self) -> u64 {
270 self.exec_error_incompatible_persisted_format
271 }
272
273 #[must_use]
274 pub const fn exec_error_not_found(&self) -> u64 {
275 self.exec_error_not_found
276 }
277
278 #[must_use]
279 pub const fn exec_error_internal(&self) -> u64 {
280 self.exec_error_internal
281 }
282
283 #[must_use]
284 pub const fn exec_error_conflict(&self) -> u64 {
285 self.exec_error_conflict
286 }
287
288 #[must_use]
289 pub const fn exec_error_unsupported(&self) -> u64 {
290 self.exec_error_unsupported
291 }
292
293 #[must_use]
294 pub const fn exec_error_invariant_violation(&self) -> u64 {
295 self.exec_error_invariant_violation
296 }
297
298 #[must_use]
299 pub const fn exec_aborted(&self) -> u64 {
300 self.exec_aborted
301 }
302
303 #[must_use]
304 pub const fn cache_shared_query_plan_hits(&self) -> u64 {
305 self.cache_shared_query_plan_hits
306 }
307
308 #[must_use]
309 pub const fn cache_shared_query_plan_misses(&self) -> u64 {
310 self.cache_shared_query_plan_misses
311 }
312
313 #[must_use]
314 pub const fn cache_shared_query_plan_inserts(&self) -> u64 {
315 self.cache_shared_query_plan_inserts
316 }
317
318 #[must_use]
319 pub const fn cache_shared_query_plan_entries(&self) -> u64 {
320 self.cache_shared_query_plan_entries
321 }
322
323 #[must_use]
324 pub const fn cache_shared_query_plan_miss_cold(&self) -> u64 {
325 self.cache_shared_query_plan_miss_cold
326 }
327
328 #[must_use]
329 pub const fn cache_shared_query_plan_miss_distinct_key(&self) -> u64 {
330 self.cache_shared_query_plan_miss_distinct_key
331 }
332
333 #[must_use]
334 pub const fn cache_shared_query_plan_miss_method_version(&self) -> u64 {
335 self.cache_shared_query_plan_miss_method_version
336 }
337
338 #[must_use]
339 pub const fn cache_shared_query_plan_miss_schema_fingerprint(&self) -> u64 {
340 self.cache_shared_query_plan_miss_schema_fingerprint
341 }
342
343 #[must_use]
344 pub const fn cache_shared_query_plan_miss_visibility(&self) -> u64 {
345 self.cache_shared_query_plan_miss_visibility
346 }
347
348 #[must_use]
349 pub const fn cache_sql_compiled_command_hits(&self) -> u64 {
350 self.cache_sql_compiled_command_hits
351 }
352
353 #[must_use]
354 pub const fn cache_sql_compiled_command_misses(&self) -> u64 {
355 self.cache_sql_compiled_command_misses
356 }
357
358 #[must_use]
359 pub const fn cache_sql_compiled_command_inserts(&self) -> u64 {
360 self.cache_sql_compiled_command_inserts
361 }
362
363 #[must_use]
364 pub const fn cache_sql_compiled_command_entries(&self) -> u64 {
365 self.cache_sql_compiled_command_entries
366 }
367
368 #[must_use]
369 pub const fn cache_sql_compiled_command_miss_cold(&self) -> u64 {
370 self.cache_sql_compiled_command_miss_cold
371 }
372
373 #[must_use]
374 pub const fn cache_sql_compiled_command_miss_distinct_key(&self) -> u64 {
375 self.cache_sql_compiled_command_miss_distinct_key
376 }
377
378 #[must_use]
379 pub const fn cache_sql_compiled_command_miss_method_version(&self) -> u64 {
380 self.cache_sql_compiled_command_miss_method_version
381 }
382
383 #[must_use]
384 pub const fn cache_sql_compiled_command_miss_schema_fingerprint(&self) -> u64 {
385 self.cache_sql_compiled_command_miss_schema_fingerprint
386 }
387
388 #[must_use]
389 pub const fn cache_sql_compiled_command_miss_surface(&self) -> u64 {
390 self.cache_sql_compiled_command_miss_surface
391 }
392
393 #[must_use]
394 pub const fn schema_reconcile_checks(&self) -> u64 {
395 self.schema_reconcile_checks
396 }
397
398 #[must_use]
399 pub const fn schema_reconcile_exact_match(&self) -> u64 {
400 self.schema_reconcile_exact_match
401 }
402
403 #[must_use]
404 pub const fn schema_reconcile_first_create(&self) -> u64 {
405 self.schema_reconcile_first_create
406 }
407
408 #[must_use]
409 pub const fn schema_reconcile_latest_snapshot_corrupt(&self) -> u64 {
410 self.schema_reconcile_latest_snapshot_corrupt
411 }
412
413 #[must_use]
414 pub const fn schema_reconcile_rejected_field_slot(&self) -> u64 {
415 self.schema_reconcile_rejected_field_slot
416 }
417
418 #[must_use]
419 pub const fn schema_reconcile_rejected_other(&self) -> u64 {
420 self.schema_reconcile_rejected_other
421 }
422
423 #[must_use]
424 pub const fn schema_reconcile_rejected_row_layout(&self) -> u64 {
425 self.schema_reconcile_rejected_row_layout
426 }
427
428 #[must_use]
429 pub const fn schema_reconcile_rejected_schema_version(&self) -> u64 {
430 self.schema_reconcile_rejected_schema_version
431 }
432
433 #[must_use]
434 pub const fn schema_reconcile_store_write_error(&self) -> u64 {
435 self.schema_reconcile_store_write_error
436 }
437
438 #[must_use]
439 pub const fn schema_transition_checks(&self) -> u64 {
440 self.schema_transition_checks
441 }
442
443 #[must_use]
444 pub const fn schema_transition_exact_match(&self) -> u64 {
445 self.schema_transition_exact_match
446 }
447
448 #[must_use]
449 pub const fn schema_transition_rejected_entity_identity(&self) -> u64 {
450 self.schema_transition_rejected_entity_identity
451 }
452
453 #[must_use]
454 pub const fn schema_transition_rejected_field_contract(&self) -> u64 {
455 self.schema_transition_rejected_field_contract
456 }
457
458 #[must_use]
459 pub const fn schema_transition_rejected_field_slot(&self) -> u64 {
460 self.schema_transition_rejected_field_slot
461 }
462
463 #[must_use]
464 pub const fn schema_transition_rejected_row_layout(&self) -> u64 {
465 self.schema_transition_rejected_row_layout
466 }
467
468 #[must_use]
469 pub const fn schema_transition_rejected_schema_version(&self) -> u64 {
470 self.schema_transition_rejected_schema_version
471 }
472
473 #[must_use]
474 pub const fn schema_transition_rejected_snapshot(&self) -> u64 {
475 self.schema_transition_rejected_snapshot
476 }
477
478 #[must_use]
479 pub const fn schema_store_snapshots(&self) -> u64 {
480 self.schema_store_snapshots
481 }
482
483 #[must_use]
484 pub const fn schema_store_encoded_bytes(&self) -> u64 {
485 self.schema_store_encoded_bytes
486 }
487
488 #[must_use]
489 pub const fn schema_store_latest_snapshot_bytes(&self) -> u64 {
490 self.schema_store_latest_snapshot_bytes
491 }
492
493 #[must_use]
494 pub const fn accepted_schema_fields(&self) -> u64 {
495 self.accepted_schema_fields
496 }
497
498 #[must_use]
499 pub const fn accepted_schema_nested_leaf_facts(&self) -> u64 {
500 self.accepted_schema_nested_leaf_facts
501 }
502
503 #[must_use]
504 pub const fn sql_compile_rejects(&self) -> u64 {
505 self.sql_compile_rejects
506 }
507
508 #[must_use]
509 pub const fn sql_compile_reject_cache_key(&self) -> u64 {
510 self.sql_compile_reject_cache_key
511 }
512
513 #[must_use]
514 pub const fn sql_compile_reject_parse(&self) -> u64 {
515 self.sql_compile_reject_parse
516 }
517
518 #[must_use]
519 pub const fn sql_compile_reject_semantic(&self) -> u64 {
520 self.sql_compile_reject_semantic
521 }
522
523 #[must_use]
524 pub const fn plan_index(&self) -> u64 {
525 self.plan_index
526 }
527
528 #[must_use]
529 pub const fn plan_keys(&self) -> u64 {
530 self.plan_keys
531 }
532
533 #[must_use]
534 pub const fn plan_range(&self) -> u64 {
535 self.plan_range
536 }
537
538 #[must_use]
539 pub const fn plan_full_scan(&self) -> u64 {
540 self.plan_full_scan
541 }
542
543 #[must_use]
544 pub const fn plan_by_key(&self) -> u64 {
545 self.plan_by_key
546 }
547
548 #[must_use]
549 pub const fn plan_by_keys(&self) -> u64 {
550 self.plan_by_keys
551 }
552
553 #[must_use]
554 pub const fn plan_key_range(&self) -> u64 {
555 self.plan_key_range
556 }
557
558 #[must_use]
559 pub const fn plan_index_prefix(&self) -> u64 {
560 self.plan_index_prefix
561 }
562
563 #[must_use]
564 pub const fn plan_index_multi_lookup(&self) -> u64 {
565 self.plan_index_multi_lookup
566 }
567
568 #[must_use]
569 pub const fn plan_index_range(&self) -> u64 {
570 self.plan_index_range
571 }
572
573 #[must_use]
574 pub const fn plan_explicit_full_scan(&self) -> u64 {
575 self.plan_explicit_full_scan
576 }
577
578 #[must_use]
579 pub const fn plan_union(&self) -> u64 {
580 self.plan_union
581 }
582
583 #[must_use]
584 pub const fn plan_intersection(&self) -> u64 {
585 self.plan_intersection
586 }
587
588 #[must_use]
589 pub const fn plan_grouped_hash_materialized(&self) -> u64 {
590 self.plan_grouped_hash_materialized
591 }
592
593 #[must_use]
594 pub const fn plan_grouped_ordered_materialized(&self) -> u64 {
595 self.plan_grouped_ordered_materialized
596 }
597
598 #[must_use]
599 pub const fn plan_choice_conflicting_primary_key_children_access_preferred(&self) -> u64 {
600 self.plan_choice_conflicting_primary_key_children_access_preferred
601 }
602
603 #[must_use]
604 pub const fn plan_choice_constant_false_predicate(&self) -> u64 {
605 self.plan_choice_constant_false_predicate
606 }
607
608 #[must_use]
609 pub const fn plan_choice_empty_child_access_preferred(&self) -> u64 {
610 self.plan_choice_empty_child_access_preferred
611 }
612
613 #[must_use]
614 pub const fn plan_choice_full_scan_access(&self) -> u64 {
615 self.plan_choice_full_scan_access
616 }
617
618 #[must_use]
619 pub const fn plan_choice_intent_key_access_override(&self) -> u64 {
620 self.plan_choice_intent_key_access_override
621 }
622
623 #[must_use]
624 pub const fn plan_choice_limit_zero_window(&self) -> u64 {
625 self.plan_choice_limit_zero_window
626 }
627
628 #[must_use]
629 pub const fn plan_choice_non_index_access(&self) -> u64 {
630 self.plan_choice_non_index_access
631 }
632
633 #[must_use]
634 pub const fn plan_choice_planner_composite_non_index(&self) -> u64 {
635 self.plan_choice_planner_composite_non_index
636 }
637
638 #[must_use]
639 pub const fn plan_choice_planner_full_scan_fallback(&self) -> u64 {
640 self.plan_choice_planner_full_scan_fallback
641 }
642
643 #[must_use]
644 pub const fn plan_choice_planner_key_set_access(&self) -> u64 {
645 self.plan_choice_planner_key_set_access
646 }
647
648 #[must_use]
649 pub const fn plan_choice_planner_primary_key_lookup(&self) -> u64 {
650 self.plan_choice_planner_primary_key_lookup
651 }
652
653 #[must_use]
654 pub const fn plan_choice_planner_primary_key_range(&self) -> u64 {
655 self.plan_choice_planner_primary_key_range
656 }
657
658 #[must_use]
659 pub const fn plan_choice_required_order_primary_key_range_preferred(&self) -> u64 {
660 self.plan_choice_required_order_primary_key_range_preferred
661 }
662
663 #[must_use]
664 pub const fn plan_choice_singleton_primary_key_child_access_preferred(&self) -> u64 {
665 self.plan_choice_singleton_primary_key_child_access_preferred
666 }
667
668 #[must_use]
669 pub const fn prepared_shape_already_finalized(&self) -> u64 {
670 self.prepared_shape_already_finalized
671 }
672
673 #[must_use]
674 pub const fn prepared_shape_generated_fallback(&self) -> u64 {
675 self.prepared_shape_generated_fallback
676 }
677
678 #[must_use]
679 pub const fn rows_loaded(&self) -> u64 {
680 self.rows_loaded
681 }
682
683 #[must_use]
684 pub const fn rows_saved(&self) -> u64 {
685 self.rows_saved
686 }
687
688 #[must_use]
689 pub const fn rows_inserted(&self) -> u64 {
690 self.rows_inserted
691 }
692
693 #[must_use]
694 pub const fn rows_updated(&self) -> u64 {
695 self.rows_updated
696 }
697
698 #[must_use]
699 pub const fn rows_replaced(&self) -> u64 {
700 self.rows_replaced
701 }
702
703 #[must_use]
704 pub const fn rows_scanned(&self) -> u64 {
705 self.rows_scanned
706 }
707
708 #[must_use]
709 pub const fn rows_filtered(&self) -> u64 {
710 self.rows_filtered
711 }
712
713 #[must_use]
714 pub const fn rows_aggregated(&self) -> u64 {
715 self.rows_aggregated
716 }
717
718 #[must_use]
719 pub const fn rows_emitted(&self) -> u64 {
720 self.rows_emitted
721 }
722
723 #[must_use]
724 pub const fn load_candidate_rows_scanned(&self) -> u64 {
725 self.load_candidate_rows_scanned
726 }
727
728 #[must_use]
729 pub const fn load_candidate_rows_filtered(&self) -> u64 {
730 self.load_candidate_rows_filtered
731 }
732
733 #[must_use]
734 pub const fn load_result_rows_emitted(&self) -> u64 {
735 self.load_result_rows_emitted
736 }
737
738 #[must_use]
739 pub const fn rows_deleted(&self) -> u64 {
740 self.rows_deleted
741 }
742
743 #[must_use]
744 pub const fn sql_insert_calls(&self) -> u64 {
745 self.sql_insert_calls
746 }
747
748 #[must_use]
749 pub const fn sql_insert_select_calls(&self) -> u64 {
750 self.sql_insert_select_calls
751 }
752
753 #[must_use]
754 pub const fn sql_update_calls(&self) -> u64 {
755 self.sql_update_calls
756 }
757
758 #[must_use]
759 pub const fn sql_delete_calls(&self) -> u64 {
760 self.sql_delete_calls
761 }
762
763 #[must_use]
764 pub const fn sql_write_matched_rows(&self) -> u64 {
765 self.sql_write_matched_rows
766 }
767
768 #[must_use]
769 pub const fn sql_write_mutated_rows(&self) -> u64 {
770 self.sql_write_mutated_rows
771 }
772
773 #[must_use]
774 pub const fn sql_write_returning_rows(&self) -> u64 {
775 self.sql_write_returning_rows
776 }
777
778 #[must_use]
779 pub const fn sql_write_error_insert(&self) -> u64 {
780 self.sql_write_error_insert
781 }
782
783 #[must_use]
784 pub const fn sql_write_error_insert_select(&self) -> u64 {
785 self.sql_write_error_insert_select
786 }
787
788 #[must_use]
789 pub const fn sql_write_error_update(&self) -> u64 {
790 self.sql_write_error_update
791 }
792
793 #[must_use]
794 pub const fn sql_write_error_delete(&self) -> u64 {
795 self.sql_write_error_delete
796 }
797
798 #[must_use]
799 pub const fn sql_write_error_corruption(&self) -> u64 {
800 self.sql_write_error_corruption
801 }
802
803 #[must_use]
804 pub const fn sql_write_error_incompatible_persisted_format(&self) -> u64 {
805 self.sql_write_error_incompatible_persisted_format
806 }
807
808 #[must_use]
809 pub const fn sql_write_error_not_found(&self) -> u64 {
810 self.sql_write_error_not_found
811 }
812
813 #[must_use]
814 pub const fn sql_write_error_internal(&self) -> u64 {
815 self.sql_write_error_internal
816 }
817
818 #[must_use]
819 pub const fn sql_write_error_conflict(&self) -> u64 {
820 self.sql_write_error_conflict
821 }
822
823 #[must_use]
824 pub const fn sql_write_error_unsupported(&self) -> u64 {
825 self.sql_write_error_unsupported
826 }
827
828 #[must_use]
829 pub const fn sql_write_error_invariant_violation(&self) -> u64 {
830 self.sql_write_error_invariant_violation
831 }
832
833 #[must_use]
834 pub const fn index_inserts(&self) -> u64 {
835 self.index_inserts
836 }
837
838 #[must_use]
839 pub const fn index_removes(&self) -> u64 {
840 self.index_removes
841 }
842
843 #[must_use]
844 pub const fn reverse_index_inserts(&self) -> u64 {
845 self.reverse_index_inserts
846 }
847
848 #[must_use]
849 pub const fn reverse_index_removes(&self) -> u64 {
850 self.reverse_index_removes
851 }
852
853 #[must_use]
854 pub const fn relation_reverse_lookups(&self) -> u64 {
855 self.relation_reverse_lookups
856 }
857
858 #[must_use]
859 pub const fn relation_delete_blocks(&self) -> u64 {
860 self.relation_delete_blocks
861 }
862
863 #[must_use]
864 pub const fn write_rows_touched(&self) -> u64 {
865 self.write_rows_touched
866 }
867
868 #[must_use]
869 pub const fn write_index_entries_changed(&self) -> u64 {
870 self.write_index_entries_changed
871 }
872
873 #[must_use]
874 pub const fn write_reverse_index_entries_changed(&self) -> u64 {
875 self.write_reverse_index_entries_changed
876 }
877
878 #[must_use]
879 pub const fn write_relation_checks(&self) -> u64 {
880 self.write_relation_checks
881 }
882
883 #[must_use]
884 pub const fn unique_violations(&self) -> u64 {
885 self.unique_violations
886 }
887
888 #[must_use]
889 pub const fn non_atomic_partial_commits(&self) -> u64 {
890 self.non_atomic_partial_commits
891 }
892
893 #[must_use]
894 pub const fn non_atomic_partial_rows_committed(&self) -> u64 {
895 self.non_atomic_partial_rows_committed
896 }
897
898 #[must_use]
900 pub const fn load_selectivity_ratio(&self) -> Option<MetricRatio> {
901 ratio(
902 self.load_result_rows_emitted,
903 self.load_candidate_rows_scanned,
904 )
905 }
906
907 #[must_use]
909 pub const fn load_filter_ratio(&self) -> Option<MetricRatio> {
910 ratio(
911 self.load_candidate_rows_filtered,
912 self.load_candidate_rows_scanned,
913 )
914 }
915
916 #[must_use]
918 pub const fn sql_write_mutation_ratio(&self) -> Option<MetricRatio> {
919 ratio(self.sql_write_mutated_rows, self.sql_write_matched_rows)
920 }
921
922 #[must_use]
924 pub const fn sql_write_returning_ratio(&self) -> Option<MetricRatio> {
925 ratio(self.sql_write_returning_rows, self.sql_write_mutated_rows)
926 }
927
928 #[must_use]
930 pub const fn write_index_entries_per_row(&self) -> Option<MetricRatio> {
931 ratio(self.write_index_entries_changed, self.write_rows_touched)
932 }
933
934 #[must_use]
936 pub const fn write_reverse_index_entries_per_row(&self) -> Option<MetricRatio> {
937 ratio(
938 self.write_reverse_index_entries_changed,
939 self.write_rows_touched,
940 )
941 }
942
943 #[must_use]
945 pub const fn write_relation_checks_per_row(&self) -> Option<MetricRatio> {
946 ratio(self.write_relation_checks, self.write_rows_touched)
947 }
948}
949
950#[derive(Clone, Debug, Default)]
951pub(crate) struct EntityCounters {
952 pub(crate) load_calls: u64,
953 pub(crate) save_calls: u64,
954 pub(crate) delete_calls: u64,
955 pub(crate) save_insert_calls: u64,
956 pub(crate) save_update_calls: u64,
957 pub(crate) save_replace_calls: u64,
958 pub(crate) exec_success: u64,
959 pub(crate) exec_error_corruption: u64,
960 pub(crate) exec_error_incompatible_persisted_format: u64,
961 pub(crate) exec_error_not_found: u64,
962 pub(crate) exec_error_internal: u64,
963 pub(crate) exec_error_conflict: u64,
964 pub(crate) exec_error_unsupported: u64,
965 pub(crate) exec_error_invariant_violation: u64,
966 pub(crate) exec_aborted: u64,
967 pub(crate) cache_shared_query_plan_hits: u64,
968 pub(crate) cache_shared_query_plan_misses: u64,
969 pub(crate) cache_shared_query_plan_inserts: u64,
970 pub(crate) cache_shared_query_plan_miss_cold: u64,
971 pub(crate) cache_shared_query_plan_miss_distinct_key: u64,
972 pub(crate) cache_shared_query_plan_miss_method_version: u64,
973 pub(crate) cache_shared_query_plan_miss_schema_fingerprint: u64,
974 pub(crate) cache_shared_query_plan_miss_visibility: u64,
975 pub(crate) cache_sql_compiled_command_hits: u64,
976 pub(crate) cache_sql_compiled_command_misses: u64,
977 pub(crate) cache_sql_compiled_command_inserts: u64,
978 pub(crate) cache_sql_compiled_command_miss_cold: u64,
979 pub(crate) cache_sql_compiled_command_miss_distinct_key: u64,
980 pub(crate) cache_sql_compiled_command_miss_method_version: u64,
981 pub(crate) cache_sql_compiled_command_miss_schema_fingerprint: u64,
982 pub(crate) cache_sql_compiled_command_miss_surface: u64,
983 pub(crate) schema_reconcile_checks: u64,
984 pub(crate) schema_reconcile_exact_match: u64,
985 pub(crate) schema_reconcile_first_create: u64,
986 pub(crate) schema_reconcile_latest_snapshot_corrupt: u64,
987 pub(crate) schema_reconcile_rejected_field_slot: u64,
988 pub(crate) schema_reconcile_rejected_other: u64,
989 pub(crate) schema_reconcile_rejected_row_layout: u64,
990 pub(crate) schema_reconcile_rejected_schema_version: u64,
991 pub(crate) schema_reconcile_store_write_error: u64,
992 pub(crate) schema_transition_checks: u64,
993 pub(crate) schema_transition_exact_match: u64,
994 pub(crate) schema_transition_rejected_entity_identity: u64,
995 pub(crate) schema_transition_rejected_field_contract: u64,
996 pub(crate) schema_transition_rejected_field_slot: u64,
997 pub(crate) schema_transition_rejected_row_layout: u64,
998 pub(crate) schema_transition_rejected_schema_version: u64,
999 pub(crate) schema_transition_rejected_snapshot: u64,
1000 pub(crate) schema_store_snapshots: u64,
1001 pub(crate) schema_store_encoded_bytes: u64,
1002 pub(crate) schema_store_latest_snapshot_bytes: u64,
1003 pub(crate) accepted_schema_fields: u64,
1004 pub(crate) accepted_schema_nested_leaf_facts: u64,
1005 pub(crate) sql_compile_rejects: u64,
1006 pub(crate) sql_compile_reject_cache_key: u64,
1007 pub(crate) sql_compile_reject_parse: u64,
1008 pub(crate) sql_compile_reject_semantic: u64,
1009 pub(crate) plan_index: u64,
1010 pub(crate) plan_keys: u64,
1011 pub(crate) plan_range: u64,
1012 pub(crate) plan_full_scan: u64,
1013 pub(crate) plan_by_key: u64,
1014 pub(crate) plan_by_keys: u64,
1015 pub(crate) plan_key_range: u64,
1016 pub(crate) plan_index_prefix: u64,
1017 pub(crate) plan_index_multi_lookup: u64,
1018 pub(crate) plan_index_range: u64,
1019 pub(crate) plan_explicit_full_scan: u64,
1020 pub(crate) plan_union: u64,
1021 pub(crate) plan_intersection: u64,
1022 pub(crate) plan_grouped_hash_materialized: u64,
1023 pub(crate) plan_grouped_ordered_materialized: u64,
1024 pub(crate) plan_choice_conflicting_primary_key_children_access_preferred: u64,
1025 pub(crate) plan_choice_constant_false_predicate: u64,
1026 pub(crate) plan_choice_empty_child_access_preferred: u64,
1027 pub(crate) plan_choice_full_scan_access: u64,
1028 pub(crate) plan_choice_intent_key_access_override: u64,
1029 pub(crate) plan_choice_limit_zero_window: u64,
1030 pub(crate) plan_choice_non_index_access: u64,
1031 pub(crate) plan_choice_planner_composite_non_index: u64,
1032 pub(crate) plan_choice_planner_full_scan_fallback: u64,
1033 pub(crate) plan_choice_planner_key_set_access: u64,
1034 pub(crate) plan_choice_planner_primary_key_lookup: u64,
1035 pub(crate) plan_choice_planner_primary_key_range: u64,
1036 pub(crate) plan_choice_required_order_primary_key_range_preferred: u64,
1037 pub(crate) plan_choice_singleton_primary_key_child_access_preferred: u64,
1038 pub(crate) prepared_shape_already_finalized: u64,
1039 pub(crate) prepared_shape_generated_fallback: u64,
1040 pub(crate) rows_loaded: u64,
1041 pub(crate) rows_saved: u64,
1042 pub(crate) rows_inserted: u64,
1043 pub(crate) rows_updated: u64,
1044 pub(crate) rows_replaced: u64,
1045 pub(crate) rows_scanned: u64,
1046 pub(crate) rows_filtered: u64,
1047 pub(crate) rows_aggregated: u64,
1048 pub(crate) rows_emitted: u64,
1049 pub(crate) load_candidate_rows_scanned: u64,
1050 pub(crate) load_candidate_rows_filtered: u64,
1051 pub(crate) load_result_rows_emitted: u64,
1052 pub(crate) rows_deleted: u64,
1053 pub(crate) sql_insert_calls: u64,
1054 pub(crate) sql_insert_select_calls: u64,
1055 pub(crate) sql_update_calls: u64,
1056 pub(crate) sql_delete_calls: u64,
1057 pub(crate) sql_write_matched_rows: u64,
1058 pub(crate) sql_write_mutated_rows: u64,
1059 pub(crate) sql_write_returning_rows: u64,
1060 pub(crate) sql_write_error_insert: u64,
1061 pub(crate) sql_write_error_insert_select: u64,
1062 pub(crate) sql_write_error_update: u64,
1063 pub(crate) sql_write_error_delete: u64,
1064 pub(crate) sql_write_error_corruption: u64,
1065 pub(crate) sql_write_error_incompatible_persisted_format: u64,
1066 pub(crate) sql_write_error_not_found: u64,
1067 pub(crate) sql_write_error_internal: u64,
1068 pub(crate) sql_write_error_conflict: u64,
1069 pub(crate) sql_write_error_unsupported: u64,
1070 pub(crate) sql_write_error_invariant_violation: u64,
1071 pub(crate) index_inserts: u64,
1072 pub(crate) index_removes: u64,
1073 pub(crate) reverse_index_inserts: u64,
1074 pub(crate) reverse_index_removes: u64,
1075 pub(crate) relation_reverse_lookups: u64,
1076 pub(crate) relation_delete_blocks: u64,
1077 pub(crate) write_rows_touched: u64,
1078 pub(crate) write_index_entries_changed: u64,
1079 pub(crate) write_reverse_index_entries_changed: u64,
1080 pub(crate) write_relation_checks: u64,
1081 pub(crate) unique_violations: u64,
1082 pub(crate) non_atomic_partial_commits: u64,
1083 pub(crate) non_atomic_partial_rows_committed: u64,
1084}
1085
1086#[cfg_attr(doc, doc = "EventPerf\n\nInstruction totals and maxima.")]
1087#[derive(CandidType, Clone, Debug, Default, Deserialize)]
1088pub struct EventPerf {
1089 pub(crate) load_inst_total: u128,
1091 pub(crate) save_inst_total: u128,
1092 pub(crate) delete_inst_total: u128,
1093
1094 pub(crate) load_inst_max: u64,
1096 pub(crate) save_inst_max: u64,
1097 pub(crate) delete_inst_max: u64,
1098}
1099
1100impl EventPerf {
1101 #[must_use]
1102 pub const fn new(
1103 load_inst_total: u128,
1104 save_inst_total: u128,
1105 delete_inst_total: u128,
1106 load_inst_max: u64,
1107 save_inst_max: u64,
1108 delete_inst_max: u64,
1109 ) -> Self {
1110 Self {
1111 load_inst_total,
1112 save_inst_total,
1113 delete_inst_total,
1114 load_inst_max,
1115 save_inst_max,
1116 delete_inst_max,
1117 }
1118 }
1119
1120 #[must_use]
1121 pub const fn load_inst_total(&self) -> u128 {
1122 self.load_inst_total
1123 }
1124
1125 #[must_use]
1126 pub const fn save_inst_total(&self) -> u128 {
1127 self.save_inst_total
1128 }
1129
1130 #[must_use]
1131 pub const fn delete_inst_total(&self) -> u128 {
1132 self.delete_inst_total
1133 }
1134
1135 #[must_use]
1136 pub const fn load_inst_max(&self) -> u64 {
1137 self.load_inst_max
1138 }
1139
1140 #[must_use]
1141 pub const fn save_inst_max(&self) -> u64 {
1142 self.save_inst_max
1143 }
1144
1145 #[must_use]
1146 pub const fn delete_inst_max(&self) -> u64 {
1147 self.delete_inst_max
1148 }
1149}
1150
1151thread_local! {
1152 static EVENT_STATE: RefCell<EventState> = RefCell::new(EventState::default());
1153}
1154
1155pub(crate) fn with_state<R>(f: impl FnOnce(&EventState) -> R) -> R {
1157 EVENT_STATE.with(|m| f(&m.borrow()))
1158}
1159
1160pub(crate) fn with_state_mut<R>(f: impl FnOnce(&mut EventState) -> R) -> R {
1162 EVENT_STATE.with(|m| f(&mut m.borrow_mut()))
1163}
1164
1165pub(super) fn reset() {
1167 with_state_mut(|m| *m = EventState::default());
1168}
1169
1170pub(crate) fn reset_all() {
1172 reset();
1173}
1174
1175pub(super) fn add_instructions(total: &mut u128, max: &mut u64, delta_inst: u64) {
1177 *total = total.saturating_add(u128::from(delta_inst));
1178 if delta_inst > *max {
1179 *max = delta_inst;
1180 }
1181}
1182
1183#[cfg_attr(doc, doc = "EventReport\n\nMetrics query payload.")]
1184#[derive(CandidType, Clone, Debug, Default, Deserialize)]
1185pub struct EventReport {
1186 counters: Option<EventCounters>,
1187 entity_counters: Vec<EntitySummary>,
1188 window_filter_matched: bool,
1189 requested_window_start_ms: Option<u64>,
1190 active_window_start_ms: u64,
1191}
1192
1193impl EventReport {
1194 #[must_use]
1195 pub(crate) const fn new(
1196 counters: Option<EventCounters>,
1197 entity_counters: Vec<EntitySummary>,
1198 window_filter_matched: bool,
1199 requested_window_start_ms: Option<u64>,
1200 active_window_start_ms: u64,
1201 ) -> Self {
1202 Self {
1203 counters,
1204 entity_counters,
1205 window_filter_matched,
1206 requested_window_start_ms,
1207 active_window_start_ms,
1208 }
1209 }
1210
1211 #[must_use]
1212 pub const fn counters(&self) -> Option<&EventCounters> {
1213 self.counters.as_ref()
1214 }
1215
1216 #[must_use]
1217 pub fn entity_counters(&self) -> &[EntitySummary] {
1218 &self.entity_counters
1219 }
1220
1221 #[must_use]
1222 pub const fn window_filter_matched(&self) -> bool {
1223 self.window_filter_matched
1224 }
1225
1226 #[must_use]
1227 pub const fn requested_window_start_ms(&self) -> Option<u64> {
1228 self.requested_window_start_ms
1229 }
1230
1231 #[must_use]
1232 pub const fn active_window_start_ms(&self) -> u64 {
1233 self.active_window_start_ms
1234 }
1235
1236 #[must_use]
1237 pub fn into_counters(self) -> Option<EventCounters> {
1238 self.counters
1239 }
1240
1241 #[must_use]
1242 pub fn into_entity_counters(self) -> Vec<EntitySummary> {
1243 self.entity_counters
1244 }
1245}
1246
1247#[derive(CandidType, Clone, Debug, Default, Deserialize)]
1256pub struct EventCounters {
1257 pub(crate) ops: EventOps,
1258 pub(crate) perf: EventPerf,
1259 pub(crate) window_start_ms: u64,
1260 pub(crate) window_end_ms: u64,
1261 pub(crate) window_duration_ms: u64,
1262}
1263
1264impl EventCounters {
1265 #[must_use]
1266 pub(crate) const fn new(
1267 ops: EventOps,
1268 perf: EventPerf,
1269 window_start_ms: u64,
1270 window_end_ms: u64,
1271 ) -> Self {
1272 Self {
1273 ops,
1274 perf,
1275 window_start_ms,
1276 window_end_ms,
1277 window_duration_ms: window_end_ms.saturating_sub(window_start_ms),
1278 }
1279 }
1280
1281 #[must_use]
1282 pub const fn ops(&self) -> &EventOps {
1283 &self.ops
1284 }
1285
1286 #[must_use]
1287 pub const fn perf(&self) -> &EventPerf {
1288 &self.perf
1289 }
1290
1291 #[must_use]
1292 pub const fn window_start_ms(&self) -> u64 {
1293 self.window_start_ms
1294 }
1295
1296 #[must_use]
1297 pub const fn window_end_ms(&self) -> u64 {
1298 self.window_end_ms
1299 }
1300
1301 #[must_use]
1302 pub const fn window_duration_ms(&self) -> u64 {
1303 self.window_duration_ms
1304 }
1305}
1306
1307#[cfg_attr(doc, doc = "EntitySummary\n\nPer-entity metrics summary.")]
1308#[derive(CandidType, Clone, Debug, Default, Deserialize)]
1309pub struct EntitySummary {
1310 path: String,
1311 load_calls: u64,
1312 save_calls: u64,
1313 delete_calls: u64,
1314 save_insert_calls: u64,
1315 save_update_calls: u64,
1316 save_replace_calls: u64,
1317 exec_success: u64,
1318 exec_error_corruption: u64,
1319 exec_error_incompatible_persisted_format: u64,
1320 exec_error_not_found: u64,
1321 exec_error_internal: u64,
1322 exec_error_conflict: u64,
1323 exec_error_unsupported: u64,
1324 exec_error_invariant_violation: u64,
1325 exec_aborted: u64,
1326 cache_shared_query_plan_hits: u64,
1327 cache_shared_query_plan_misses: u64,
1328 cache_shared_query_plan_inserts: u64,
1329 cache_shared_query_plan_miss_cold: u64,
1330 cache_shared_query_plan_miss_distinct_key: u64,
1331 cache_shared_query_plan_miss_method_version: u64,
1332 cache_shared_query_plan_miss_schema_fingerprint: u64,
1333 cache_shared_query_plan_miss_visibility: u64,
1334 cache_sql_compiled_command_hits: u64,
1335 cache_sql_compiled_command_misses: u64,
1336 cache_sql_compiled_command_inserts: u64,
1337 cache_sql_compiled_command_miss_cold: u64,
1338 cache_sql_compiled_command_miss_distinct_key: u64,
1339 cache_sql_compiled_command_miss_method_version: u64,
1340 cache_sql_compiled_command_miss_schema_fingerprint: u64,
1341 cache_sql_compiled_command_miss_surface: u64,
1342 schema_reconcile_checks: u64,
1343 schema_reconcile_exact_match: u64,
1344 schema_reconcile_first_create: u64,
1345 schema_reconcile_latest_snapshot_corrupt: u64,
1346 schema_reconcile_rejected_field_slot: u64,
1347 schema_reconcile_rejected_other: u64,
1348 schema_reconcile_rejected_row_layout: u64,
1349 schema_reconcile_rejected_schema_version: u64,
1350 schema_reconcile_store_write_error: u64,
1351 schema_transition_checks: u64,
1352 schema_transition_exact_match: u64,
1353 schema_transition_rejected_entity_identity: u64,
1354 schema_transition_rejected_field_contract: u64,
1355 schema_transition_rejected_field_slot: u64,
1356 schema_transition_rejected_row_layout: u64,
1357 schema_transition_rejected_schema_version: u64,
1358 schema_transition_rejected_snapshot: u64,
1359 schema_store_snapshots: u64,
1360 schema_store_encoded_bytes: u64,
1361 schema_store_latest_snapshot_bytes: u64,
1362 accepted_schema_fields: u64,
1363 accepted_schema_nested_leaf_facts: u64,
1364 sql_compile_rejects: u64,
1365 sql_compile_reject_cache_key: u64,
1366 sql_compile_reject_parse: u64,
1367 sql_compile_reject_semantic: u64,
1368 plan_index: u64,
1369 plan_keys: u64,
1370 plan_range: u64,
1371 plan_full_scan: u64,
1372 plan_by_key: u64,
1373 plan_by_keys: u64,
1374 plan_key_range: u64,
1375 plan_index_prefix: u64,
1376 plan_index_multi_lookup: u64,
1377 plan_index_range: u64,
1378 plan_explicit_full_scan: u64,
1379 plan_union: u64,
1380 plan_intersection: u64,
1381 plan_grouped_hash_materialized: u64,
1382 plan_grouped_ordered_materialized: u64,
1383 plan_choice_conflicting_primary_key_children_access_preferred: u64,
1384 plan_choice_constant_false_predicate: u64,
1385 plan_choice_empty_child_access_preferred: u64,
1386 plan_choice_full_scan_access: u64,
1387 plan_choice_intent_key_access_override: u64,
1388 plan_choice_limit_zero_window: u64,
1389 plan_choice_non_index_access: u64,
1390 plan_choice_planner_composite_non_index: u64,
1391 plan_choice_planner_full_scan_fallback: u64,
1392 plan_choice_planner_key_set_access: u64,
1393 plan_choice_planner_primary_key_lookup: u64,
1394 plan_choice_planner_primary_key_range: u64,
1395 plan_choice_required_order_primary_key_range_preferred: u64,
1396 plan_choice_singleton_primary_key_child_access_preferred: u64,
1397 prepared_shape_already_finalized: u64,
1398 prepared_shape_generated_fallback: u64,
1399 rows_loaded: u64,
1400 rows_saved: u64,
1401 rows_inserted: u64,
1402 rows_updated: u64,
1403 rows_replaced: u64,
1404 rows_scanned: u64,
1405 rows_filtered: u64,
1406 rows_aggregated: u64,
1407 rows_emitted: u64,
1408 load_candidate_rows_scanned: u64,
1409 load_candidate_rows_filtered: u64,
1410 load_result_rows_emitted: u64,
1411 rows_deleted: u64,
1412 sql_insert_calls: u64,
1413 sql_insert_select_calls: u64,
1414 sql_update_calls: u64,
1415 sql_delete_calls: u64,
1416 sql_write_matched_rows: u64,
1417 sql_write_mutated_rows: u64,
1418 sql_write_returning_rows: u64,
1419 sql_write_error_insert: u64,
1420 sql_write_error_insert_select: u64,
1421 sql_write_error_update: u64,
1422 sql_write_error_delete: u64,
1423 sql_write_error_corruption: u64,
1424 sql_write_error_incompatible_persisted_format: u64,
1425 sql_write_error_not_found: u64,
1426 sql_write_error_internal: u64,
1427 sql_write_error_conflict: u64,
1428 sql_write_error_unsupported: u64,
1429 sql_write_error_invariant_violation: u64,
1430 index_inserts: u64,
1431 index_removes: u64,
1432 reverse_index_inserts: u64,
1433 reverse_index_removes: u64,
1434 relation_reverse_lookups: u64,
1435 relation_delete_blocks: u64,
1436 write_rows_touched: u64,
1437 write_index_entries_changed: u64,
1438 write_reverse_index_entries_changed: u64,
1439 write_relation_checks: u64,
1440 unique_violations: u64,
1441 non_atomic_partial_commits: u64,
1442 non_atomic_partial_rows_committed: u64,
1443}
1444
1445impl EntitySummary {
1446 #[must_use]
1447 pub const fn path(&self) -> &str {
1448 self.path.as_str()
1449 }
1450
1451 #[must_use]
1452 pub const fn load_calls(&self) -> u64 {
1453 self.load_calls
1454 }
1455
1456 #[must_use]
1457 pub const fn save_calls(&self) -> u64 {
1458 self.save_calls
1459 }
1460
1461 #[must_use]
1462 pub const fn delete_calls(&self) -> u64 {
1463 self.delete_calls
1464 }
1465
1466 #[must_use]
1467 pub const fn save_insert_calls(&self) -> u64 {
1468 self.save_insert_calls
1469 }
1470
1471 #[must_use]
1472 pub const fn save_update_calls(&self) -> u64 {
1473 self.save_update_calls
1474 }
1475
1476 #[must_use]
1477 pub const fn save_replace_calls(&self) -> u64 {
1478 self.save_replace_calls
1479 }
1480
1481 #[must_use]
1482 pub const fn exec_success(&self) -> u64 {
1483 self.exec_success
1484 }
1485
1486 #[must_use]
1487 pub const fn exec_error_corruption(&self) -> u64 {
1488 self.exec_error_corruption
1489 }
1490
1491 #[must_use]
1492 pub const fn exec_error_incompatible_persisted_format(&self) -> u64 {
1493 self.exec_error_incompatible_persisted_format
1494 }
1495
1496 #[must_use]
1497 pub const fn exec_error_not_found(&self) -> u64 {
1498 self.exec_error_not_found
1499 }
1500
1501 #[must_use]
1502 pub const fn exec_error_internal(&self) -> u64 {
1503 self.exec_error_internal
1504 }
1505
1506 #[must_use]
1507 pub const fn exec_error_conflict(&self) -> u64 {
1508 self.exec_error_conflict
1509 }
1510
1511 #[must_use]
1512 pub const fn exec_error_unsupported(&self) -> u64 {
1513 self.exec_error_unsupported
1514 }
1515
1516 #[must_use]
1517 pub const fn exec_error_invariant_violation(&self) -> u64 {
1518 self.exec_error_invariant_violation
1519 }
1520
1521 #[must_use]
1522 pub const fn exec_aborted(&self) -> u64 {
1523 self.exec_aborted
1524 }
1525
1526 #[must_use]
1527 pub const fn cache_shared_query_plan_hits(&self) -> u64 {
1528 self.cache_shared_query_plan_hits
1529 }
1530
1531 #[must_use]
1532 pub const fn cache_shared_query_plan_misses(&self) -> u64 {
1533 self.cache_shared_query_plan_misses
1534 }
1535
1536 #[must_use]
1537 pub const fn cache_shared_query_plan_inserts(&self) -> u64 {
1538 self.cache_shared_query_plan_inserts
1539 }
1540
1541 #[must_use]
1542 pub const fn cache_shared_query_plan_miss_cold(&self) -> u64 {
1543 self.cache_shared_query_plan_miss_cold
1544 }
1545
1546 #[must_use]
1547 pub const fn cache_shared_query_plan_miss_distinct_key(&self) -> u64 {
1548 self.cache_shared_query_plan_miss_distinct_key
1549 }
1550
1551 #[must_use]
1552 pub const fn cache_shared_query_plan_miss_method_version(&self) -> u64 {
1553 self.cache_shared_query_plan_miss_method_version
1554 }
1555
1556 #[must_use]
1557 pub const fn cache_shared_query_plan_miss_schema_fingerprint(&self) -> u64 {
1558 self.cache_shared_query_plan_miss_schema_fingerprint
1559 }
1560
1561 #[must_use]
1562 pub const fn cache_shared_query_plan_miss_visibility(&self) -> u64 {
1563 self.cache_shared_query_plan_miss_visibility
1564 }
1565
1566 #[must_use]
1567 pub const fn cache_sql_compiled_command_hits(&self) -> u64 {
1568 self.cache_sql_compiled_command_hits
1569 }
1570
1571 #[must_use]
1572 pub const fn cache_sql_compiled_command_misses(&self) -> u64 {
1573 self.cache_sql_compiled_command_misses
1574 }
1575
1576 #[must_use]
1577 pub const fn cache_sql_compiled_command_inserts(&self) -> u64 {
1578 self.cache_sql_compiled_command_inserts
1579 }
1580
1581 #[must_use]
1582 pub const fn cache_sql_compiled_command_miss_cold(&self) -> u64 {
1583 self.cache_sql_compiled_command_miss_cold
1584 }
1585
1586 #[must_use]
1587 pub const fn cache_sql_compiled_command_miss_distinct_key(&self) -> u64 {
1588 self.cache_sql_compiled_command_miss_distinct_key
1589 }
1590
1591 #[must_use]
1592 pub const fn cache_sql_compiled_command_miss_method_version(&self) -> u64 {
1593 self.cache_sql_compiled_command_miss_method_version
1594 }
1595
1596 #[must_use]
1597 pub const fn cache_sql_compiled_command_miss_schema_fingerprint(&self) -> u64 {
1598 self.cache_sql_compiled_command_miss_schema_fingerprint
1599 }
1600
1601 #[must_use]
1602 pub const fn cache_sql_compiled_command_miss_surface(&self) -> u64 {
1603 self.cache_sql_compiled_command_miss_surface
1604 }
1605
1606 #[must_use]
1607 pub const fn schema_reconcile_checks(&self) -> u64 {
1608 self.schema_reconcile_checks
1609 }
1610
1611 #[must_use]
1612 pub const fn schema_reconcile_exact_match(&self) -> u64 {
1613 self.schema_reconcile_exact_match
1614 }
1615
1616 #[must_use]
1617 pub const fn schema_reconcile_first_create(&self) -> u64 {
1618 self.schema_reconcile_first_create
1619 }
1620
1621 #[must_use]
1622 pub const fn schema_reconcile_latest_snapshot_corrupt(&self) -> u64 {
1623 self.schema_reconcile_latest_snapshot_corrupt
1624 }
1625
1626 #[must_use]
1627 pub const fn schema_reconcile_rejected_field_slot(&self) -> u64 {
1628 self.schema_reconcile_rejected_field_slot
1629 }
1630
1631 #[must_use]
1632 pub const fn schema_reconcile_rejected_other(&self) -> u64 {
1633 self.schema_reconcile_rejected_other
1634 }
1635
1636 #[must_use]
1637 pub const fn schema_reconcile_rejected_row_layout(&self) -> u64 {
1638 self.schema_reconcile_rejected_row_layout
1639 }
1640
1641 #[must_use]
1642 pub const fn schema_reconcile_rejected_schema_version(&self) -> u64 {
1643 self.schema_reconcile_rejected_schema_version
1644 }
1645
1646 #[must_use]
1647 pub const fn schema_reconcile_store_write_error(&self) -> u64 {
1648 self.schema_reconcile_store_write_error
1649 }
1650
1651 #[must_use]
1652 pub const fn schema_transition_checks(&self) -> u64 {
1653 self.schema_transition_checks
1654 }
1655
1656 #[must_use]
1657 pub const fn schema_transition_exact_match(&self) -> u64 {
1658 self.schema_transition_exact_match
1659 }
1660
1661 #[must_use]
1662 pub const fn schema_transition_rejected_entity_identity(&self) -> u64 {
1663 self.schema_transition_rejected_entity_identity
1664 }
1665
1666 #[must_use]
1667 pub const fn schema_transition_rejected_field_contract(&self) -> u64 {
1668 self.schema_transition_rejected_field_contract
1669 }
1670
1671 #[must_use]
1672 pub const fn schema_transition_rejected_field_slot(&self) -> u64 {
1673 self.schema_transition_rejected_field_slot
1674 }
1675
1676 #[must_use]
1677 pub const fn schema_transition_rejected_row_layout(&self) -> u64 {
1678 self.schema_transition_rejected_row_layout
1679 }
1680
1681 #[must_use]
1682 pub const fn schema_transition_rejected_schema_version(&self) -> u64 {
1683 self.schema_transition_rejected_schema_version
1684 }
1685
1686 #[must_use]
1687 pub const fn schema_transition_rejected_snapshot(&self) -> u64 {
1688 self.schema_transition_rejected_snapshot
1689 }
1690
1691 #[must_use]
1692 pub const fn schema_store_snapshots(&self) -> u64 {
1693 self.schema_store_snapshots
1694 }
1695
1696 #[must_use]
1697 pub const fn schema_store_encoded_bytes(&self) -> u64 {
1698 self.schema_store_encoded_bytes
1699 }
1700
1701 #[must_use]
1702 pub const fn schema_store_latest_snapshot_bytes(&self) -> u64 {
1703 self.schema_store_latest_snapshot_bytes
1704 }
1705
1706 #[must_use]
1707 pub const fn accepted_schema_fields(&self) -> u64 {
1708 self.accepted_schema_fields
1709 }
1710
1711 #[must_use]
1712 pub const fn accepted_schema_nested_leaf_facts(&self) -> u64 {
1713 self.accepted_schema_nested_leaf_facts
1714 }
1715
1716 #[must_use]
1717 pub const fn sql_compile_rejects(&self) -> u64 {
1718 self.sql_compile_rejects
1719 }
1720
1721 #[must_use]
1722 pub const fn sql_compile_reject_cache_key(&self) -> u64 {
1723 self.sql_compile_reject_cache_key
1724 }
1725
1726 #[must_use]
1727 pub const fn sql_compile_reject_parse(&self) -> u64 {
1728 self.sql_compile_reject_parse
1729 }
1730
1731 #[must_use]
1732 pub const fn sql_compile_reject_semantic(&self) -> u64 {
1733 self.sql_compile_reject_semantic
1734 }
1735
1736 #[must_use]
1737 pub const fn plan_index(&self) -> u64 {
1738 self.plan_index
1739 }
1740
1741 #[must_use]
1742 pub const fn plan_keys(&self) -> u64 {
1743 self.plan_keys
1744 }
1745
1746 #[must_use]
1747 pub const fn plan_range(&self) -> u64 {
1748 self.plan_range
1749 }
1750
1751 #[must_use]
1752 pub const fn plan_full_scan(&self) -> u64 {
1753 self.plan_full_scan
1754 }
1755
1756 #[must_use]
1757 pub const fn plan_by_key(&self) -> u64 {
1758 self.plan_by_key
1759 }
1760
1761 #[must_use]
1762 pub const fn plan_by_keys(&self) -> u64 {
1763 self.plan_by_keys
1764 }
1765
1766 #[must_use]
1767 pub const fn plan_key_range(&self) -> u64 {
1768 self.plan_key_range
1769 }
1770
1771 #[must_use]
1772 pub const fn plan_index_prefix(&self) -> u64 {
1773 self.plan_index_prefix
1774 }
1775
1776 #[must_use]
1777 pub const fn plan_index_multi_lookup(&self) -> u64 {
1778 self.plan_index_multi_lookup
1779 }
1780
1781 #[must_use]
1782 pub const fn plan_index_range(&self) -> u64 {
1783 self.plan_index_range
1784 }
1785
1786 #[must_use]
1787 pub const fn plan_explicit_full_scan(&self) -> u64 {
1788 self.plan_explicit_full_scan
1789 }
1790
1791 #[must_use]
1792 pub const fn plan_union(&self) -> u64 {
1793 self.plan_union
1794 }
1795
1796 #[must_use]
1797 pub const fn plan_intersection(&self) -> u64 {
1798 self.plan_intersection
1799 }
1800
1801 #[must_use]
1802 pub const fn plan_grouped_hash_materialized(&self) -> u64 {
1803 self.plan_grouped_hash_materialized
1804 }
1805
1806 #[must_use]
1807 pub const fn plan_grouped_ordered_materialized(&self) -> u64 {
1808 self.plan_grouped_ordered_materialized
1809 }
1810
1811 #[must_use]
1812 pub const fn plan_choice_conflicting_primary_key_children_access_preferred(&self) -> u64 {
1813 self.plan_choice_conflicting_primary_key_children_access_preferred
1814 }
1815
1816 #[must_use]
1817 pub const fn plan_choice_constant_false_predicate(&self) -> u64 {
1818 self.plan_choice_constant_false_predicate
1819 }
1820
1821 #[must_use]
1822 pub const fn plan_choice_empty_child_access_preferred(&self) -> u64 {
1823 self.plan_choice_empty_child_access_preferred
1824 }
1825
1826 #[must_use]
1827 pub const fn plan_choice_full_scan_access(&self) -> u64 {
1828 self.plan_choice_full_scan_access
1829 }
1830
1831 #[must_use]
1832 pub const fn plan_choice_intent_key_access_override(&self) -> u64 {
1833 self.plan_choice_intent_key_access_override
1834 }
1835
1836 #[must_use]
1837 pub const fn plan_choice_limit_zero_window(&self) -> u64 {
1838 self.plan_choice_limit_zero_window
1839 }
1840
1841 #[must_use]
1842 pub const fn plan_choice_non_index_access(&self) -> u64 {
1843 self.plan_choice_non_index_access
1844 }
1845
1846 #[must_use]
1847 pub const fn plan_choice_planner_composite_non_index(&self) -> u64 {
1848 self.plan_choice_planner_composite_non_index
1849 }
1850
1851 #[must_use]
1852 pub const fn plan_choice_planner_full_scan_fallback(&self) -> u64 {
1853 self.plan_choice_planner_full_scan_fallback
1854 }
1855
1856 #[must_use]
1857 pub const fn plan_choice_planner_key_set_access(&self) -> u64 {
1858 self.plan_choice_planner_key_set_access
1859 }
1860
1861 #[must_use]
1862 pub const fn plan_choice_planner_primary_key_lookup(&self) -> u64 {
1863 self.plan_choice_planner_primary_key_lookup
1864 }
1865
1866 #[must_use]
1867 pub const fn plan_choice_planner_primary_key_range(&self) -> u64 {
1868 self.plan_choice_planner_primary_key_range
1869 }
1870
1871 #[must_use]
1872 pub const fn plan_choice_required_order_primary_key_range_preferred(&self) -> u64 {
1873 self.plan_choice_required_order_primary_key_range_preferred
1874 }
1875
1876 #[must_use]
1877 pub const fn plan_choice_singleton_primary_key_child_access_preferred(&self) -> u64 {
1878 self.plan_choice_singleton_primary_key_child_access_preferred
1879 }
1880
1881 #[must_use]
1882 pub const fn prepared_shape_already_finalized(&self) -> u64 {
1883 self.prepared_shape_already_finalized
1884 }
1885
1886 #[must_use]
1887 pub const fn prepared_shape_generated_fallback(&self) -> u64 {
1888 self.prepared_shape_generated_fallback
1889 }
1890
1891 #[must_use]
1892 pub const fn rows_loaded(&self) -> u64 {
1893 self.rows_loaded
1894 }
1895
1896 #[must_use]
1897 pub const fn rows_saved(&self) -> u64 {
1898 self.rows_saved
1899 }
1900
1901 #[must_use]
1902 pub const fn rows_inserted(&self) -> u64 {
1903 self.rows_inserted
1904 }
1905
1906 #[must_use]
1907 pub const fn rows_updated(&self) -> u64 {
1908 self.rows_updated
1909 }
1910
1911 #[must_use]
1912 pub const fn rows_replaced(&self) -> u64 {
1913 self.rows_replaced
1914 }
1915
1916 #[must_use]
1917 pub const fn rows_scanned(&self) -> u64 {
1918 self.rows_scanned
1919 }
1920
1921 #[must_use]
1922 pub const fn rows_filtered(&self) -> u64 {
1923 self.rows_filtered
1924 }
1925
1926 #[must_use]
1927 pub const fn rows_aggregated(&self) -> u64 {
1928 self.rows_aggregated
1929 }
1930
1931 #[must_use]
1932 pub const fn rows_emitted(&self) -> u64 {
1933 self.rows_emitted
1934 }
1935
1936 #[must_use]
1937 pub const fn load_candidate_rows_scanned(&self) -> u64 {
1938 self.load_candidate_rows_scanned
1939 }
1940
1941 #[must_use]
1942 pub const fn load_candidate_rows_filtered(&self) -> u64 {
1943 self.load_candidate_rows_filtered
1944 }
1945
1946 #[must_use]
1947 pub const fn load_result_rows_emitted(&self) -> u64 {
1948 self.load_result_rows_emitted
1949 }
1950
1951 #[must_use]
1952 pub const fn rows_deleted(&self) -> u64 {
1953 self.rows_deleted
1954 }
1955
1956 #[must_use]
1957 pub const fn sql_insert_calls(&self) -> u64 {
1958 self.sql_insert_calls
1959 }
1960
1961 #[must_use]
1962 pub const fn sql_insert_select_calls(&self) -> u64 {
1963 self.sql_insert_select_calls
1964 }
1965
1966 #[must_use]
1967 pub const fn sql_update_calls(&self) -> u64 {
1968 self.sql_update_calls
1969 }
1970
1971 #[must_use]
1972 pub const fn sql_delete_calls(&self) -> u64 {
1973 self.sql_delete_calls
1974 }
1975
1976 #[must_use]
1977 pub const fn sql_write_matched_rows(&self) -> u64 {
1978 self.sql_write_matched_rows
1979 }
1980
1981 #[must_use]
1982 pub const fn sql_write_mutated_rows(&self) -> u64 {
1983 self.sql_write_mutated_rows
1984 }
1985
1986 #[must_use]
1987 pub const fn sql_write_returning_rows(&self) -> u64 {
1988 self.sql_write_returning_rows
1989 }
1990
1991 #[must_use]
1992 pub const fn sql_write_error_insert(&self) -> u64 {
1993 self.sql_write_error_insert
1994 }
1995
1996 #[must_use]
1997 pub const fn sql_write_error_insert_select(&self) -> u64 {
1998 self.sql_write_error_insert_select
1999 }
2000
2001 #[must_use]
2002 pub const fn sql_write_error_update(&self) -> u64 {
2003 self.sql_write_error_update
2004 }
2005
2006 #[must_use]
2007 pub const fn sql_write_error_delete(&self) -> u64 {
2008 self.sql_write_error_delete
2009 }
2010
2011 #[must_use]
2012 pub const fn sql_write_error_corruption(&self) -> u64 {
2013 self.sql_write_error_corruption
2014 }
2015
2016 #[must_use]
2017 pub const fn sql_write_error_incompatible_persisted_format(&self) -> u64 {
2018 self.sql_write_error_incompatible_persisted_format
2019 }
2020
2021 #[must_use]
2022 pub const fn sql_write_error_not_found(&self) -> u64 {
2023 self.sql_write_error_not_found
2024 }
2025
2026 #[must_use]
2027 pub const fn sql_write_error_internal(&self) -> u64 {
2028 self.sql_write_error_internal
2029 }
2030
2031 #[must_use]
2032 pub const fn sql_write_error_conflict(&self) -> u64 {
2033 self.sql_write_error_conflict
2034 }
2035
2036 #[must_use]
2037 pub const fn sql_write_error_unsupported(&self) -> u64 {
2038 self.sql_write_error_unsupported
2039 }
2040
2041 #[must_use]
2042 pub const fn sql_write_error_invariant_violation(&self) -> u64 {
2043 self.sql_write_error_invariant_violation
2044 }
2045
2046 #[must_use]
2047 pub const fn index_inserts(&self) -> u64 {
2048 self.index_inserts
2049 }
2050
2051 #[must_use]
2052 pub const fn index_removes(&self) -> u64 {
2053 self.index_removes
2054 }
2055
2056 #[must_use]
2057 pub const fn reverse_index_inserts(&self) -> u64 {
2058 self.reverse_index_inserts
2059 }
2060
2061 #[must_use]
2062 pub const fn reverse_index_removes(&self) -> u64 {
2063 self.reverse_index_removes
2064 }
2065
2066 #[must_use]
2067 pub const fn relation_reverse_lookups(&self) -> u64 {
2068 self.relation_reverse_lookups
2069 }
2070
2071 #[must_use]
2072 pub const fn relation_delete_blocks(&self) -> u64 {
2073 self.relation_delete_blocks
2074 }
2075
2076 #[must_use]
2077 pub const fn write_rows_touched(&self) -> u64 {
2078 self.write_rows_touched
2079 }
2080
2081 #[must_use]
2082 pub const fn write_index_entries_changed(&self) -> u64 {
2083 self.write_index_entries_changed
2084 }
2085
2086 #[must_use]
2087 pub const fn write_reverse_index_entries_changed(&self) -> u64 {
2088 self.write_reverse_index_entries_changed
2089 }
2090
2091 #[must_use]
2092 pub const fn write_relation_checks(&self) -> u64 {
2093 self.write_relation_checks
2094 }
2095
2096 #[must_use]
2097 pub const fn unique_violations(&self) -> u64 {
2098 self.unique_violations
2099 }
2100
2101 #[must_use]
2102 pub const fn non_atomic_partial_commits(&self) -> u64 {
2103 self.non_atomic_partial_commits
2104 }
2105
2106 #[must_use]
2107 pub const fn non_atomic_partial_rows_committed(&self) -> u64 {
2108 self.non_atomic_partial_rows_committed
2109 }
2110
2111 #[must_use]
2113 pub const fn load_selectivity_ratio(&self) -> Option<MetricRatio> {
2114 ratio(
2115 self.load_result_rows_emitted,
2116 self.load_candidate_rows_scanned,
2117 )
2118 }
2119
2120 #[must_use]
2122 pub const fn load_filter_ratio(&self) -> Option<MetricRatio> {
2123 ratio(
2124 self.load_candidate_rows_filtered,
2125 self.load_candidate_rows_scanned,
2126 )
2127 }
2128
2129 #[must_use]
2131 pub const fn sql_write_mutation_ratio(&self) -> Option<MetricRatio> {
2132 ratio(self.sql_write_mutated_rows, self.sql_write_matched_rows)
2133 }
2134
2135 #[must_use]
2137 pub const fn sql_write_returning_ratio(&self) -> Option<MetricRatio> {
2138 ratio(self.sql_write_returning_rows, self.sql_write_mutated_rows)
2139 }
2140
2141 #[must_use]
2143 pub const fn write_index_entries_per_row(&self) -> Option<MetricRatio> {
2144 ratio(self.write_index_entries_changed, self.write_rows_touched)
2145 }
2146
2147 #[must_use]
2149 pub const fn write_reverse_index_entries_per_row(&self) -> Option<MetricRatio> {
2150 ratio(
2151 self.write_reverse_index_entries_changed,
2152 self.write_rows_touched,
2153 )
2154 }
2155
2156 #[must_use]
2158 pub const fn write_relation_checks_per_row(&self) -> Option<MetricRatio> {
2159 ratio(self.write_relation_checks, self.write_rows_touched)
2160 }
2161
2162 #[expect(clippy::too_many_lines)]
2165 const fn activity_score(&self) -> u64 {
2166 self.load_calls
2167 .saturating_add(self.save_calls)
2168 .saturating_add(self.delete_calls)
2169 .saturating_add(self.save_insert_calls)
2170 .saturating_add(self.save_update_calls)
2171 .saturating_add(self.save_replace_calls)
2172 .saturating_add(self.exec_success)
2173 .saturating_add(self.exec_error_corruption)
2174 .saturating_add(self.exec_error_incompatible_persisted_format)
2175 .saturating_add(self.exec_error_not_found)
2176 .saturating_add(self.exec_error_internal)
2177 .saturating_add(self.exec_error_conflict)
2178 .saturating_add(self.exec_error_unsupported)
2179 .saturating_add(self.exec_error_invariant_violation)
2180 .saturating_add(self.exec_aborted)
2181 .saturating_add(self.cache_shared_query_plan_hits)
2182 .saturating_add(self.cache_shared_query_plan_misses)
2183 .saturating_add(self.cache_shared_query_plan_inserts)
2184 .saturating_add(self.cache_shared_query_plan_miss_cold)
2185 .saturating_add(self.cache_shared_query_plan_miss_distinct_key)
2186 .saturating_add(self.cache_shared_query_plan_miss_method_version)
2187 .saturating_add(self.cache_shared_query_plan_miss_schema_fingerprint)
2188 .saturating_add(self.cache_shared_query_plan_miss_visibility)
2189 .saturating_add(self.cache_sql_compiled_command_hits)
2190 .saturating_add(self.cache_sql_compiled_command_misses)
2191 .saturating_add(self.cache_sql_compiled_command_inserts)
2192 .saturating_add(self.cache_sql_compiled_command_miss_cold)
2193 .saturating_add(self.cache_sql_compiled_command_miss_distinct_key)
2194 .saturating_add(self.cache_sql_compiled_command_miss_method_version)
2195 .saturating_add(self.cache_sql_compiled_command_miss_schema_fingerprint)
2196 .saturating_add(self.cache_sql_compiled_command_miss_surface)
2197 .saturating_add(self.schema_reconcile_checks)
2198 .saturating_add(self.schema_reconcile_exact_match)
2199 .saturating_add(self.schema_reconcile_first_create)
2200 .saturating_add(self.schema_reconcile_latest_snapshot_corrupt)
2201 .saturating_add(self.schema_reconcile_rejected_field_slot)
2202 .saturating_add(self.schema_reconcile_rejected_other)
2203 .saturating_add(self.schema_reconcile_rejected_row_layout)
2204 .saturating_add(self.schema_reconcile_rejected_schema_version)
2205 .saturating_add(self.schema_reconcile_store_write_error)
2206 .saturating_add(self.schema_transition_checks)
2207 .saturating_add(self.schema_transition_exact_match)
2208 .saturating_add(self.schema_transition_rejected_entity_identity)
2209 .saturating_add(self.schema_transition_rejected_field_contract)
2210 .saturating_add(self.schema_transition_rejected_field_slot)
2211 .saturating_add(self.schema_transition_rejected_row_layout)
2212 .saturating_add(self.schema_transition_rejected_schema_version)
2213 .saturating_add(self.schema_transition_rejected_snapshot)
2214 .saturating_add(self.schema_store_snapshots)
2215 .saturating_add(self.schema_store_encoded_bytes)
2216 .saturating_add(self.schema_store_latest_snapshot_bytes)
2217 .saturating_add(self.accepted_schema_fields)
2218 .saturating_add(self.accepted_schema_nested_leaf_facts)
2219 .saturating_add(self.sql_compile_rejects)
2220 .saturating_add(self.sql_compile_reject_cache_key)
2221 .saturating_add(self.sql_compile_reject_parse)
2222 .saturating_add(self.sql_compile_reject_semantic)
2223 .saturating_add(self.plan_index)
2224 .saturating_add(self.plan_keys)
2225 .saturating_add(self.plan_range)
2226 .saturating_add(self.plan_full_scan)
2227 .saturating_add(self.plan_by_key)
2228 .saturating_add(self.plan_by_keys)
2229 .saturating_add(self.plan_key_range)
2230 .saturating_add(self.plan_index_prefix)
2231 .saturating_add(self.plan_index_multi_lookup)
2232 .saturating_add(self.plan_index_range)
2233 .saturating_add(self.plan_explicit_full_scan)
2234 .saturating_add(self.plan_union)
2235 .saturating_add(self.plan_intersection)
2236 .saturating_add(self.plan_grouped_hash_materialized)
2237 .saturating_add(self.plan_grouped_ordered_materialized)
2238 .saturating_add(self.plan_choice_conflicting_primary_key_children_access_preferred)
2239 .saturating_add(self.plan_choice_constant_false_predicate)
2240 .saturating_add(self.plan_choice_empty_child_access_preferred)
2241 .saturating_add(self.plan_choice_full_scan_access)
2242 .saturating_add(self.plan_choice_intent_key_access_override)
2243 .saturating_add(self.plan_choice_limit_zero_window)
2244 .saturating_add(self.plan_choice_non_index_access)
2245 .saturating_add(self.plan_choice_planner_composite_non_index)
2246 .saturating_add(self.plan_choice_planner_full_scan_fallback)
2247 .saturating_add(self.plan_choice_planner_key_set_access)
2248 .saturating_add(self.plan_choice_planner_primary_key_lookup)
2249 .saturating_add(self.plan_choice_planner_primary_key_range)
2250 .saturating_add(self.plan_choice_required_order_primary_key_range_preferred)
2251 .saturating_add(self.plan_choice_singleton_primary_key_child_access_preferred)
2252 .saturating_add(self.prepared_shape_already_finalized)
2253 .saturating_add(self.prepared_shape_generated_fallback)
2254 .saturating_add(self.rows_loaded)
2255 .saturating_add(self.rows_saved)
2256 .saturating_add(self.rows_inserted)
2257 .saturating_add(self.rows_updated)
2258 .saturating_add(self.rows_replaced)
2259 .saturating_add(self.rows_scanned)
2260 .saturating_add(self.rows_filtered)
2261 .saturating_add(self.rows_aggregated)
2262 .saturating_add(self.rows_emitted)
2263 .saturating_add(self.load_candidate_rows_scanned)
2264 .saturating_add(self.load_candidate_rows_filtered)
2265 .saturating_add(self.load_result_rows_emitted)
2266 .saturating_add(self.rows_deleted)
2267 .saturating_add(self.sql_insert_calls)
2268 .saturating_add(self.sql_insert_select_calls)
2269 .saturating_add(self.sql_update_calls)
2270 .saturating_add(self.sql_delete_calls)
2271 .saturating_add(self.sql_write_matched_rows)
2272 .saturating_add(self.sql_write_mutated_rows)
2273 .saturating_add(self.sql_write_returning_rows)
2274 .saturating_add(self.sql_write_error_insert)
2275 .saturating_add(self.sql_write_error_insert_select)
2276 .saturating_add(self.sql_write_error_update)
2277 .saturating_add(self.sql_write_error_delete)
2278 .saturating_add(self.sql_write_error_corruption)
2279 .saturating_add(self.sql_write_error_incompatible_persisted_format)
2280 .saturating_add(self.sql_write_error_not_found)
2281 .saturating_add(self.sql_write_error_internal)
2282 .saturating_add(self.sql_write_error_conflict)
2283 .saturating_add(self.sql_write_error_unsupported)
2284 .saturating_add(self.sql_write_error_invariant_violation)
2285 .saturating_add(self.index_inserts)
2286 .saturating_add(self.index_removes)
2287 .saturating_add(self.reverse_index_inserts)
2288 .saturating_add(self.reverse_index_removes)
2289 .saturating_add(self.relation_reverse_lookups)
2290 .saturating_add(self.relation_delete_blocks)
2291 .saturating_add(self.write_rows_touched)
2292 .saturating_add(self.write_index_entries_changed)
2293 .saturating_add(self.write_reverse_index_entries_changed)
2294 .saturating_add(self.write_relation_checks)
2295 .saturating_add(self.unique_violations)
2296 .saturating_add(self.non_atomic_partial_commits)
2297 .saturating_add(self.non_atomic_partial_rows_committed)
2298 }
2299}
2300
2301#[expect(clippy::too_many_lines)]
2306fn entity_summary_from_counters(path: &str, ops: &EntityCounters) -> EntitySummary {
2307 EntitySummary {
2308 path: path.to_string(),
2309 load_calls: ops.load_calls,
2310 save_calls: ops.save_calls,
2311 delete_calls: ops.delete_calls,
2312 save_insert_calls: ops.save_insert_calls,
2313 save_update_calls: ops.save_update_calls,
2314 save_replace_calls: ops.save_replace_calls,
2315 exec_success: ops.exec_success,
2316 exec_error_corruption: ops.exec_error_corruption,
2317 exec_error_incompatible_persisted_format: ops.exec_error_incompatible_persisted_format,
2318 exec_error_not_found: ops.exec_error_not_found,
2319 exec_error_internal: ops.exec_error_internal,
2320 exec_error_conflict: ops.exec_error_conflict,
2321 exec_error_unsupported: ops.exec_error_unsupported,
2322 exec_error_invariant_violation: ops.exec_error_invariant_violation,
2323 exec_aborted: ops.exec_aborted,
2324 cache_shared_query_plan_hits: ops.cache_shared_query_plan_hits,
2325 cache_shared_query_plan_misses: ops.cache_shared_query_plan_misses,
2326 cache_shared_query_plan_inserts: ops.cache_shared_query_plan_inserts,
2327 cache_shared_query_plan_miss_cold: ops.cache_shared_query_plan_miss_cold,
2328 cache_shared_query_plan_miss_distinct_key: ops.cache_shared_query_plan_miss_distinct_key,
2329 cache_shared_query_plan_miss_method_version: ops
2330 .cache_shared_query_plan_miss_method_version,
2331 cache_shared_query_plan_miss_schema_fingerprint: ops
2332 .cache_shared_query_plan_miss_schema_fingerprint,
2333 cache_shared_query_plan_miss_visibility: ops.cache_shared_query_plan_miss_visibility,
2334 cache_sql_compiled_command_hits: ops.cache_sql_compiled_command_hits,
2335 cache_sql_compiled_command_misses: ops.cache_sql_compiled_command_misses,
2336 cache_sql_compiled_command_inserts: ops.cache_sql_compiled_command_inserts,
2337 cache_sql_compiled_command_miss_cold: ops.cache_sql_compiled_command_miss_cold,
2338 cache_sql_compiled_command_miss_distinct_key: ops
2339 .cache_sql_compiled_command_miss_distinct_key,
2340 cache_sql_compiled_command_miss_method_version: ops
2341 .cache_sql_compiled_command_miss_method_version,
2342 cache_sql_compiled_command_miss_schema_fingerprint: ops
2343 .cache_sql_compiled_command_miss_schema_fingerprint,
2344 cache_sql_compiled_command_miss_surface: ops.cache_sql_compiled_command_miss_surface,
2345 schema_reconcile_checks: ops.schema_reconcile_checks,
2346 schema_reconcile_exact_match: ops.schema_reconcile_exact_match,
2347 schema_reconcile_first_create: ops.schema_reconcile_first_create,
2348 schema_reconcile_latest_snapshot_corrupt: ops.schema_reconcile_latest_snapshot_corrupt,
2349 schema_reconcile_rejected_field_slot: ops.schema_reconcile_rejected_field_slot,
2350 schema_reconcile_rejected_other: ops.schema_reconcile_rejected_other,
2351 schema_reconcile_rejected_row_layout: ops.schema_reconcile_rejected_row_layout,
2352 schema_reconcile_rejected_schema_version: ops.schema_reconcile_rejected_schema_version,
2353 schema_reconcile_store_write_error: ops.schema_reconcile_store_write_error,
2354 schema_transition_checks: ops.schema_transition_checks,
2355 schema_transition_exact_match: ops.schema_transition_exact_match,
2356 schema_transition_rejected_entity_identity: ops.schema_transition_rejected_entity_identity,
2357 schema_transition_rejected_field_contract: ops.schema_transition_rejected_field_contract,
2358 schema_transition_rejected_field_slot: ops.schema_transition_rejected_field_slot,
2359 schema_transition_rejected_row_layout: ops.schema_transition_rejected_row_layout,
2360 schema_transition_rejected_schema_version: ops.schema_transition_rejected_schema_version,
2361 schema_transition_rejected_snapshot: ops.schema_transition_rejected_snapshot,
2362 schema_store_snapshots: ops.schema_store_snapshots,
2363 schema_store_encoded_bytes: ops.schema_store_encoded_bytes,
2364 schema_store_latest_snapshot_bytes: ops.schema_store_latest_snapshot_bytes,
2365 accepted_schema_fields: ops.accepted_schema_fields,
2366 accepted_schema_nested_leaf_facts: ops.accepted_schema_nested_leaf_facts,
2367 sql_compile_rejects: ops.sql_compile_rejects,
2368 sql_compile_reject_cache_key: ops.sql_compile_reject_cache_key,
2369 sql_compile_reject_parse: ops.sql_compile_reject_parse,
2370 sql_compile_reject_semantic: ops.sql_compile_reject_semantic,
2371 plan_index: ops.plan_index,
2372 plan_keys: ops.plan_keys,
2373 plan_range: ops.plan_range,
2374 plan_full_scan: ops.plan_full_scan,
2375 plan_by_key: ops.plan_by_key,
2376 plan_by_keys: ops.plan_by_keys,
2377 plan_key_range: ops.plan_key_range,
2378 plan_index_prefix: ops.plan_index_prefix,
2379 plan_index_multi_lookup: ops.plan_index_multi_lookup,
2380 plan_index_range: ops.plan_index_range,
2381 plan_explicit_full_scan: ops.plan_explicit_full_scan,
2382 plan_union: ops.plan_union,
2383 plan_intersection: ops.plan_intersection,
2384 plan_grouped_hash_materialized: ops.plan_grouped_hash_materialized,
2385 plan_grouped_ordered_materialized: ops.plan_grouped_ordered_materialized,
2386 plan_choice_conflicting_primary_key_children_access_preferred: ops
2387 .plan_choice_conflicting_primary_key_children_access_preferred,
2388 plan_choice_constant_false_predicate: ops.plan_choice_constant_false_predicate,
2389 plan_choice_empty_child_access_preferred: ops.plan_choice_empty_child_access_preferred,
2390 plan_choice_full_scan_access: ops.plan_choice_full_scan_access,
2391 plan_choice_intent_key_access_override: ops.plan_choice_intent_key_access_override,
2392 plan_choice_limit_zero_window: ops.plan_choice_limit_zero_window,
2393 plan_choice_non_index_access: ops.plan_choice_non_index_access,
2394 plan_choice_planner_composite_non_index: ops.plan_choice_planner_composite_non_index,
2395 plan_choice_planner_full_scan_fallback: ops.plan_choice_planner_full_scan_fallback,
2396 plan_choice_planner_key_set_access: ops.plan_choice_planner_key_set_access,
2397 plan_choice_planner_primary_key_lookup: ops.plan_choice_planner_primary_key_lookup,
2398 plan_choice_planner_primary_key_range: ops.plan_choice_planner_primary_key_range,
2399 plan_choice_required_order_primary_key_range_preferred: ops
2400 .plan_choice_required_order_primary_key_range_preferred,
2401 plan_choice_singleton_primary_key_child_access_preferred: ops
2402 .plan_choice_singleton_primary_key_child_access_preferred,
2403 prepared_shape_already_finalized: ops.prepared_shape_already_finalized,
2404 prepared_shape_generated_fallback: ops.prepared_shape_generated_fallback,
2405 rows_loaded: ops.rows_loaded,
2406 rows_saved: ops.rows_saved,
2407 rows_inserted: ops.rows_inserted,
2408 rows_updated: ops.rows_updated,
2409 rows_replaced: ops.rows_replaced,
2410 rows_scanned: ops.rows_scanned,
2411 rows_filtered: ops.rows_filtered,
2412 rows_aggregated: ops.rows_aggregated,
2413 rows_emitted: ops.rows_emitted,
2414 load_candidate_rows_scanned: ops.load_candidate_rows_scanned,
2415 load_candidate_rows_filtered: ops.load_candidate_rows_filtered,
2416 load_result_rows_emitted: ops.load_result_rows_emitted,
2417 rows_deleted: ops.rows_deleted,
2418 sql_insert_calls: ops.sql_insert_calls,
2419 sql_insert_select_calls: ops.sql_insert_select_calls,
2420 sql_update_calls: ops.sql_update_calls,
2421 sql_delete_calls: ops.sql_delete_calls,
2422 sql_write_matched_rows: ops.sql_write_matched_rows,
2423 sql_write_mutated_rows: ops.sql_write_mutated_rows,
2424 sql_write_returning_rows: ops.sql_write_returning_rows,
2425 sql_write_error_insert: ops.sql_write_error_insert,
2426 sql_write_error_insert_select: ops.sql_write_error_insert_select,
2427 sql_write_error_update: ops.sql_write_error_update,
2428 sql_write_error_delete: ops.sql_write_error_delete,
2429 sql_write_error_corruption: ops.sql_write_error_corruption,
2430 sql_write_error_incompatible_persisted_format: ops
2431 .sql_write_error_incompatible_persisted_format,
2432 sql_write_error_not_found: ops.sql_write_error_not_found,
2433 sql_write_error_internal: ops.sql_write_error_internal,
2434 sql_write_error_conflict: ops.sql_write_error_conflict,
2435 sql_write_error_unsupported: ops.sql_write_error_unsupported,
2436 sql_write_error_invariant_violation: ops.sql_write_error_invariant_violation,
2437 index_inserts: ops.index_inserts,
2438 index_removes: ops.index_removes,
2439 reverse_index_inserts: ops.reverse_index_inserts,
2440 reverse_index_removes: ops.reverse_index_removes,
2441 relation_reverse_lookups: ops.relation_reverse_lookups,
2442 relation_delete_blocks: ops.relation_delete_blocks,
2443 write_rows_touched: ops.write_rows_touched,
2444 write_index_entries_changed: ops.write_index_entries_changed,
2445 write_reverse_index_entries_changed: ops.write_reverse_index_entries_changed,
2446 write_relation_checks: ops.write_relation_checks,
2447 unique_violations: ops.unique_violations,
2448 non_atomic_partial_commits: ops.non_atomic_partial_commits,
2449 non_atomic_partial_rows_committed: ops.non_atomic_partial_rows_committed,
2450 }
2451}
2452
2453#[must_use]
2463pub(super) fn report_window_start(window_start_ms: Option<u64>) -> EventReport {
2464 let snap = with_state(Clone::clone);
2465 if let Some(requested_window_start_ms) = window_start_ms
2466 && requested_window_start_ms > snap.window_start_ms
2467 {
2468 return EventReport::new(
2469 None,
2470 Vec::new(),
2471 false,
2472 window_start_ms,
2473 snap.window_start_ms,
2474 );
2475 }
2476
2477 let mut entity_counters: Vec<EntitySummary> = Vec::new();
2478 for (path, ops) in &snap.entities {
2479 entity_counters.push(entity_summary_from_counters(path, ops));
2480 }
2481
2482 entity_counters.sort_by(|a, b| {
2483 b.activity_score()
2484 .cmp(&a.activity_score())
2485 .then_with(|| b.rows_loaded.cmp(&a.rows_loaded))
2486 .then_with(|| b.rows_saved.cmp(&a.rows_saved))
2487 .then_with(|| b.rows_scanned.cmp(&a.rows_scanned))
2488 .then_with(|| b.rows_deleted.cmp(&a.rows_deleted))
2489 .then_with(|| a.path.cmp(&b.path))
2490 });
2491
2492 EventReport::new(
2493 Some(EventCounters::new(
2494 snap.ops.clone(),
2495 snap.perf.clone(),
2496 snap.window_start_ms,
2497 now_millis(),
2498 )),
2499 entity_counters,
2500 true,
2501 window_start_ms,
2502 snap.window_start_ms,
2503 )
2504}