1use crate::runtime::now_millis;
11use candid::CandidType;
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_numerator_and_denominator(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
1254pub mod compact_metric_code {
1260 pub const LOAD_CALLS: u16 = 1;
1262 pub const SAVE_CALLS: u16 = 2;
1264 pub const DELETE_CALLS: u16 = 3;
1266 pub const EXEC_SUCCESS: u16 = 4;
1268 pub const EXEC_ERRORS: u16 = 5;
1270 pub const EXEC_ABORTED: u16 = 6;
1272 pub const ROWS_LOADED: u16 = 7;
1274 pub const ROWS_SAVED: u16 = 8;
1276 pub const ROWS_DELETED: u16 = 9;
1278 pub const ROWS_SCANNED: u16 = 10;
1280 pub const ROWS_FILTERED: u16 = 11;
1282 pub const ROWS_EMITTED: u16 = 12;
1284 pub const SQL_INSERT_CALLS: u16 = 13;
1286 pub const SQL_INSERT_SELECT_CALLS: u16 = 14;
1288 pub const SQL_UPDATE_CALLS: u16 = 15;
1290 pub const SQL_DELETE_CALLS: u16 = 16;
1292 pub const SQL_WRITE_MATCHED_ROWS: u16 = 17;
1294 pub const SQL_WRITE_MUTATED_ROWS: u16 = 18;
1296 pub const SQL_WRITE_RETURNING_ROWS: u16 = 19;
1298 pub const CACHE_SHARED_QUERY_PLAN_HITS: u16 = 20;
1300 pub const CACHE_SHARED_QUERY_PLAN_MISSES: u16 = 21;
1302 pub const CACHE_SQL_COMPILED_COMMAND_HITS: u16 = 22;
1304 pub const CACHE_SQL_COMPILED_COMMAND_MISSES: u16 = 23;
1306}
1307
1308#[cfg_attr(doc, doc = "CompactMetric\n\nCompact metrics counter.")]
1309#[derive(CandidType, Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq)]
1310pub struct CompactMetric {
1311 code: u16,
1312 value: u64,
1313}
1314
1315impl CompactMetric {
1316 #[must_use]
1317 pub(crate) const fn new(code: u16, value: u64) -> Self {
1318 Self { code, value }
1319 }
1320
1321 #[must_use]
1323 pub const fn code(&self) -> u16 {
1324 self.code
1325 }
1326
1327 #[must_use]
1329 pub const fn value(&self) -> u64 {
1330 self.value
1331 }
1332
1333 #[must_use]
1335 pub const fn into_code_and_value(self) -> (u16, u64) {
1336 (self.code, self.value)
1337 }
1338}
1339
1340#[cfg_attr(doc, doc = "CompactEventCounters\n\nCompact global metrics counters.")]
1341#[derive(CandidType, Clone, Debug, Default, Deserialize, Eq, PartialEq)]
1342pub struct CompactEventCounters {
1343 metrics: Vec<CompactMetric>,
1344 window_start_ms: u64,
1345 window_end_ms: u64,
1346 window_duration_ms: u64,
1347}
1348
1349impl CompactEventCounters {
1350 #[must_use]
1351 pub(crate) const fn new(
1352 metrics: Vec<CompactMetric>,
1353 window_start_ms: u64,
1354 window_end_ms: u64,
1355 ) -> Self {
1356 Self {
1357 metrics,
1358 window_start_ms,
1359 window_end_ms,
1360 window_duration_ms: window_end_ms.saturating_sub(window_start_ms),
1361 }
1362 }
1363
1364 #[must_use]
1366 pub fn metrics(&self) -> &[CompactMetric] {
1367 &self.metrics
1368 }
1369
1370 #[must_use]
1372 pub const fn window_start_ms(&self) -> u64 {
1373 self.window_start_ms
1374 }
1375
1376 #[must_use]
1378 pub const fn window_end_ms(&self) -> u64 {
1379 self.window_end_ms
1380 }
1381
1382 #[must_use]
1384 pub const fn window_duration_ms(&self) -> u64 {
1385 self.window_duration_ms
1386 }
1387}
1388
1389#[cfg_attr(
1390 doc,
1391 doc = "CompactEntityMetrics\n\nCompact per-entity metrics counters."
1392)]
1393#[derive(CandidType, Clone, Debug, Default, Deserialize, Eq, PartialEq)]
1394pub struct CompactEntityMetrics {
1395 path: String,
1396 metrics: Vec<CompactMetric>,
1397}
1398
1399impl CompactEntityMetrics {
1400 #[must_use]
1401 pub(crate) const fn new(path: String, metrics: Vec<CompactMetric>) -> Self {
1402 Self { path, metrics }
1403 }
1404
1405 #[must_use]
1407 pub const fn path(&self) -> &str {
1408 self.path.as_str()
1409 }
1410
1411 #[must_use]
1413 pub fn metrics(&self) -> &[CompactMetric] {
1414 &self.metrics
1415 }
1416}
1417
1418#[cfg_attr(doc, doc = "CompactMetricsReport\n\nCompact metrics query payload.")]
1419#[derive(CandidType, Clone, Debug, Default, Deserialize, Eq, PartialEq)]
1420pub struct CompactMetricsReport {
1421 counters: Option<CompactEventCounters>,
1422 entity_counters: Vec<CompactEntityMetrics>,
1423 window_filter_matched: bool,
1424 requested_window_start_ms: Option<u64>,
1425 active_window_start_ms: u64,
1426}
1427
1428impl CompactMetricsReport {
1429 #[must_use]
1430 pub(crate) const fn new(
1431 counters: Option<CompactEventCounters>,
1432 entity_counters: Vec<CompactEntityMetrics>,
1433 window_filter_matched: bool,
1434 requested_window_start_ms: Option<u64>,
1435 active_window_start_ms: u64,
1436 ) -> Self {
1437 Self {
1438 counters,
1439 entity_counters,
1440 window_filter_matched,
1441 requested_window_start_ms,
1442 active_window_start_ms,
1443 }
1444 }
1445
1446 #[must_use]
1448 pub const fn counters(&self) -> Option<&CompactEventCounters> {
1449 self.counters.as_ref()
1450 }
1451
1452 #[must_use]
1454 pub fn entity_counters(&self) -> &[CompactEntityMetrics] {
1455 &self.entity_counters
1456 }
1457
1458 #[must_use]
1460 pub const fn window_filter_matched(&self) -> bool {
1461 self.window_filter_matched
1462 }
1463
1464 #[must_use]
1466 pub const fn requested_window_start_ms(&self) -> Option<u64> {
1467 self.requested_window_start_ms
1468 }
1469
1470 #[must_use]
1472 pub const fn active_window_start_ms(&self) -> u64 {
1473 self.active_window_start_ms
1474 }
1475}
1476
1477#[derive(CandidType, Clone, Debug, Default, Deserialize)]
1486pub struct EventCounters {
1487 pub(crate) ops: EventOps,
1488 pub(crate) perf: EventPerf,
1489 pub(crate) window_start_ms: u64,
1490 pub(crate) window_end_ms: u64,
1491 pub(crate) window_duration_ms: u64,
1492}
1493
1494impl EventCounters {
1495 #[must_use]
1496 pub(crate) const fn new(
1497 ops: EventOps,
1498 perf: EventPerf,
1499 window_start_ms: u64,
1500 window_end_ms: u64,
1501 ) -> Self {
1502 Self {
1503 ops,
1504 perf,
1505 window_start_ms,
1506 window_end_ms,
1507 window_duration_ms: window_end_ms.saturating_sub(window_start_ms),
1508 }
1509 }
1510
1511 #[must_use]
1512 pub const fn ops(&self) -> &EventOps {
1513 &self.ops
1514 }
1515
1516 #[must_use]
1517 pub const fn perf(&self) -> &EventPerf {
1518 &self.perf
1519 }
1520
1521 #[must_use]
1522 pub const fn window_start_ms(&self) -> u64 {
1523 self.window_start_ms
1524 }
1525
1526 #[must_use]
1527 pub const fn window_end_ms(&self) -> u64 {
1528 self.window_end_ms
1529 }
1530
1531 #[must_use]
1532 pub const fn window_duration_ms(&self) -> u64 {
1533 self.window_duration_ms
1534 }
1535}
1536
1537#[cfg_attr(doc, doc = "EntitySummary\n\nPer-entity metrics summary.")]
1538#[derive(CandidType, Clone, Debug, Default, Deserialize)]
1539pub struct EntitySummary {
1540 path: String,
1541 load_calls: u64,
1542 save_calls: u64,
1543 delete_calls: u64,
1544 save_insert_calls: u64,
1545 save_update_calls: u64,
1546 save_replace_calls: u64,
1547 exec_success: u64,
1548 exec_error_corruption: u64,
1549 exec_error_incompatible_persisted_format: u64,
1550 exec_error_not_found: u64,
1551 exec_error_internal: u64,
1552 exec_error_conflict: u64,
1553 exec_error_unsupported: u64,
1554 exec_error_invariant_violation: u64,
1555 exec_aborted: u64,
1556 cache_shared_query_plan_hits: u64,
1557 cache_shared_query_plan_misses: u64,
1558 cache_shared_query_plan_inserts: u64,
1559 cache_shared_query_plan_miss_cold: u64,
1560 cache_shared_query_plan_miss_distinct_key: u64,
1561 cache_shared_query_plan_miss_method_version: u64,
1562 cache_shared_query_plan_miss_schema_fingerprint: u64,
1563 cache_shared_query_plan_miss_visibility: u64,
1564 cache_sql_compiled_command_hits: u64,
1565 cache_sql_compiled_command_misses: u64,
1566 cache_sql_compiled_command_inserts: u64,
1567 cache_sql_compiled_command_miss_cold: u64,
1568 cache_sql_compiled_command_miss_distinct_key: u64,
1569 cache_sql_compiled_command_miss_method_version: u64,
1570 cache_sql_compiled_command_miss_schema_fingerprint: u64,
1571 cache_sql_compiled_command_miss_surface: u64,
1572 schema_reconcile_checks: u64,
1573 schema_reconcile_exact_match: u64,
1574 schema_reconcile_first_create: u64,
1575 schema_reconcile_latest_snapshot_corrupt: u64,
1576 schema_reconcile_rejected_field_slot: u64,
1577 schema_reconcile_rejected_other: u64,
1578 schema_reconcile_rejected_row_layout: u64,
1579 schema_reconcile_rejected_schema_version: u64,
1580 schema_reconcile_store_write_error: u64,
1581 schema_transition_checks: u64,
1582 schema_transition_append_only_nullable_fields: u64,
1583 schema_transition_exact_match: u64,
1584 schema_transition_rejected_entity_identity: u64,
1585 schema_transition_rejected_field_contract: u64,
1586 schema_transition_rejected_field_slot: u64,
1587 schema_transition_rejected_row_layout: u64,
1588 schema_transition_rejected_schema_version: u64,
1589 schema_transition_rejected_snapshot: u64,
1590 schema_store_snapshots: u64,
1591 schema_store_encoded_bytes: u64,
1592 schema_store_latest_snapshot_bytes: u64,
1593 accepted_schema_fields: u64,
1594 accepted_schema_nested_leaf_facts: u64,
1595 sql_compile_rejects: u64,
1596 sql_compile_reject_cache_key: u64,
1597 sql_compile_reject_parse: u64,
1598 sql_compile_reject_semantic: u64,
1599 plan_index: u64,
1600 plan_keys: u64,
1601 plan_range: u64,
1602 plan_full_scan: u64,
1603 plan_by_key: u64,
1604 plan_by_keys: u64,
1605 plan_key_range: u64,
1606 plan_index_prefix: u64,
1607 plan_index_multi_lookup: u64,
1608 plan_index_range: u64,
1609 plan_explicit_full_scan: u64,
1610 plan_union: u64,
1611 plan_intersection: u64,
1612 plan_grouped_hash_materialized: u64,
1613 plan_grouped_ordered_materialized: u64,
1614 plan_choice_conflicting_primary_key_children_access_preferred: u64,
1615 plan_choice_constant_false_predicate: u64,
1616 plan_choice_empty_child_access_preferred: u64,
1617 plan_choice_full_scan_access: u64,
1618 plan_choice_intent_key_access_override: u64,
1619 plan_choice_limit_zero_window: u64,
1620 plan_choice_non_index_access: u64,
1621 plan_choice_planner_composite_non_index: u64,
1622 plan_choice_planner_full_scan_fallback: u64,
1623 plan_choice_planner_key_set_access: u64,
1624 plan_choice_planner_primary_key_lookup: u64,
1625 plan_choice_planner_primary_key_range: u64,
1626 plan_choice_required_order_primary_key_range_preferred: u64,
1627 plan_choice_singleton_primary_key_child_access_preferred: u64,
1628 prepared_shape_already_finalized: u64,
1629 prepared_shape_generated_fallback: u64,
1630 rows_loaded: u64,
1631 rows_saved: u64,
1632 rows_inserted: u64,
1633 rows_updated: u64,
1634 rows_replaced: u64,
1635 rows_scanned: u64,
1636 rows_filtered: u64,
1637 rows_aggregated: u64,
1638 rows_emitted: u64,
1639 load_candidate_rows_scanned: u64,
1640 load_candidate_rows_filtered: u64,
1641 load_result_rows_emitted: u64,
1642 rows_deleted: u64,
1643 sql_insert_calls: u64,
1644 sql_insert_select_calls: u64,
1645 sql_update_calls: u64,
1646 sql_delete_calls: u64,
1647 sql_write_matched_rows: u64,
1648 sql_write_mutated_rows: u64,
1649 sql_write_returning_rows: u64,
1650 sql_write_error_insert: u64,
1651 sql_write_error_insert_select: u64,
1652 sql_write_error_update: u64,
1653 sql_write_error_delete: u64,
1654 sql_write_error_corruption: u64,
1655 sql_write_error_incompatible_persisted_format: u64,
1656 sql_write_error_not_found: u64,
1657 sql_write_error_internal: u64,
1658 sql_write_error_conflict: u64,
1659 sql_write_error_unsupported: u64,
1660 sql_write_error_invariant_violation: u64,
1661 index_inserts: u64,
1662 index_removes: u64,
1663 reverse_index_inserts: u64,
1664 reverse_index_removes: u64,
1665 relation_reverse_lookups: u64,
1666 relation_delete_blocks: u64,
1667 write_rows_touched: u64,
1668 write_index_entries_changed: u64,
1669 write_reverse_index_entries_changed: u64,
1670 write_relation_checks: u64,
1671 unique_violations: u64,
1672 non_atomic_partial_commits: u64,
1673 non_atomic_partial_rows_committed: u64,
1674}
1675
1676impl EntitySummary {
1677 #[must_use]
1678 pub const fn path(&self) -> &str {
1679 self.path.as_str()
1680 }
1681
1682 #[must_use]
1683 pub const fn load_calls(&self) -> u64 {
1684 self.load_calls
1685 }
1686
1687 #[must_use]
1688 pub const fn save_calls(&self) -> u64 {
1689 self.save_calls
1690 }
1691
1692 #[must_use]
1693 pub const fn delete_calls(&self) -> u64 {
1694 self.delete_calls
1695 }
1696
1697 #[must_use]
1698 pub const fn save_insert_calls(&self) -> u64 {
1699 self.save_insert_calls
1700 }
1701
1702 #[must_use]
1703 pub const fn save_update_calls(&self) -> u64 {
1704 self.save_update_calls
1705 }
1706
1707 #[must_use]
1708 pub const fn save_replace_calls(&self) -> u64 {
1709 self.save_replace_calls
1710 }
1711
1712 #[must_use]
1713 pub const fn exec_success(&self) -> u64 {
1714 self.exec_success
1715 }
1716
1717 #[must_use]
1718 pub const fn exec_error_corruption(&self) -> u64 {
1719 self.exec_error_corruption
1720 }
1721
1722 #[must_use]
1723 pub const fn exec_error_incompatible_persisted_format(&self) -> u64 {
1724 self.exec_error_incompatible_persisted_format
1725 }
1726
1727 #[must_use]
1728 pub const fn exec_error_not_found(&self) -> u64 {
1729 self.exec_error_not_found
1730 }
1731
1732 #[must_use]
1733 pub const fn exec_error_internal(&self) -> u64 {
1734 self.exec_error_internal
1735 }
1736
1737 #[must_use]
1738 pub const fn exec_error_conflict(&self) -> u64 {
1739 self.exec_error_conflict
1740 }
1741
1742 #[must_use]
1743 pub const fn exec_error_unsupported(&self) -> u64 {
1744 self.exec_error_unsupported
1745 }
1746
1747 #[must_use]
1748 pub const fn exec_error_invariant_violation(&self) -> u64 {
1749 self.exec_error_invariant_violation
1750 }
1751
1752 #[must_use]
1753 pub const fn exec_aborted(&self) -> u64 {
1754 self.exec_aborted
1755 }
1756
1757 #[must_use]
1758 pub const fn cache_shared_query_plan_hits(&self) -> u64 {
1759 self.cache_shared_query_plan_hits
1760 }
1761
1762 #[must_use]
1763 pub const fn cache_shared_query_plan_misses(&self) -> u64 {
1764 self.cache_shared_query_plan_misses
1765 }
1766
1767 #[must_use]
1768 pub const fn cache_shared_query_plan_inserts(&self) -> u64 {
1769 self.cache_shared_query_plan_inserts
1770 }
1771
1772 #[must_use]
1773 pub const fn cache_shared_query_plan_miss_cold(&self) -> u64 {
1774 self.cache_shared_query_plan_miss_cold
1775 }
1776
1777 #[must_use]
1778 pub const fn cache_shared_query_plan_miss_distinct_key(&self) -> u64 {
1779 self.cache_shared_query_plan_miss_distinct_key
1780 }
1781
1782 #[must_use]
1783 pub const fn cache_shared_query_plan_miss_method_version(&self) -> u64 {
1784 self.cache_shared_query_plan_miss_method_version
1785 }
1786
1787 #[must_use]
1788 pub const fn cache_shared_query_plan_miss_schema_fingerprint(&self) -> u64 {
1789 self.cache_shared_query_plan_miss_schema_fingerprint
1790 }
1791
1792 #[must_use]
1793 pub const fn cache_shared_query_plan_miss_visibility(&self) -> u64 {
1794 self.cache_shared_query_plan_miss_visibility
1795 }
1796
1797 #[must_use]
1798 pub const fn cache_sql_compiled_command_hits(&self) -> u64 {
1799 self.cache_sql_compiled_command_hits
1800 }
1801
1802 #[must_use]
1803 pub const fn cache_sql_compiled_command_misses(&self) -> u64 {
1804 self.cache_sql_compiled_command_misses
1805 }
1806
1807 #[must_use]
1808 pub const fn cache_sql_compiled_command_inserts(&self) -> u64 {
1809 self.cache_sql_compiled_command_inserts
1810 }
1811
1812 #[must_use]
1813 pub const fn cache_sql_compiled_command_miss_cold(&self) -> u64 {
1814 self.cache_sql_compiled_command_miss_cold
1815 }
1816
1817 #[must_use]
1818 pub const fn cache_sql_compiled_command_miss_distinct_key(&self) -> u64 {
1819 self.cache_sql_compiled_command_miss_distinct_key
1820 }
1821
1822 #[must_use]
1823 pub const fn cache_sql_compiled_command_miss_method_version(&self) -> u64 {
1824 self.cache_sql_compiled_command_miss_method_version
1825 }
1826
1827 #[must_use]
1828 pub const fn cache_sql_compiled_command_miss_schema_fingerprint(&self) -> u64 {
1829 self.cache_sql_compiled_command_miss_schema_fingerprint
1830 }
1831
1832 #[must_use]
1833 pub const fn cache_sql_compiled_command_miss_surface(&self) -> u64 {
1834 self.cache_sql_compiled_command_miss_surface
1835 }
1836
1837 #[must_use]
1838 pub const fn schema_reconcile_checks(&self) -> u64 {
1839 self.schema_reconcile_checks
1840 }
1841
1842 #[must_use]
1843 pub const fn schema_reconcile_exact_match(&self) -> u64 {
1844 self.schema_reconcile_exact_match
1845 }
1846
1847 #[must_use]
1848 pub const fn schema_reconcile_first_create(&self) -> u64 {
1849 self.schema_reconcile_first_create
1850 }
1851
1852 #[must_use]
1853 pub const fn schema_reconcile_latest_snapshot_corrupt(&self) -> u64 {
1854 self.schema_reconcile_latest_snapshot_corrupt
1855 }
1856
1857 #[must_use]
1858 pub const fn schema_reconcile_rejected_field_slot(&self) -> u64 {
1859 self.schema_reconcile_rejected_field_slot
1860 }
1861
1862 #[must_use]
1863 pub const fn schema_reconcile_rejected_other(&self) -> u64 {
1864 self.schema_reconcile_rejected_other
1865 }
1866
1867 #[must_use]
1868 pub const fn schema_reconcile_rejected_row_layout(&self) -> u64 {
1869 self.schema_reconcile_rejected_row_layout
1870 }
1871
1872 #[must_use]
1873 pub const fn schema_reconcile_rejected_schema_version(&self) -> u64 {
1874 self.schema_reconcile_rejected_schema_version
1875 }
1876
1877 #[must_use]
1878 pub const fn schema_reconcile_store_write_error(&self) -> u64 {
1879 self.schema_reconcile_store_write_error
1880 }
1881
1882 #[must_use]
1883 pub const fn schema_transition_checks(&self) -> u64 {
1884 self.schema_transition_checks
1885 }
1886
1887 #[must_use]
1888 pub const fn schema_transition_append_only_nullable_fields(&self) -> u64 {
1889 self.schema_transition_append_only_nullable_fields
1890 }
1891
1892 #[must_use]
1893 pub const fn schema_transition_exact_match(&self) -> u64 {
1894 self.schema_transition_exact_match
1895 }
1896
1897 #[must_use]
1898 pub const fn schema_transition_rejected_entity_identity(&self) -> u64 {
1899 self.schema_transition_rejected_entity_identity
1900 }
1901
1902 #[must_use]
1903 pub const fn schema_transition_rejected_field_contract(&self) -> u64 {
1904 self.schema_transition_rejected_field_contract
1905 }
1906
1907 #[must_use]
1908 pub const fn schema_transition_rejected_field_slot(&self) -> u64 {
1909 self.schema_transition_rejected_field_slot
1910 }
1911
1912 #[must_use]
1913 pub const fn schema_transition_rejected_row_layout(&self) -> u64 {
1914 self.schema_transition_rejected_row_layout
1915 }
1916
1917 #[must_use]
1918 pub const fn schema_transition_rejected_schema_version(&self) -> u64 {
1919 self.schema_transition_rejected_schema_version
1920 }
1921
1922 #[must_use]
1923 pub const fn schema_transition_rejected_snapshot(&self) -> u64 {
1924 self.schema_transition_rejected_snapshot
1925 }
1926
1927 #[must_use]
1928 pub const fn schema_store_snapshots(&self) -> u64 {
1929 self.schema_store_snapshots
1930 }
1931
1932 #[must_use]
1933 pub const fn schema_store_encoded_bytes(&self) -> u64 {
1934 self.schema_store_encoded_bytes
1935 }
1936
1937 #[must_use]
1938 pub const fn schema_store_latest_snapshot_bytes(&self) -> u64 {
1939 self.schema_store_latest_snapshot_bytes
1940 }
1941
1942 #[must_use]
1943 pub const fn accepted_schema_fields(&self) -> u64 {
1944 self.accepted_schema_fields
1945 }
1946
1947 #[must_use]
1948 pub const fn accepted_schema_nested_leaf_facts(&self) -> u64 {
1949 self.accepted_schema_nested_leaf_facts
1950 }
1951
1952 #[must_use]
1953 pub const fn sql_compile_rejects(&self) -> u64 {
1954 self.sql_compile_rejects
1955 }
1956
1957 #[must_use]
1958 pub const fn sql_compile_reject_cache_key(&self) -> u64 {
1959 self.sql_compile_reject_cache_key
1960 }
1961
1962 #[must_use]
1963 pub const fn sql_compile_reject_parse(&self) -> u64 {
1964 self.sql_compile_reject_parse
1965 }
1966
1967 #[must_use]
1968 pub const fn sql_compile_reject_semantic(&self) -> u64 {
1969 self.sql_compile_reject_semantic
1970 }
1971
1972 #[must_use]
1973 pub const fn plan_index(&self) -> u64 {
1974 self.plan_index
1975 }
1976
1977 #[must_use]
1978 pub const fn plan_keys(&self) -> u64 {
1979 self.plan_keys
1980 }
1981
1982 #[must_use]
1983 pub const fn plan_range(&self) -> u64 {
1984 self.plan_range
1985 }
1986
1987 #[must_use]
1988 pub const fn plan_full_scan(&self) -> u64 {
1989 self.plan_full_scan
1990 }
1991
1992 #[must_use]
1993 pub const fn plan_by_key(&self) -> u64 {
1994 self.plan_by_key
1995 }
1996
1997 #[must_use]
1998 pub const fn plan_by_keys(&self) -> u64 {
1999 self.plan_by_keys
2000 }
2001
2002 #[must_use]
2003 pub const fn plan_key_range(&self) -> u64 {
2004 self.plan_key_range
2005 }
2006
2007 #[must_use]
2008 pub const fn plan_index_prefix(&self) -> u64 {
2009 self.plan_index_prefix
2010 }
2011
2012 #[must_use]
2013 pub const fn plan_index_multi_lookup(&self) -> u64 {
2014 self.plan_index_multi_lookup
2015 }
2016
2017 #[must_use]
2018 pub const fn plan_index_range(&self) -> u64 {
2019 self.plan_index_range
2020 }
2021
2022 #[must_use]
2023 pub const fn plan_explicit_full_scan(&self) -> u64 {
2024 self.plan_explicit_full_scan
2025 }
2026
2027 #[must_use]
2028 pub const fn plan_union(&self) -> u64 {
2029 self.plan_union
2030 }
2031
2032 #[must_use]
2033 pub const fn plan_intersection(&self) -> u64 {
2034 self.plan_intersection
2035 }
2036
2037 #[must_use]
2038 pub const fn plan_grouped_hash_materialized(&self) -> u64 {
2039 self.plan_grouped_hash_materialized
2040 }
2041
2042 #[must_use]
2043 pub const fn plan_grouped_ordered_materialized(&self) -> u64 {
2044 self.plan_grouped_ordered_materialized
2045 }
2046
2047 #[must_use]
2048 pub const fn plan_choice_conflicting_primary_key_children_access_preferred(&self) -> u64 {
2049 self.plan_choice_conflicting_primary_key_children_access_preferred
2050 }
2051
2052 #[must_use]
2053 pub const fn plan_choice_constant_false_predicate(&self) -> u64 {
2054 self.plan_choice_constant_false_predicate
2055 }
2056
2057 #[must_use]
2058 pub const fn plan_choice_empty_child_access_preferred(&self) -> u64 {
2059 self.plan_choice_empty_child_access_preferred
2060 }
2061
2062 #[must_use]
2063 pub const fn plan_choice_full_scan_access(&self) -> u64 {
2064 self.plan_choice_full_scan_access
2065 }
2066
2067 #[must_use]
2068 pub const fn plan_choice_intent_key_access_override(&self) -> u64 {
2069 self.plan_choice_intent_key_access_override
2070 }
2071
2072 #[must_use]
2073 pub const fn plan_choice_limit_zero_window(&self) -> u64 {
2074 self.plan_choice_limit_zero_window
2075 }
2076
2077 #[must_use]
2078 pub const fn plan_choice_non_index_access(&self) -> u64 {
2079 self.plan_choice_non_index_access
2080 }
2081
2082 #[must_use]
2083 pub const fn plan_choice_planner_composite_non_index(&self) -> u64 {
2084 self.plan_choice_planner_composite_non_index
2085 }
2086
2087 #[must_use]
2088 pub const fn plan_choice_planner_full_scan_fallback(&self) -> u64 {
2089 self.plan_choice_planner_full_scan_fallback
2090 }
2091
2092 #[must_use]
2093 pub const fn plan_choice_planner_key_set_access(&self) -> u64 {
2094 self.plan_choice_planner_key_set_access
2095 }
2096
2097 #[must_use]
2098 pub const fn plan_choice_planner_primary_key_lookup(&self) -> u64 {
2099 self.plan_choice_planner_primary_key_lookup
2100 }
2101
2102 #[must_use]
2103 pub const fn plan_choice_planner_primary_key_range(&self) -> u64 {
2104 self.plan_choice_planner_primary_key_range
2105 }
2106
2107 #[must_use]
2108 pub const fn plan_choice_required_order_primary_key_range_preferred(&self) -> u64 {
2109 self.plan_choice_required_order_primary_key_range_preferred
2110 }
2111
2112 #[must_use]
2113 pub const fn plan_choice_singleton_primary_key_child_access_preferred(&self) -> u64 {
2114 self.plan_choice_singleton_primary_key_child_access_preferred
2115 }
2116
2117 #[must_use]
2118 pub const fn prepared_shape_already_finalized(&self) -> u64 {
2119 self.prepared_shape_already_finalized
2120 }
2121
2122 #[must_use]
2123 pub const fn prepared_shape_generated_fallback(&self) -> u64 {
2124 self.prepared_shape_generated_fallback
2125 }
2126
2127 #[must_use]
2128 pub const fn rows_loaded(&self) -> u64 {
2129 self.rows_loaded
2130 }
2131
2132 #[must_use]
2133 pub const fn rows_saved(&self) -> u64 {
2134 self.rows_saved
2135 }
2136
2137 #[must_use]
2138 pub const fn rows_inserted(&self) -> u64 {
2139 self.rows_inserted
2140 }
2141
2142 #[must_use]
2143 pub const fn rows_updated(&self) -> u64 {
2144 self.rows_updated
2145 }
2146
2147 #[must_use]
2148 pub const fn rows_replaced(&self) -> u64 {
2149 self.rows_replaced
2150 }
2151
2152 #[must_use]
2153 pub const fn rows_scanned(&self) -> u64 {
2154 self.rows_scanned
2155 }
2156
2157 #[must_use]
2158 pub const fn rows_filtered(&self) -> u64 {
2159 self.rows_filtered
2160 }
2161
2162 #[must_use]
2163 pub const fn rows_aggregated(&self) -> u64 {
2164 self.rows_aggregated
2165 }
2166
2167 #[must_use]
2168 pub const fn rows_emitted(&self) -> u64 {
2169 self.rows_emitted
2170 }
2171
2172 #[must_use]
2173 pub const fn load_candidate_rows_scanned(&self) -> u64 {
2174 self.load_candidate_rows_scanned
2175 }
2176
2177 #[must_use]
2178 pub const fn load_candidate_rows_filtered(&self) -> u64 {
2179 self.load_candidate_rows_filtered
2180 }
2181
2182 #[must_use]
2183 pub const fn load_result_rows_emitted(&self) -> u64 {
2184 self.load_result_rows_emitted
2185 }
2186
2187 #[must_use]
2188 pub const fn rows_deleted(&self) -> u64 {
2189 self.rows_deleted
2190 }
2191
2192 #[must_use]
2193 pub const fn sql_insert_calls(&self) -> u64 {
2194 self.sql_insert_calls
2195 }
2196
2197 #[must_use]
2198 pub const fn sql_insert_select_calls(&self) -> u64 {
2199 self.sql_insert_select_calls
2200 }
2201
2202 #[must_use]
2203 pub const fn sql_update_calls(&self) -> u64 {
2204 self.sql_update_calls
2205 }
2206
2207 #[must_use]
2208 pub const fn sql_delete_calls(&self) -> u64 {
2209 self.sql_delete_calls
2210 }
2211
2212 #[must_use]
2213 pub const fn sql_write_matched_rows(&self) -> u64 {
2214 self.sql_write_matched_rows
2215 }
2216
2217 #[must_use]
2218 pub const fn sql_write_mutated_rows(&self) -> u64 {
2219 self.sql_write_mutated_rows
2220 }
2221
2222 #[must_use]
2223 pub const fn sql_write_returning_rows(&self) -> u64 {
2224 self.sql_write_returning_rows
2225 }
2226
2227 #[must_use]
2228 pub const fn sql_write_error_insert(&self) -> u64 {
2229 self.sql_write_error_insert
2230 }
2231
2232 #[must_use]
2233 pub const fn sql_write_error_insert_select(&self) -> u64 {
2234 self.sql_write_error_insert_select
2235 }
2236
2237 #[must_use]
2238 pub const fn sql_write_error_update(&self) -> u64 {
2239 self.sql_write_error_update
2240 }
2241
2242 #[must_use]
2243 pub const fn sql_write_error_delete(&self) -> u64 {
2244 self.sql_write_error_delete
2245 }
2246
2247 #[must_use]
2248 pub const fn sql_write_error_corruption(&self) -> u64 {
2249 self.sql_write_error_corruption
2250 }
2251
2252 #[must_use]
2253 pub const fn sql_write_error_incompatible_persisted_format(&self) -> u64 {
2254 self.sql_write_error_incompatible_persisted_format
2255 }
2256
2257 #[must_use]
2258 pub const fn sql_write_error_not_found(&self) -> u64 {
2259 self.sql_write_error_not_found
2260 }
2261
2262 #[must_use]
2263 pub const fn sql_write_error_internal(&self) -> u64 {
2264 self.sql_write_error_internal
2265 }
2266
2267 #[must_use]
2268 pub const fn sql_write_error_conflict(&self) -> u64 {
2269 self.sql_write_error_conflict
2270 }
2271
2272 #[must_use]
2273 pub const fn sql_write_error_unsupported(&self) -> u64 {
2274 self.sql_write_error_unsupported
2275 }
2276
2277 #[must_use]
2278 pub const fn sql_write_error_invariant_violation(&self) -> u64 {
2279 self.sql_write_error_invariant_violation
2280 }
2281
2282 #[must_use]
2283 pub const fn index_inserts(&self) -> u64 {
2284 self.index_inserts
2285 }
2286
2287 #[must_use]
2288 pub const fn index_removes(&self) -> u64 {
2289 self.index_removes
2290 }
2291
2292 #[must_use]
2293 pub const fn reverse_index_inserts(&self) -> u64 {
2294 self.reverse_index_inserts
2295 }
2296
2297 #[must_use]
2298 pub const fn reverse_index_removes(&self) -> u64 {
2299 self.reverse_index_removes
2300 }
2301
2302 #[must_use]
2303 pub const fn relation_reverse_lookups(&self) -> u64 {
2304 self.relation_reverse_lookups
2305 }
2306
2307 #[must_use]
2308 pub const fn relation_delete_blocks(&self) -> u64 {
2309 self.relation_delete_blocks
2310 }
2311
2312 #[must_use]
2313 pub const fn write_rows_touched(&self) -> u64 {
2314 self.write_rows_touched
2315 }
2316
2317 #[must_use]
2318 pub const fn write_index_entries_changed(&self) -> u64 {
2319 self.write_index_entries_changed
2320 }
2321
2322 #[must_use]
2323 pub const fn write_reverse_index_entries_changed(&self) -> u64 {
2324 self.write_reverse_index_entries_changed
2325 }
2326
2327 #[must_use]
2328 pub const fn write_relation_checks(&self) -> u64 {
2329 self.write_relation_checks
2330 }
2331
2332 #[must_use]
2333 pub const fn unique_violations(&self) -> u64 {
2334 self.unique_violations
2335 }
2336
2337 #[must_use]
2338 pub const fn non_atomic_partial_commits(&self) -> u64 {
2339 self.non_atomic_partial_commits
2340 }
2341
2342 #[must_use]
2343 pub const fn non_atomic_partial_rows_committed(&self) -> u64 {
2344 self.non_atomic_partial_rows_committed
2345 }
2346
2347 #[must_use]
2349 pub const fn load_selectivity_ratio(&self) -> Option<MetricRatio> {
2350 ratio(
2351 self.load_result_rows_emitted,
2352 self.load_candidate_rows_scanned,
2353 )
2354 }
2355
2356 #[must_use]
2358 pub const fn load_filter_ratio(&self) -> Option<MetricRatio> {
2359 ratio(
2360 self.load_candidate_rows_filtered,
2361 self.load_candidate_rows_scanned,
2362 )
2363 }
2364
2365 #[must_use]
2367 pub const fn sql_write_mutation_ratio(&self) -> Option<MetricRatio> {
2368 ratio(self.sql_write_mutated_rows, self.sql_write_matched_rows)
2369 }
2370
2371 #[must_use]
2373 pub const fn sql_write_returning_ratio(&self) -> Option<MetricRatio> {
2374 ratio(self.sql_write_returning_rows, self.sql_write_mutated_rows)
2375 }
2376
2377 #[must_use]
2379 pub const fn write_index_entries_per_row(&self) -> Option<MetricRatio> {
2380 ratio(self.write_index_entries_changed, self.write_rows_touched)
2381 }
2382
2383 #[must_use]
2385 pub const fn write_reverse_index_entries_per_row(&self) -> Option<MetricRatio> {
2386 ratio(
2387 self.write_reverse_index_entries_changed,
2388 self.write_rows_touched,
2389 )
2390 }
2391
2392 #[must_use]
2394 pub const fn write_relation_checks_per_row(&self) -> Option<MetricRatio> {
2395 ratio(self.write_relation_checks, self.write_rows_touched)
2396 }
2397
2398 #[expect(clippy::too_many_lines)]
2401 const fn activity_score(&self) -> u64 {
2402 self.load_calls
2403 .saturating_add(self.save_calls)
2404 .saturating_add(self.delete_calls)
2405 .saturating_add(self.save_insert_calls)
2406 .saturating_add(self.save_update_calls)
2407 .saturating_add(self.save_replace_calls)
2408 .saturating_add(self.exec_success)
2409 .saturating_add(self.exec_error_corruption)
2410 .saturating_add(self.exec_error_incompatible_persisted_format)
2411 .saturating_add(self.exec_error_not_found)
2412 .saturating_add(self.exec_error_internal)
2413 .saturating_add(self.exec_error_conflict)
2414 .saturating_add(self.exec_error_unsupported)
2415 .saturating_add(self.exec_error_invariant_violation)
2416 .saturating_add(self.exec_aborted)
2417 .saturating_add(self.cache_shared_query_plan_hits)
2418 .saturating_add(self.cache_shared_query_plan_misses)
2419 .saturating_add(self.cache_shared_query_plan_inserts)
2420 .saturating_add(self.cache_shared_query_plan_miss_cold)
2421 .saturating_add(self.cache_shared_query_plan_miss_distinct_key)
2422 .saturating_add(self.cache_shared_query_plan_miss_method_version)
2423 .saturating_add(self.cache_shared_query_plan_miss_schema_fingerprint)
2424 .saturating_add(self.cache_shared_query_plan_miss_visibility)
2425 .saturating_add(self.cache_sql_compiled_command_hits)
2426 .saturating_add(self.cache_sql_compiled_command_misses)
2427 .saturating_add(self.cache_sql_compiled_command_inserts)
2428 .saturating_add(self.cache_sql_compiled_command_miss_cold)
2429 .saturating_add(self.cache_sql_compiled_command_miss_distinct_key)
2430 .saturating_add(self.cache_sql_compiled_command_miss_method_version)
2431 .saturating_add(self.cache_sql_compiled_command_miss_schema_fingerprint)
2432 .saturating_add(self.cache_sql_compiled_command_miss_surface)
2433 .saturating_add(self.schema_reconcile_checks)
2434 .saturating_add(self.schema_reconcile_exact_match)
2435 .saturating_add(self.schema_reconcile_first_create)
2436 .saturating_add(self.schema_reconcile_latest_snapshot_corrupt)
2437 .saturating_add(self.schema_reconcile_rejected_field_slot)
2438 .saturating_add(self.schema_reconcile_rejected_other)
2439 .saturating_add(self.schema_reconcile_rejected_row_layout)
2440 .saturating_add(self.schema_reconcile_rejected_schema_version)
2441 .saturating_add(self.schema_reconcile_store_write_error)
2442 .saturating_add(self.schema_transition_checks)
2443 .saturating_add(self.schema_transition_append_only_nullable_fields)
2444 .saturating_add(self.schema_transition_exact_match)
2445 .saturating_add(self.schema_transition_rejected_entity_identity)
2446 .saturating_add(self.schema_transition_rejected_field_contract)
2447 .saturating_add(self.schema_transition_rejected_field_slot)
2448 .saturating_add(self.schema_transition_rejected_row_layout)
2449 .saturating_add(self.schema_transition_rejected_schema_version)
2450 .saturating_add(self.schema_transition_rejected_snapshot)
2451 .saturating_add(self.schema_store_snapshots)
2452 .saturating_add(self.schema_store_encoded_bytes)
2453 .saturating_add(self.schema_store_latest_snapshot_bytes)
2454 .saturating_add(self.accepted_schema_fields)
2455 .saturating_add(self.accepted_schema_nested_leaf_facts)
2456 .saturating_add(self.sql_compile_rejects)
2457 .saturating_add(self.sql_compile_reject_cache_key)
2458 .saturating_add(self.sql_compile_reject_parse)
2459 .saturating_add(self.sql_compile_reject_semantic)
2460 .saturating_add(self.plan_index)
2461 .saturating_add(self.plan_keys)
2462 .saturating_add(self.plan_range)
2463 .saturating_add(self.plan_full_scan)
2464 .saturating_add(self.plan_by_key)
2465 .saturating_add(self.plan_by_keys)
2466 .saturating_add(self.plan_key_range)
2467 .saturating_add(self.plan_index_prefix)
2468 .saturating_add(self.plan_index_multi_lookup)
2469 .saturating_add(self.plan_index_range)
2470 .saturating_add(self.plan_explicit_full_scan)
2471 .saturating_add(self.plan_union)
2472 .saturating_add(self.plan_intersection)
2473 .saturating_add(self.plan_grouped_hash_materialized)
2474 .saturating_add(self.plan_grouped_ordered_materialized)
2475 .saturating_add(self.plan_choice_conflicting_primary_key_children_access_preferred)
2476 .saturating_add(self.plan_choice_constant_false_predicate)
2477 .saturating_add(self.plan_choice_empty_child_access_preferred)
2478 .saturating_add(self.plan_choice_full_scan_access)
2479 .saturating_add(self.plan_choice_intent_key_access_override)
2480 .saturating_add(self.plan_choice_limit_zero_window)
2481 .saturating_add(self.plan_choice_non_index_access)
2482 .saturating_add(self.plan_choice_planner_composite_non_index)
2483 .saturating_add(self.plan_choice_planner_full_scan_fallback)
2484 .saturating_add(self.plan_choice_planner_key_set_access)
2485 .saturating_add(self.plan_choice_planner_primary_key_lookup)
2486 .saturating_add(self.plan_choice_planner_primary_key_range)
2487 .saturating_add(self.plan_choice_required_order_primary_key_range_preferred)
2488 .saturating_add(self.plan_choice_singleton_primary_key_child_access_preferred)
2489 .saturating_add(self.prepared_shape_already_finalized)
2490 .saturating_add(self.prepared_shape_generated_fallback)
2491 .saturating_add(self.rows_loaded)
2492 .saturating_add(self.rows_saved)
2493 .saturating_add(self.rows_inserted)
2494 .saturating_add(self.rows_updated)
2495 .saturating_add(self.rows_replaced)
2496 .saturating_add(self.rows_scanned)
2497 .saturating_add(self.rows_filtered)
2498 .saturating_add(self.rows_aggregated)
2499 .saturating_add(self.rows_emitted)
2500 .saturating_add(self.load_candidate_rows_scanned)
2501 .saturating_add(self.load_candidate_rows_filtered)
2502 .saturating_add(self.load_result_rows_emitted)
2503 .saturating_add(self.rows_deleted)
2504 .saturating_add(self.sql_insert_calls)
2505 .saturating_add(self.sql_insert_select_calls)
2506 .saturating_add(self.sql_update_calls)
2507 .saturating_add(self.sql_delete_calls)
2508 .saturating_add(self.sql_write_matched_rows)
2509 .saturating_add(self.sql_write_mutated_rows)
2510 .saturating_add(self.sql_write_returning_rows)
2511 .saturating_add(self.sql_write_error_insert)
2512 .saturating_add(self.sql_write_error_insert_select)
2513 .saturating_add(self.sql_write_error_update)
2514 .saturating_add(self.sql_write_error_delete)
2515 .saturating_add(self.sql_write_error_corruption)
2516 .saturating_add(self.sql_write_error_incompatible_persisted_format)
2517 .saturating_add(self.sql_write_error_not_found)
2518 .saturating_add(self.sql_write_error_internal)
2519 .saturating_add(self.sql_write_error_conflict)
2520 .saturating_add(self.sql_write_error_unsupported)
2521 .saturating_add(self.sql_write_error_invariant_violation)
2522 .saturating_add(self.index_inserts)
2523 .saturating_add(self.index_removes)
2524 .saturating_add(self.reverse_index_inserts)
2525 .saturating_add(self.reverse_index_removes)
2526 .saturating_add(self.relation_reverse_lookups)
2527 .saturating_add(self.relation_delete_blocks)
2528 .saturating_add(self.write_rows_touched)
2529 .saturating_add(self.write_index_entries_changed)
2530 .saturating_add(self.write_reverse_index_entries_changed)
2531 .saturating_add(self.write_relation_checks)
2532 .saturating_add(self.unique_violations)
2533 .saturating_add(self.non_atomic_partial_commits)
2534 .saturating_add(self.non_atomic_partial_rows_committed)
2535 }
2536}
2537
2538#[expect(clippy::too_many_lines)]
2543fn entity_summary_from_counters(path: &str, ops: &EntityCounters) -> EntitySummary {
2544 EntitySummary {
2545 path: path.to_string(),
2546 load_calls: ops.load_calls,
2547 save_calls: ops.save_calls,
2548 delete_calls: ops.delete_calls,
2549 save_insert_calls: ops.save_insert_calls,
2550 save_update_calls: ops.save_update_calls,
2551 save_replace_calls: ops.save_replace_calls,
2552 exec_success: ops.exec_success,
2553 exec_error_corruption: ops.exec_error_corruption,
2554 exec_error_incompatible_persisted_format: ops.exec_error_incompatible_persisted_format,
2555 exec_error_not_found: ops.exec_error_not_found,
2556 exec_error_internal: ops.exec_error_internal,
2557 exec_error_conflict: ops.exec_error_conflict,
2558 exec_error_unsupported: ops.exec_error_unsupported,
2559 exec_error_invariant_violation: ops.exec_error_invariant_violation,
2560 exec_aborted: ops.exec_aborted,
2561 cache_shared_query_plan_hits: ops.cache_shared_query_plan_hits,
2562 cache_shared_query_plan_misses: ops.cache_shared_query_plan_misses,
2563 cache_shared_query_plan_inserts: ops.cache_shared_query_plan_inserts,
2564 cache_shared_query_plan_miss_cold: ops.cache_shared_query_plan_miss_cold,
2565 cache_shared_query_plan_miss_distinct_key: ops.cache_shared_query_plan_miss_distinct_key,
2566 cache_shared_query_plan_miss_method_version: ops
2567 .cache_shared_query_plan_miss_method_version,
2568 cache_shared_query_plan_miss_schema_fingerprint: ops
2569 .cache_shared_query_plan_miss_schema_fingerprint,
2570 cache_shared_query_plan_miss_visibility: ops.cache_shared_query_plan_miss_visibility,
2571 cache_sql_compiled_command_hits: ops.cache_sql_compiled_command_hits,
2572 cache_sql_compiled_command_misses: ops.cache_sql_compiled_command_misses,
2573 cache_sql_compiled_command_inserts: ops.cache_sql_compiled_command_inserts,
2574 cache_sql_compiled_command_miss_cold: ops.cache_sql_compiled_command_miss_cold,
2575 cache_sql_compiled_command_miss_distinct_key: ops
2576 .cache_sql_compiled_command_miss_distinct_key,
2577 cache_sql_compiled_command_miss_method_version: ops
2578 .cache_sql_compiled_command_miss_method_version,
2579 cache_sql_compiled_command_miss_schema_fingerprint: ops
2580 .cache_sql_compiled_command_miss_schema_fingerprint,
2581 cache_sql_compiled_command_miss_surface: ops.cache_sql_compiled_command_miss_surface,
2582 schema_reconcile_checks: ops.schema_reconcile_checks,
2583 schema_reconcile_exact_match: ops.schema_reconcile_exact_match,
2584 schema_reconcile_first_create: ops.schema_reconcile_first_create,
2585 schema_reconcile_latest_snapshot_corrupt: ops.schema_reconcile_latest_snapshot_corrupt,
2586 schema_reconcile_rejected_field_slot: ops.schema_reconcile_rejected_field_slot,
2587 schema_reconcile_rejected_other: ops.schema_reconcile_rejected_other,
2588 schema_reconcile_rejected_row_layout: ops.schema_reconcile_rejected_row_layout,
2589 schema_reconcile_rejected_schema_version: ops.schema_reconcile_rejected_schema_version,
2590 schema_reconcile_store_write_error: ops.schema_reconcile_store_write_error,
2591 schema_transition_checks: ops.schema_transition_checks,
2592 schema_transition_append_only_nullable_fields: ops
2593 .schema_transition_append_only_nullable_fields,
2594 schema_transition_exact_match: ops.schema_transition_exact_match,
2595 schema_transition_rejected_entity_identity: ops.schema_transition_rejected_entity_identity,
2596 schema_transition_rejected_field_contract: ops.schema_transition_rejected_field_contract,
2597 schema_transition_rejected_field_slot: ops.schema_transition_rejected_field_slot,
2598 schema_transition_rejected_row_layout: ops.schema_transition_rejected_row_layout,
2599 schema_transition_rejected_schema_version: ops.schema_transition_rejected_schema_version,
2600 schema_transition_rejected_snapshot: ops.schema_transition_rejected_snapshot,
2601 schema_store_snapshots: ops.schema_store_snapshots,
2602 schema_store_encoded_bytes: ops.schema_store_encoded_bytes,
2603 schema_store_latest_snapshot_bytes: ops.schema_store_latest_snapshot_bytes,
2604 accepted_schema_fields: ops.accepted_schema_fields,
2605 accepted_schema_nested_leaf_facts: ops.accepted_schema_nested_leaf_facts,
2606 sql_compile_rejects: ops.sql_compile_rejects,
2607 sql_compile_reject_cache_key: ops.sql_compile_reject_cache_key,
2608 sql_compile_reject_parse: ops.sql_compile_reject_parse,
2609 sql_compile_reject_semantic: ops.sql_compile_reject_semantic,
2610 plan_index: ops.plan_index,
2611 plan_keys: ops.plan_keys,
2612 plan_range: ops.plan_range,
2613 plan_full_scan: ops.plan_full_scan,
2614 plan_by_key: ops.plan_by_key,
2615 plan_by_keys: ops.plan_by_keys,
2616 plan_key_range: ops.plan_key_range,
2617 plan_index_prefix: ops.plan_index_prefix,
2618 plan_index_multi_lookup: ops.plan_index_multi_lookup,
2619 plan_index_range: ops.plan_index_range,
2620 plan_explicit_full_scan: ops.plan_explicit_full_scan,
2621 plan_union: ops.plan_union,
2622 plan_intersection: ops.plan_intersection,
2623 plan_grouped_hash_materialized: ops.plan_grouped_hash_materialized,
2624 plan_grouped_ordered_materialized: ops.plan_grouped_ordered_materialized,
2625 plan_choice_conflicting_primary_key_children_access_preferred: ops
2626 .plan_choice_conflicting_primary_key_children_access_preferred,
2627 plan_choice_constant_false_predicate: ops.plan_choice_constant_false_predicate,
2628 plan_choice_empty_child_access_preferred: ops.plan_choice_empty_child_access_preferred,
2629 plan_choice_full_scan_access: ops.plan_choice_full_scan_access,
2630 plan_choice_intent_key_access_override: ops.plan_choice_intent_key_access_override,
2631 plan_choice_limit_zero_window: ops.plan_choice_limit_zero_window,
2632 plan_choice_non_index_access: ops.plan_choice_non_index_access,
2633 plan_choice_planner_composite_non_index: ops.plan_choice_planner_composite_non_index,
2634 plan_choice_planner_full_scan_fallback: ops.plan_choice_planner_full_scan_fallback,
2635 plan_choice_planner_key_set_access: ops.plan_choice_planner_key_set_access,
2636 plan_choice_planner_primary_key_lookup: ops.plan_choice_planner_primary_key_lookup,
2637 plan_choice_planner_primary_key_range: ops.plan_choice_planner_primary_key_range,
2638 plan_choice_required_order_primary_key_range_preferred: ops
2639 .plan_choice_required_order_primary_key_range_preferred,
2640 plan_choice_singleton_primary_key_child_access_preferred: ops
2641 .plan_choice_singleton_primary_key_child_access_preferred,
2642 prepared_shape_already_finalized: ops.prepared_shape_already_finalized,
2643 prepared_shape_generated_fallback: ops.prepared_shape_generated_fallback,
2644 rows_loaded: ops.rows_loaded,
2645 rows_saved: ops.rows_saved,
2646 rows_inserted: ops.rows_inserted,
2647 rows_updated: ops.rows_updated,
2648 rows_replaced: ops.rows_replaced,
2649 rows_scanned: ops.rows_scanned,
2650 rows_filtered: ops.rows_filtered,
2651 rows_aggregated: ops.rows_aggregated,
2652 rows_emitted: ops.rows_emitted,
2653 load_candidate_rows_scanned: ops.load_candidate_rows_scanned,
2654 load_candidate_rows_filtered: ops.load_candidate_rows_filtered,
2655 load_result_rows_emitted: ops.load_result_rows_emitted,
2656 rows_deleted: ops.rows_deleted,
2657 sql_insert_calls: ops.sql_insert_calls,
2658 sql_insert_select_calls: ops.sql_insert_select_calls,
2659 sql_update_calls: ops.sql_update_calls,
2660 sql_delete_calls: ops.sql_delete_calls,
2661 sql_write_matched_rows: ops.sql_write_matched_rows,
2662 sql_write_mutated_rows: ops.sql_write_mutated_rows,
2663 sql_write_returning_rows: ops.sql_write_returning_rows,
2664 sql_write_error_insert: ops.sql_write_error_insert,
2665 sql_write_error_insert_select: ops.sql_write_error_insert_select,
2666 sql_write_error_update: ops.sql_write_error_update,
2667 sql_write_error_delete: ops.sql_write_error_delete,
2668 sql_write_error_corruption: ops.sql_write_error_corruption,
2669 sql_write_error_incompatible_persisted_format: ops
2670 .sql_write_error_incompatible_persisted_format,
2671 sql_write_error_not_found: ops.sql_write_error_not_found,
2672 sql_write_error_internal: ops.sql_write_error_internal,
2673 sql_write_error_conflict: ops.sql_write_error_conflict,
2674 sql_write_error_unsupported: ops.sql_write_error_unsupported,
2675 sql_write_error_invariant_violation: ops.sql_write_error_invariant_violation,
2676 index_inserts: ops.index_inserts,
2677 index_removes: ops.index_removes,
2678 reverse_index_inserts: ops.reverse_index_inserts,
2679 reverse_index_removes: ops.reverse_index_removes,
2680 relation_reverse_lookups: ops.relation_reverse_lookups,
2681 relation_delete_blocks: ops.relation_delete_blocks,
2682 write_rows_touched: ops.write_rows_touched,
2683 write_index_entries_changed: ops.write_index_entries_changed,
2684 write_reverse_index_entries_changed: ops.write_reverse_index_entries_changed,
2685 write_relation_checks: ops.write_relation_checks,
2686 unique_violations: ops.unique_violations,
2687 non_atomic_partial_commits: ops.non_atomic_partial_commits,
2688 non_atomic_partial_rows_committed: ops.non_atomic_partial_rows_committed,
2689 }
2690}
2691
2692fn push_compact_metric(metrics: &mut Vec<CompactMetric>, code: u16, value: u64) {
2693 if value != 0 {
2694 metrics.push(CompactMetric::new(code, value));
2695 }
2696}
2697
2698const fn event_ops_exec_errors(ops: &EventOps) -> u64 {
2699 ops.exec_error_corruption
2700 .saturating_add(ops.exec_error_incompatible_persisted_format)
2701 .saturating_add(ops.exec_error_not_found)
2702 .saturating_add(ops.exec_error_internal)
2703 .saturating_add(ops.exec_error_conflict)
2704 .saturating_add(ops.exec_error_unsupported)
2705 .saturating_add(ops.exec_error_invariant_violation)
2706}
2707
2708const fn entity_ops_exec_errors(ops: &EntityCounters) -> u64 {
2709 ops.exec_error_corruption
2710 .saturating_add(ops.exec_error_incompatible_persisted_format)
2711 .saturating_add(ops.exec_error_not_found)
2712 .saturating_add(ops.exec_error_internal)
2713 .saturating_add(ops.exec_error_conflict)
2714 .saturating_add(ops.exec_error_unsupported)
2715 .saturating_add(ops.exec_error_invariant_violation)
2716}
2717
2718fn compact_event_metrics(ops: &EventOps) -> Vec<CompactMetric> {
2719 use compact_metric_code::{
2720 CACHE_SHARED_QUERY_PLAN_HITS, CACHE_SHARED_QUERY_PLAN_MISSES,
2721 CACHE_SQL_COMPILED_COMMAND_HITS, CACHE_SQL_COMPILED_COMMAND_MISSES, DELETE_CALLS,
2722 EXEC_ABORTED, EXEC_ERRORS, EXEC_SUCCESS, LOAD_CALLS, ROWS_DELETED, ROWS_EMITTED,
2723 ROWS_FILTERED, ROWS_LOADED, ROWS_SAVED, ROWS_SCANNED, SAVE_CALLS, SQL_DELETE_CALLS,
2724 SQL_INSERT_CALLS, SQL_INSERT_SELECT_CALLS, SQL_UPDATE_CALLS, SQL_WRITE_MATCHED_ROWS,
2725 SQL_WRITE_MUTATED_ROWS, SQL_WRITE_RETURNING_ROWS,
2726 };
2727
2728 let mut metrics = Vec::new();
2729 push_compact_metric(&mut metrics, LOAD_CALLS, ops.load_calls);
2730 push_compact_metric(&mut metrics, SAVE_CALLS, ops.save_calls);
2731 push_compact_metric(&mut metrics, DELETE_CALLS, ops.delete_calls);
2732 push_compact_metric(&mut metrics, EXEC_SUCCESS, ops.exec_success);
2733 push_compact_metric(&mut metrics, EXEC_ERRORS, event_ops_exec_errors(ops));
2734 push_compact_metric(&mut metrics, EXEC_ABORTED, ops.exec_aborted);
2735 push_compact_metric(&mut metrics, ROWS_LOADED, ops.rows_loaded);
2736 push_compact_metric(&mut metrics, ROWS_SAVED, ops.rows_saved);
2737 push_compact_metric(&mut metrics, ROWS_DELETED, ops.rows_deleted);
2738 push_compact_metric(&mut metrics, ROWS_SCANNED, ops.rows_scanned);
2739 push_compact_metric(&mut metrics, ROWS_FILTERED, ops.rows_filtered);
2740 push_compact_metric(&mut metrics, ROWS_EMITTED, ops.rows_emitted);
2741 push_compact_metric(&mut metrics, SQL_INSERT_CALLS, ops.sql_insert_calls);
2742 push_compact_metric(
2743 &mut metrics,
2744 SQL_INSERT_SELECT_CALLS,
2745 ops.sql_insert_select_calls,
2746 );
2747 push_compact_metric(&mut metrics, SQL_UPDATE_CALLS, ops.sql_update_calls);
2748 push_compact_metric(&mut metrics, SQL_DELETE_CALLS, ops.sql_delete_calls);
2749 push_compact_metric(
2750 &mut metrics,
2751 SQL_WRITE_MATCHED_ROWS,
2752 ops.sql_write_matched_rows,
2753 );
2754 push_compact_metric(
2755 &mut metrics,
2756 SQL_WRITE_MUTATED_ROWS,
2757 ops.sql_write_mutated_rows,
2758 );
2759 push_compact_metric(
2760 &mut metrics,
2761 SQL_WRITE_RETURNING_ROWS,
2762 ops.sql_write_returning_rows,
2763 );
2764 push_compact_metric(
2765 &mut metrics,
2766 CACHE_SHARED_QUERY_PLAN_HITS,
2767 ops.cache_shared_query_plan_hits,
2768 );
2769 push_compact_metric(
2770 &mut metrics,
2771 CACHE_SHARED_QUERY_PLAN_MISSES,
2772 ops.cache_shared_query_plan_misses,
2773 );
2774 push_compact_metric(
2775 &mut metrics,
2776 CACHE_SQL_COMPILED_COMMAND_HITS,
2777 ops.cache_sql_compiled_command_hits,
2778 );
2779 push_compact_metric(
2780 &mut metrics,
2781 CACHE_SQL_COMPILED_COMMAND_MISSES,
2782 ops.cache_sql_compiled_command_misses,
2783 );
2784
2785 metrics
2786}
2787
2788fn compact_entity_metrics(ops: &EntityCounters) -> Vec<CompactMetric> {
2789 use compact_metric_code::{
2790 CACHE_SHARED_QUERY_PLAN_HITS, CACHE_SHARED_QUERY_PLAN_MISSES,
2791 CACHE_SQL_COMPILED_COMMAND_HITS, CACHE_SQL_COMPILED_COMMAND_MISSES, DELETE_CALLS,
2792 EXEC_ABORTED, EXEC_ERRORS, EXEC_SUCCESS, LOAD_CALLS, ROWS_DELETED, ROWS_EMITTED,
2793 ROWS_FILTERED, ROWS_LOADED, ROWS_SAVED, ROWS_SCANNED, SAVE_CALLS, SQL_DELETE_CALLS,
2794 SQL_INSERT_CALLS, SQL_INSERT_SELECT_CALLS, SQL_UPDATE_CALLS, SQL_WRITE_MATCHED_ROWS,
2795 SQL_WRITE_MUTATED_ROWS, SQL_WRITE_RETURNING_ROWS,
2796 };
2797
2798 let mut metrics = Vec::new();
2799 push_compact_metric(&mut metrics, LOAD_CALLS, ops.load_calls);
2800 push_compact_metric(&mut metrics, SAVE_CALLS, ops.save_calls);
2801 push_compact_metric(&mut metrics, DELETE_CALLS, ops.delete_calls);
2802 push_compact_metric(&mut metrics, EXEC_SUCCESS, ops.exec_success);
2803 push_compact_metric(&mut metrics, EXEC_ERRORS, entity_ops_exec_errors(ops));
2804 push_compact_metric(&mut metrics, EXEC_ABORTED, ops.exec_aborted);
2805 push_compact_metric(&mut metrics, ROWS_LOADED, ops.rows_loaded);
2806 push_compact_metric(&mut metrics, ROWS_SAVED, ops.rows_saved);
2807 push_compact_metric(&mut metrics, ROWS_DELETED, ops.rows_deleted);
2808 push_compact_metric(&mut metrics, ROWS_SCANNED, ops.rows_scanned);
2809 push_compact_metric(&mut metrics, ROWS_FILTERED, ops.rows_filtered);
2810 push_compact_metric(&mut metrics, ROWS_EMITTED, ops.rows_emitted);
2811 push_compact_metric(&mut metrics, SQL_INSERT_CALLS, ops.sql_insert_calls);
2812 push_compact_metric(
2813 &mut metrics,
2814 SQL_INSERT_SELECT_CALLS,
2815 ops.sql_insert_select_calls,
2816 );
2817 push_compact_metric(&mut metrics, SQL_UPDATE_CALLS, ops.sql_update_calls);
2818 push_compact_metric(&mut metrics, SQL_DELETE_CALLS, ops.sql_delete_calls);
2819 push_compact_metric(
2820 &mut metrics,
2821 SQL_WRITE_MATCHED_ROWS,
2822 ops.sql_write_matched_rows,
2823 );
2824 push_compact_metric(
2825 &mut metrics,
2826 SQL_WRITE_MUTATED_ROWS,
2827 ops.sql_write_mutated_rows,
2828 );
2829 push_compact_metric(
2830 &mut metrics,
2831 SQL_WRITE_RETURNING_ROWS,
2832 ops.sql_write_returning_rows,
2833 );
2834 push_compact_metric(
2835 &mut metrics,
2836 CACHE_SHARED_QUERY_PLAN_HITS,
2837 ops.cache_shared_query_plan_hits,
2838 );
2839 push_compact_metric(
2840 &mut metrics,
2841 CACHE_SHARED_QUERY_PLAN_MISSES,
2842 ops.cache_shared_query_plan_misses,
2843 );
2844 push_compact_metric(
2845 &mut metrics,
2846 CACHE_SQL_COMPILED_COMMAND_HITS,
2847 ops.cache_sql_compiled_command_hits,
2848 );
2849 push_compact_metric(
2850 &mut metrics,
2851 CACHE_SQL_COMPILED_COMMAND_MISSES,
2852 ops.cache_sql_compiled_command_misses,
2853 );
2854
2855 metrics
2856}
2857
2858#[must_use]
2868pub(super) fn report_window_start(window_start_ms: Option<u64>) -> EventReport {
2869 let snap = with_state(Clone::clone);
2870 if let Some(requested_window_start_ms) = window_start_ms
2871 && requested_window_start_ms > snap.window_start_ms
2872 {
2873 return EventReport::new(
2874 None,
2875 Vec::new(),
2876 false,
2877 window_start_ms,
2878 snap.window_start_ms,
2879 );
2880 }
2881
2882 let mut entity_counters: Vec<EntitySummary> = Vec::new();
2883 for (path, ops) in &snap.entities {
2884 entity_counters.push(entity_summary_from_counters(path, ops));
2885 }
2886
2887 entity_counters.sort_by(|a, b| {
2888 b.activity_score()
2889 .cmp(&a.activity_score())
2890 .then_with(|| b.rows_loaded.cmp(&a.rows_loaded))
2891 .then_with(|| b.rows_saved.cmp(&a.rows_saved))
2892 .then_with(|| b.rows_scanned.cmp(&a.rows_scanned))
2893 .then_with(|| b.rows_deleted.cmp(&a.rows_deleted))
2894 .then_with(|| a.path.cmp(&b.path))
2895 });
2896
2897 EventReport::new(
2898 Some(EventCounters::new(
2899 snap.ops.clone(),
2900 snap.perf.clone(),
2901 snap.window_start_ms,
2902 now_millis(),
2903 )),
2904 entity_counters,
2905 true,
2906 window_start_ms,
2907 snap.window_start_ms,
2908 )
2909}
2910
2911#[must_use]
2913pub(super) fn compact_report_window_start(window_start_ms: Option<u64>) -> CompactMetricsReport {
2914 let snap = with_state(Clone::clone);
2915 if let Some(requested_window_start_ms) = window_start_ms
2916 && requested_window_start_ms > snap.window_start_ms
2917 {
2918 return CompactMetricsReport::new(
2919 None,
2920 Vec::new(),
2921 false,
2922 window_start_ms,
2923 snap.window_start_ms,
2924 );
2925 }
2926
2927 let mut entity_counters: Vec<CompactEntityMetrics> = Vec::new();
2928 for (path, ops) in &snap.entities {
2929 let metrics = compact_entity_metrics(ops);
2930 if !metrics.is_empty() {
2931 entity_counters.push(CompactEntityMetrics::new(path.clone(), metrics));
2932 }
2933 }
2934
2935 entity_counters.sort_by(|a, b| {
2936 let a_activity = compact_metrics_activity(a.metrics());
2937 let b_activity = compact_metrics_activity(b.metrics());
2938 b_activity
2939 .cmp(&a_activity)
2940 .then_with(|| a.path().cmp(b.path()))
2941 });
2942
2943 CompactMetricsReport::new(
2944 Some(CompactEventCounters::new(
2945 compact_event_metrics(&snap.ops),
2946 snap.window_start_ms,
2947 now_millis(),
2948 )),
2949 entity_counters,
2950 true,
2951 window_start_ms,
2952 snap.window_start_ms,
2953 )
2954}
2955
2956fn compact_metrics_activity(metrics: &[CompactMetric]) -> u64 {
2957 metrics
2958 .iter()
2959 .fold(0, |total, metric| total.saturating_add(metric.value()))
2960}