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