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_branch_set: u64,
155 pub(crate) plan_index_prefix: u64,
156 pub(crate) plan_index_multi_lookup: u64,
157 pub(crate) plan_index_range: u64,
158 pub(crate) plan_explicit_full_scan: u64,
159 pub(crate) plan_union: u64,
160 pub(crate) plan_intersection: u64,
161 pub(crate) plan_grouped_hash_materialized: u64,
162 pub(crate) plan_grouped_ordered_materialized: u64,
163 pub(crate) plan_choice_conflicting_primary_key_children_access_preferred: u64,
164 pub(crate) plan_choice_constant_false_predicate: u64,
165 pub(crate) plan_choice_empty_child_access_preferred: u64,
166 pub(crate) plan_choice_full_scan_access: u64,
167 pub(crate) plan_choice_intent_key_access_override: u64,
168 pub(crate) plan_choice_limit_zero_window: u64,
169 pub(crate) plan_choice_non_index_access: u64,
170 pub(crate) plan_choice_planner_composite_non_index: u64,
171 pub(crate) plan_choice_planner_full_scan_fallback: u64,
172 pub(crate) plan_choice_planner_key_set_access: u64,
173 pub(crate) plan_choice_planner_primary_key_lookup: u64,
174 pub(crate) plan_choice_planner_primary_key_range: u64,
175 pub(crate) plan_choice_required_order_primary_key_range_preferred: u64,
176 pub(crate) plan_choice_singleton_primary_key_child_access_preferred: u64,
177 pub(crate) prepared_shape_already_finalized: u64,
178 pub(crate) prepared_shape_generated_fallback: u64,
179
180 pub(crate) rows_loaded: u64,
182 pub(crate) rows_saved: u64,
183 pub(crate) rows_inserted: u64,
184 pub(crate) rows_updated: u64,
185 pub(crate) rows_replaced: u64,
186 pub(crate) rows_scanned: u64,
187 pub(crate) rows_filtered: u64,
188 pub(crate) rows_aggregated: u64,
189 pub(crate) rows_emitted: u64,
190 pub(crate) load_candidate_rows_scanned: u64,
191 pub(crate) load_candidate_rows_filtered: u64,
192 pub(crate) load_result_rows_emitted: u64,
193 pub(crate) rows_deleted: u64,
194 pub(crate) sql_insert_calls: u64,
195 pub(crate) sql_insert_select_calls: u64,
196 pub(crate) sql_update_calls: u64,
197 pub(crate) sql_delete_calls: u64,
198 pub(crate) sql_write_staged_rows: u64,
199 pub(crate) sql_write_matched_rows: u64,
200 pub(crate) sql_write_mutated_rows: u64,
201 pub(crate) sql_write_returning_rows: u64,
202 pub(crate) sql_write_error_insert: u64,
203 pub(crate) sql_write_error_insert_select: u64,
204 pub(crate) sql_write_error_update: u64,
205 pub(crate) sql_write_error_delete: u64,
206 pub(crate) sql_write_error_corruption: u64,
207 pub(crate) sql_write_error_incompatible_persisted_format: u64,
208 pub(crate) sql_write_error_not_found: u64,
209 pub(crate) sql_write_error_internal: u64,
210 pub(crate) sql_write_error_conflict: u64,
211 pub(crate) sql_write_error_unsupported: u64,
212 pub(crate) sql_write_error_invariant_violation: u64,
213
214 pub(crate) index_inserts: u64,
216 pub(crate) index_removes: u64,
217 pub(crate) reverse_index_inserts: u64,
218 pub(crate) reverse_index_removes: u64,
219 pub(crate) relation_reverse_lookups: u64,
220 pub(crate) relation_delete_blocks: u64,
221 pub(crate) write_rows_touched: u64,
222 pub(crate) write_index_entries_changed: u64,
223 pub(crate) write_reverse_index_entries_changed: u64,
224 pub(crate) write_relation_checks: u64,
225 pub(crate) unique_violations: u64,
226 pub(crate) non_atomic_partial_commits: u64,
227 pub(crate) non_atomic_partial_rows_committed: u64,
228}
229
230impl EventOps {
231 #[must_use]
232 pub const fn load_calls(&self) -> u64 {
233 self.load_calls
234 }
235
236 #[must_use]
237 pub const fn save_calls(&self) -> u64 {
238 self.save_calls
239 }
240
241 #[must_use]
242 pub const fn delete_calls(&self) -> u64 {
243 self.delete_calls
244 }
245
246 #[must_use]
247 pub const fn save_insert_calls(&self) -> u64 {
248 self.save_insert_calls
249 }
250
251 #[must_use]
252 pub const fn save_update_calls(&self) -> u64 {
253 self.save_update_calls
254 }
255
256 #[must_use]
257 pub const fn save_replace_calls(&self) -> u64 {
258 self.save_replace_calls
259 }
260
261 #[must_use]
262 pub const fn exec_success(&self) -> u64 {
263 self.exec_success
264 }
265
266 #[must_use]
267 pub const fn exec_error_corruption(&self) -> u64 {
268 self.exec_error_corruption
269 }
270
271 #[must_use]
272 pub const fn exec_error_incompatible_persisted_format(&self) -> u64 {
273 self.exec_error_incompatible_persisted_format
274 }
275
276 #[must_use]
277 pub const fn exec_error_not_found(&self) -> u64 {
278 self.exec_error_not_found
279 }
280
281 #[must_use]
282 pub const fn exec_error_internal(&self) -> u64 {
283 self.exec_error_internal
284 }
285
286 #[must_use]
287 pub const fn exec_error_conflict(&self) -> u64 {
288 self.exec_error_conflict
289 }
290
291 #[must_use]
292 pub const fn exec_error_unsupported(&self) -> u64 {
293 self.exec_error_unsupported
294 }
295
296 #[must_use]
297 pub const fn exec_error_invariant_violation(&self) -> u64 {
298 self.exec_error_invariant_violation
299 }
300
301 #[must_use]
302 pub const fn exec_aborted(&self) -> u64 {
303 self.exec_aborted
304 }
305
306 #[must_use]
307 pub const fn cache_shared_query_plan_hits(&self) -> u64 {
308 self.cache_shared_query_plan_hits
309 }
310
311 #[must_use]
312 pub const fn cache_shared_query_plan_misses(&self) -> u64 {
313 self.cache_shared_query_plan_misses
314 }
315
316 #[must_use]
317 pub const fn cache_shared_query_plan_inserts(&self) -> u64 {
318 self.cache_shared_query_plan_inserts
319 }
320
321 #[must_use]
322 pub const fn cache_shared_query_plan_entries(&self) -> u64 {
323 self.cache_shared_query_plan_entries
324 }
325
326 #[must_use]
327 pub const fn cache_shared_query_plan_miss_cold(&self) -> u64 {
328 self.cache_shared_query_plan_miss_cold
329 }
330
331 #[must_use]
332 pub const fn cache_shared_query_plan_miss_distinct_key(&self) -> u64 {
333 self.cache_shared_query_plan_miss_distinct_key
334 }
335
336 #[must_use]
337 pub const fn cache_shared_query_plan_miss_method_version(&self) -> u64 {
338 self.cache_shared_query_plan_miss_method_version
339 }
340
341 #[must_use]
342 pub const fn cache_shared_query_plan_miss_schema_fingerprint(&self) -> u64 {
343 self.cache_shared_query_plan_miss_schema_fingerprint
344 }
345
346 #[must_use]
347 pub const fn cache_shared_query_plan_miss_visibility(&self) -> u64 {
348 self.cache_shared_query_plan_miss_visibility
349 }
350
351 #[must_use]
352 pub const fn cache_sql_compiled_command_hits(&self) -> u64 {
353 self.cache_sql_compiled_command_hits
354 }
355
356 #[must_use]
357 pub const fn cache_sql_compiled_command_misses(&self) -> u64 {
358 self.cache_sql_compiled_command_misses
359 }
360
361 #[must_use]
362 pub const fn cache_sql_compiled_command_inserts(&self) -> u64 {
363 self.cache_sql_compiled_command_inserts
364 }
365
366 #[must_use]
367 pub const fn cache_sql_compiled_command_entries(&self) -> u64 {
368 self.cache_sql_compiled_command_entries
369 }
370
371 #[must_use]
372 pub const fn cache_sql_compiled_command_miss_cold(&self) -> u64 {
373 self.cache_sql_compiled_command_miss_cold
374 }
375
376 #[must_use]
377 pub const fn cache_sql_compiled_command_miss_distinct_key(&self) -> u64 {
378 self.cache_sql_compiled_command_miss_distinct_key
379 }
380
381 #[must_use]
382 pub const fn cache_sql_compiled_command_miss_method_version(&self) -> u64 {
383 self.cache_sql_compiled_command_miss_method_version
384 }
385
386 #[must_use]
387 pub const fn cache_sql_compiled_command_miss_schema_fingerprint(&self) -> u64 {
388 self.cache_sql_compiled_command_miss_schema_fingerprint
389 }
390
391 #[must_use]
392 pub const fn cache_sql_compiled_command_miss_surface(&self) -> u64 {
393 self.cache_sql_compiled_command_miss_surface
394 }
395
396 #[must_use]
397 pub const fn schema_reconcile_checks(&self) -> u64 {
398 self.schema_reconcile_checks
399 }
400
401 #[must_use]
402 pub const fn schema_reconcile_exact_match(&self) -> u64 {
403 self.schema_reconcile_exact_match
404 }
405
406 #[must_use]
407 pub const fn schema_reconcile_first_create(&self) -> u64 {
408 self.schema_reconcile_first_create
409 }
410
411 #[must_use]
412 pub const fn schema_reconcile_latest_snapshot_corrupt(&self) -> u64 {
413 self.schema_reconcile_latest_snapshot_corrupt
414 }
415
416 #[must_use]
417 pub const fn schema_reconcile_rejected_field_slot(&self) -> u64 {
418 self.schema_reconcile_rejected_field_slot
419 }
420
421 #[must_use]
422 pub const fn schema_reconcile_rejected_other(&self) -> u64 {
423 self.schema_reconcile_rejected_other
424 }
425
426 #[must_use]
427 pub const fn schema_reconcile_rejected_row_layout(&self) -> u64 {
428 self.schema_reconcile_rejected_row_layout
429 }
430
431 #[must_use]
432 pub const fn schema_reconcile_rejected_schema_version(&self) -> u64 {
433 self.schema_reconcile_rejected_schema_version
434 }
435
436 #[must_use]
437 pub const fn schema_reconcile_store_write_error(&self) -> u64 {
438 self.schema_reconcile_store_write_error
439 }
440
441 #[must_use]
442 pub const fn schema_transition_checks(&self) -> u64 {
443 self.schema_transition_checks
444 }
445
446 #[must_use]
447 pub const fn schema_transition_append_only_nullable_fields(&self) -> u64 {
448 self.schema_transition_append_only_nullable_fields
449 }
450
451 #[must_use]
452 pub const fn schema_transition_exact_match(&self) -> u64 {
453 self.schema_transition_exact_match
454 }
455
456 #[must_use]
457 pub const fn schema_transition_rejected_entity_identity(&self) -> u64 {
458 self.schema_transition_rejected_entity_identity
459 }
460
461 #[must_use]
462 pub const fn schema_transition_rejected_field_contract(&self) -> u64 {
463 self.schema_transition_rejected_field_contract
464 }
465
466 #[must_use]
467 pub const fn schema_transition_rejected_field_slot(&self) -> u64 {
468 self.schema_transition_rejected_field_slot
469 }
470
471 #[must_use]
472 pub const fn schema_transition_rejected_row_layout(&self) -> u64 {
473 self.schema_transition_rejected_row_layout
474 }
475
476 #[must_use]
477 pub const fn schema_transition_rejected_schema_version(&self) -> u64 {
478 self.schema_transition_rejected_schema_version
479 }
480
481 #[must_use]
482 pub const fn schema_transition_rejected_snapshot(&self) -> u64 {
483 self.schema_transition_rejected_snapshot
484 }
485
486 #[must_use]
487 pub const fn schema_store_snapshots(&self) -> u64 {
488 self.schema_store_snapshots
489 }
490
491 #[must_use]
492 pub const fn schema_store_encoded_bytes(&self) -> u64 {
493 self.schema_store_encoded_bytes
494 }
495
496 #[must_use]
497 pub const fn schema_store_latest_snapshot_bytes(&self) -> u64 {
498 self.schema_store_latest_snapshot_bytes
499 }
500
501 #[must_use]
502 pub const fn accepted_schema_fields(&self) -> u64 {
503 self.accepted_schema_fields
504 }
505
506 #[must_use]
507 pub const fn accepted_schema_nested_leaf_facts(&self) -> u64 {
508 self.accepted_schema_nested_leaf_facts
509 }
510
511 #[must_use]
512 pub const fn sql_compile_rejects(&self) -> u64 {
513 self.sql_compile_rejects
514 }
515
516 #[must_use]
517 pub const fn sql_compile_reject_cache_key(&self) -> u64 {
518 self.sql_compile_reject_cache_key
519 }
520
521 #[must_use]
522 pub const fn sql_compile_reject_parse(&self) -> u64 {
523 self.sql_compile_reject_parse
524 }
525
526 #[must_use]
527 pub const fn sql_compile_reject_semantic(&self) -> u64 {
528 self.sql_compile_reject_semantic
529 }
530
531 #[must_use]
532 pub const fn plan_index(&self) -> u64 {
533 self.plan_index
534 }
535
536 #[must_use]
537 pub const fn plan_keys(&self) -> u64 {
538 self.plan_keys
539 }
540
541 #[must_use]
542 pub const fn plan_range(&self) -> u64 {
543 self.plan_range
544 }
545
546 #[must_use]
547 pub const fn plan_full_scan(&self) -> u64 {
548 self.plan_full_scan
549 }
550
551 #[must_use]
552 pub const fn plan_by_key(&self) -> u64 {
553 self.plan_by_key
554 }
555
556 #[must_use]
557 pub const fn plan_by_keys(&self) -> u64 {
558 self.plan_by_keys
559 }
560
561 #[must_use]
562 pub const fn plan_key_range(&self) -> u64 {
563 self.plan_key_range
564 }
565
566 #[must_use]
567 pub const fn plan_index_branch_set(&self) -> u64 {
568 self.plan_index_branch_set
569 }
570
571 #[must_use]
572 pub const fn plan_index_prefix(&self) -> u64 {
573 self.plan_index_prefix
574 }
575
576 #[must_use]
577 pub const fn plan_index_multi_lookup(&self) -> u64 {
578 self.plan_index_multi_lookup
579 }
580
581 #[must_use]
582 pub const fn plan_index_range(&self) -> u64 {
583 self.plan_index_range
584 }
585
586 #[must_use]
587 pub const fn plan_explicit_full_scan(&self) -> u64 {
588 self.plan_explicit_full_scan
589 }
590
591 #[must_use]
592 pub const fn plan_union(&self) -> u64 {
593 self.plan_union
594 }
595
596 #[must_use]
597 pub const fn plan_intersection(&self) -> u64 {
598 self.plan_intersection
599 }
600
601 #[must_use]
602 pub const fn plan_grouped_hash_materialized(&self) -> u64 {
603 self.plan_grouped_hash_materialized
604 }
605
606 #[must_use]
607 pub const fn plan_grouped_ordered_materialized(&self) -> u64 {
608 self.plan_grouped_ordered_materialized
609 }
610
611 #[must_use]
612 pub const fn plan_choice_conflicting_primary_key_children_access_preferred(&self) -> u64 {
613 self.plan_choice_conflicting_primary_key_children_access_preferred
614 }
615
616 #[must_use]
617 pub const fn plan_choice_constant_false_predicate(&self) -> u64 {
618 self.plan_choice_constant_false_predicate
619 }
620
621 #[must_use]
622 pub const fn plan_choice_empty_child_access_preferred(&self) -> u64 {
623 self.plan_choice_empty_child_access_preferred
624 }
625
626 #[must_use]
627 pub const fn plan_choice_full_scan_access(&self) -> u64 {
628 self.plan_choice_full_scan_access
629 }
630
631 #[must_use]
632 pub const fn plan_choice_intent_key_access_override(&self) -> u64 {
633 self.plan_choice_intent_key_access_override
634 }
635
636 #[must_use]
637 pub const fn plan_choice_limit_zero_window(&self) -> u64 {
638 self.plan_choice_limit_zero_window
639 }
640
641 #[must_use]
642 pub const fn plan_choice_non_index_access(&self) -> u64 {
643 self.plan_choice_non_index_access
644 }
645
646 #[must_use]
647 pub const fn plan_choice_planner_composite_non_index(&self) -> u64 {
648 self.plan_choice_planner_composite_non_index
649 }
650
651 #[must_use]
652 pub const fn plan_choice_planner_full_scan_fallback(&self) -> u64 {
653 self.plan_choice_planner_full_scan_fallback
654 }
655
656 #[must_use]
657 pub const fn plan_choice_planner_key_set_access(&self) -> u64 {
658 self.plan_choice_planner_key_set_access
659 }
660
661 #[must_use]
662 pub const fn plan_choice_planner_primary_key_lookup(&self) -> u64 {
663 self.plan_choice_planner_primary_key_lookup
664 }
665
666 #[must_use]
667 pub const fn plan_choice_planner_primary_key_range(&self) -> u64 {
668 self.plan_choice_planner_primary_key_range
669 }
670
671 #[must_use]
672 pub const fn plan_choice_required_order_primary_key_range_preferred(&self) -> u64 {
673 self.plan_choice_required_order_primary_key_range_preferred
674 }
675
676 #[must_use]
677 pub const fn plan_choice_singleton_primary_key_child_access_preferred(&self) -> u64 {
678 self.plan_choice_singleton_primary_key_child_access_preferred
679 }
680
681 #[must_use]
682 pub const fn prepared_shape_already_finalized(&self) -> u64 {
683 self.prepared_shape_already_finalized
684 }
685
686 #[must_use]
687 pub const fn prepared_shape_generated_fallback(&self) -> u64 {
688 self.prepared_shape_generated_fallback
689 }
690
691 #[must_use]
692 pub const fn rows_loaded(&self) -> u64 {
693 self.rows_loaded
694 }
695
696 #[must_use]
697 pub const fn rows_saved(&self) -> u64 {
698 self.rows_saved
699 }
700
701 #[must_use]
702 pub const fn rows_inserted(&self) -> u64 {
703 self.rows_inserted
704 }
705
706 #[must_use]
707 pub const fn rows_updated(&self) -> u64 {
708 self.rows_updated
709 }
710
711 #[must_use]
712 pub const fn rows_replaced(&self) -> u64 {
713 self.rows_replaced
714 }
715
716 #[must_use]
717 pub const fn rows_scanned(&self) -> u64 {
718 self.rows_scanned
719 }
720
721 #[must_use]
722 pub const fn rows_filtered(&self) -> u64 {
723 self.rows_filtered
724 }
725
726 #[must_use]
727 pub const fn rows_aggregated(&self) -> u64 {
728 self.rows_aggregated
729 }
730
731 #[must_use]
732 pub const fn rows_emitted(&self) -> u64 {
733 self.rows_emitted
734 }
735
736 #[must_use]
737 pub const fn load_candidate_rows_scanned(&self) -> u64 {
738 self.load_candidate_rows_scanned
739 }
740
741 #[must_use]
742 pub const fn load_candidate_rows_filtered(&self) -> u64 {
743 self.load_candidate_rows_filtered
744 }
745
746 #[must_use]
747 pub const fn load_result_rows_emitted(&self) -> u64 {
748 self.load_result_rows_emitted
749 }
750
751 #[must_use]
752 pub const fn rows_deleted(&self) -> u64 {
753 self.rows_deleted
754 }
755
756 #[must_use]
757 pub const fn sql_insert_calls(&self) -> u64 {
758 self.sql_insert_calls
759 }
760
761 #[must_use]
762 pub const fn sql_insert_select_calls(&self) -> u64 {
763 self.sql_insert_select_calls
764 }
765
766 #[must_use]
767 pub const fn sql_update_calls(&self) -> u64 {
768 self.sql_update_calls
769 }
770
771 #[must_use]
772 pub const fn sql_delete_calls(&self) -> u64 {
773 self.sql_delete_calls
774 }
775
776 #[must_use]
777 pub const fn sql_write_staged_rows(&self) -> u64 {
778 self.sql_write_staged_rows
779 }
780
781 #[must_use]
782 pub const fn sql_write_matched_rows(&self) -> u64 {
783 self.sql_write_matched_rows
784 }
785
786 #[must_use]
787 pub const fn sql_write_mutated_rows(&self) -> u64 {
788 self.sql_write_mutated_rows
789 }
790
791 #[must_use]
792 pub const fn sql_write_returning_rows(&self) -> u64 {
793 self.sql_write_returning_rows
794 }
795
796 #[must_use]
797 pub const fn sql_write_error_insert(&self) -> u64 {
798 self.sql_write_error_insert
799 }
800
801 #[must_use]
802 pub const fn sql_write_error_insert_select(&self) -> u64 {
803 self.sql_write_error_insert_select
804 }
805
806 #[must_use]
807 pub const fn sql_write_error_update(&self) -> u64 {
808 self.sql_write_error_update
809 }
810
811 #[must_use]
812 pub const fn sql_write_error_delete(&self) -> u64 {
813 self.sql_write_error_delete
814 }
815
816 #[must_use]
817 pub const fn sql_write_error_corruption(&self) -> u64 {
818 self.sql_write_error_corruption
819 }
820
821 #[must_use]
822 pub const fn sql_write_error_incompatible_persisted_format(&self) -> u64 {
823 self.sql_write_error_incompatible_persisted_format
824 }
825
826 #[must_use]
827 pub const fn sql_write_error_not_found(&self) -> u64 {
828 self.sql_write_error_not_found
829 }
830
831 #[must_use]
832 pub const fn sql_write_error_internal(&self) -> u64 {
833 self.sql_write_error_internal
834 }
835
836 #[must_use]
837 pub const fn sql_write_error_conflict(&self) -> u64 {
838 self.sql_write_error_conflict
839 }
840
841 #[must_use]
842 pub const fn sql_write_error_unsupported(&self) -> u64 {
843 self.sql_write_error_unsupported
844 }
845
846 #[must_use]
847 pub const fn sql_write_error_invariant_violation(&self) -> u64 {
848 self.sql_write_error_invariant_violation
849 }
850
851 #[must_use]
852 pub const fn index_inserts(&self) -> u64 {
853 self.index_inserts
854 }
855
856 #[must_use]
857 pub const fn index_removes(&self) -> u64 {
858 self.index_removes
859 }
860
861 #[must_use]
862 pub const fn reverse_index_inserts(&self) -> u64 {
863 self.reverse_index_inserts
864 }
865
866 #[must_use]
867 pub const fn reverse_index_removes(&self) -> u64 {
868 self.reverse_index_removes
869 }
870
871 #[must_use]
872 pub const fn relation_reverse_lookups(&self) -> u64 {
873 self.relation_reverse_lookups
874 }
875
876 #[must_use]
877 pub const fn relation_delete_blocks(&self) -> u64 {
878 self.relation_delete_blocks
879 }
880
881 #[must_use]
882 pub const fn write_rows_touched(&self) -> u64 {
883 self.write_rows_touched
884 }
885
886 #[must_use]
887 pub const fn write_index_entries_changed(&self) -> u64 {
888 self.write_index_entries_changed
889 }
890
891 #[must_use]
892 pub const fn write_reverse_index_entries_changed(&self) -> u64 {
893 self.write_reverse_index_entries_changed
894 }
895
896 #[must_use]
897 pub const fn write_relation_checks(&self) -> u64 {
898 self.write_relation_checks
899 }
900
901 #[must_use]
902 pub const fn unique_violations(&self) -> u64 {
903 self.unique_violations
904 }
905
906 #[must_use]
907 pub const fn non_atomic_partial_commits(&self) -> u64 {
908 self.non_atomic_partial_commits
909 }
910
911 #[must_use]
912 pub const fn non_atomic_partial_rows_committed(&self) -> u64 {
913 self.non_atomic_partial_rows_committed
914 }
915
916 #[must_use]
918 pub const fn load_selectivity_ratio(&self) -> Option<MetricRatio> {
919 ratio(
920 self.load_result_rows_emitted,
921 self.load_candidate_rows_scanned,
922 )
923 }
924
925 #[must_use]
927 pub const fn load_filter_ratio(&self) -> Option<MetricRatio> {
928 ratio(
929 self.load_candidate_rows_filtered,
930 self.load_candidate_rows_scanned,
931 )
932 }
933
934 #[must_use]
936 pub const fn sql_write_mutation_ratio(&self) -> Option<MetricRatio> {
937 ratio(self.sql_write_mutated_rows, self.sql_write_matched_rows)
938 }
939
940 #[must_use]
942 pub const fn sql_write_returning_ratio(&self) -> Option<MetricRatio> {
943 ratio(self.sql_write_returning_rows, self.sql_write_mutated_rows)
944 }
945
946 #[must_use]
948 pub const fn write_index_entries_per_row(&self) -> Option<MetricRatio> {
949 ratio(self.write_index_entries_changed, self.write_rows_touched)
950 }
951
952 #[must_use]
954 pub const fn write_reverse_index_entries_per_row(&self) -> Option<MetricRatio> {
955 ratio(
956 self.write_reverse_index_entries_changed,
957 self.write_rows_touched,
958 )
959 }
960
961 #[must_use]
963 pub const fn write_relation_checks_per_row(&self) -> Option<MetricRatio> {
964 ratio(self.write_relation_checks, self.write_rows_touched)
965 }
966}
967
968#[derive(Clone, Debug, Default)]
969pub(crate) struct EntityCounters {
970 pub(crate) load_calls: u64,
971 pub(crate) save_calls: u64,
972 pub(crate) delete_calls: u64,
973 pub(crate) save_insert_calls: u64,
974 pub(crate) save_update_calls: u64,
975 pub(crate) save_replace_calls: u64,
976 pub(crate) exec_success: u64,
977 pub(crate) exec_error_corruption: u64,
978 pub(crate) exec_error_incompatible_persisted_format: u64,
979 pub(crate) exec_error_not_found: u64,
980 pub(crate) exec_error_internal: u64,
981 pub(crate) exec_error_conflict: u64,
982 pub(crate) exec_error_unsupported: u64,
983 pub(crate) exec_error_invariant_violation: u64,
984 pub(crate) exec_aborted: u64,
985 pub(crate) cache_shared_query_plan_hits: u64,
986 pub(crate) cache_shared_query_plan_misses: u64,
987 pub(crate) cache_shared_query_plan_inserts: u64,
988 pub(crate) cache_shared_query_plan_miss_cold: u64,
989 pub(crate) cache_shared_query_plan_miss_distinct_key: u64,
990 pub(crate) cache_shared_query_plan_miss_method_version: u64,
991 pub(crate) cache_shared_query_plan_miss_schema_fingerprint: u64,
992 pub(crate) cache_shared_query_plan_miss_visibility: u64,
993 pub(crate) cache_sql_compiled_command_hits: u64,
994 pub(crate) cache_sql_compiled_command_misses: u64,
995 pub(crate) cache_sql_compiled_command_inserts: u64,
996 pub(crate) cache_sql_compiled_command_miss_cold: u64,
997 pub(crate) cache_sql_compiled_command_miss_distinct_key: u64,
998 pub(crate) cache_sql_compiled_command_miss_method_version: u64,
999 pub(crate) cache_sql_compiled_command_miss_schema_fingerprint: u64,
1000 pub(crate) cache_sql_compiled_command_miss_surface: u64,
1001 pub(crate) schema_reconcile_checks: u64,
1002 pub(crate) schema_reconcile_exact_match: u64,
1003 pub(crate) schema_reconcile_first_create: u64,
1004 pub(crate) schema_reconcile_latest_snapshot_corrupt: u64,
1005 pub(crate) schema_reconcile_rejected_field_slot: u64,
1006 pub(crate) schema_reconcile_rejected_other: u64,
1007 pub(crate) schema_reconcile_rejected_row_layout: u64,
1008 pub(crate) schema_reconcile_rejected_schema_version: u64,
1009 pub(crate) schema_reconcile_store_write_error: u64,
1010 pub(crate) schema_transition_checks: u64,
1011 pub(crate) schema_transition_append_only_nullable_fields: u64,
1012 pub(crate) schema_transition_exact_match: u64,
1013 pub(crate) schema_transition_rejected_entity_identity: u64,
1014 pub(crate) schema_transition_rejected_field_contract: u64,
1015 pub(crate) schema_transition_rejected_field_slot: u64,
1016 pub(crate) schema_transition_rejected_row_layout: u64,
1017 pub(crate) schema_transition_rejected_schema_version: u64,
1018 pub(crate) schema_transition_rejected_snapshot: u64,
1019 pub(crate) schema_store_snapshots: u64,
1020 pub(crate) schema_store_encoded_bytes: u64,
1021 pub(crate) schema_store_latest_snapshot_bytes: u64,
1022 pub(crate) accepted_schema_fields: u64,
1023 pub(crate) accepted_schema_nested_leaf_facts: u64,
1024 pub(crate) sql_compile_rejects: u64,
1025 pub(crate) sql_compile_reject_cache_key: u64,
1026 pub(crate) sql_compile_reject_parse: u64,
1027 pub(crate) sql_compile_reject_semantic: u64,
1028 pub(crate) plan_index: u64,
1029 pub(crate) plan_keys: u64,
1030 pub(crate) plan_range: u64,
1031 pub(crate) plan_full_scan: u64,
1032 pub(crate) plan_by_key: u64,
1033 pub(crate) plan_by_keys: u64,
1034 pub(crate) plan_key_range: u64,
1035 pub(crate) plan_index_branch_set: u64,
1036 pub(crate) plan_index_prefix: u64,
1037 pub(crate) plan_index_multi_lookup: u64,
1038 pub(crate) plan_index_range: u64,
1039 pub(crate) plan_explicit_full_scan: u64,
1040 pub(crate) plan_union: u64,
1041 pub(crate) plan_intersection: u64,
1042 pub(crate) plan_grouped_hash_materialized: u64,
1043 pub(crate) plan_grouped_ordered_materialized: u64,
1044 pub(crate) plan_choice_conflicting_primary_key_children_access_preferred: u64,
1045 pub(crate) plan_choice_constant_false_predicate: u64,
1046 pub(crate) plan_choice_empty_child_access_preferred: u64,
1047 pub(crate) plan_choice_full_scan_access: u64,
1048 pub(crate) plan_choice_intent_key_access_override: u64,
1049 pub(crate) plan_choice_limit_zero_window: u64,
1050 pub(crate) plan_choice_non_index_access: u64,
1051 pub(crate) plan_choice_planner_composite_non_index: u64,
1052 pub(crate) plan_choice_planner_full_scan_fallback: u64,
1053 pub(crate) plan_choice_planner_key_set_access: u64,
1054 pub(crate) plan_choice_planner_primary_key_lookup: u64,
1055 pub(crate) plan_choice_planner_primary_key_range: u64,
1056 pub(crate) plan_choice_required_order_primary_key_range_preferred: u64,
1057 pub(crate) plan_choice_singleton_primary_key_child_access_preferred: u64,
1058 pub(crate) prepared_shape_already_finalized: u64,
1059 pub(crate) prepared_shape_generated_fallback: u64,
1060 pub(crate) rows_loaded: u64,
1061 pub(crate) rows_saved: u64,
1062 pub(crate) rows_inserted: u64,
1063 pub(crate) rows_updated: u64,
1064 pub(crate) rows_replaced: u64,
1065 pub(crate) rows_scanned: u64,
1066 pub(crate) rows_filtered: u64,
1067 pub(crate) rows_aggregated: u64,
1068 pub(crate) rows_emitted: u64,
1069 pub(crate) load_candidate_rows_scanned: u64,
1070 pub(crate) load_candidate_rows_filtered: u64,
1071 pub(crate) load_result_rows_emitted: u64,
1072 pub(crate) rows_deleted: u64,
1073 pub(crate) sql_insert_calls: u64,
1074 pub(crate) sql_insert_select_calls: u64,
1075 pub(crate) sql_update_calls: u64,
1076 pub(crate) sql_delete_calls: u64,
1077 pub(crate) sql_write_staged_rows: u64,
1078 pub(crate) sql_write_matched_rows: u64,
1079 pub(crate) sql_write_mutated_rows: u64,
1080 pub(crate) sql_write_returning_rows: u64,
1081 pub(crate) sql_write_error_insert: u64,
1082 pub(crate) sql_write_error_insert_select: u64,
1083 pub(crate) sql_write_error_update: u64,
1084 pub(crate) sql_write_error_delete: u64,
1085 pub(crate) sql_write_error_corruption: u64,
1086 pub(crate) sql_write_error_incompatible_persisted_format: u64,
1087 pub(crate) sql_write_error_not_found: u64,
1088 pub(crate) sql_write_error_internal: u64,
1089 pub(crate) sql_write_error_conflict: u64,
1090 pub(crate) sql_write_error_unsupported: u64,
1091 pub(crate) sql_write_error_invariant_violation: u64,
1092 pub(crate) index_inserts: u64,
1093 pub(crate) index_removes: u64,
1094 pub(crate) reverse_index_inserts: u64,
1095 pub(crate) reverse_index_removes: u64,
1096 pub(crate) relation_reverse_lookups: u64,
1097 pub(crate) relation_delete_blocks: u64,
1098 pub(crate) write_rows_touched: u64,
1099 pub(crate) write_index_entries_changed: u64,
1100 pub(crate) write_reverse_index_entries_changed: u64,
1101 pub(crate) write_relation_checks: u64,
1102 pub(crate) unique_violations: u64,
1103 pub(crate) non_atomic_partial_commits: u64,
1104 pub(crate) non_atomic_partial_rows_committed: u64,
1105}
1106
1107#[cfg_attr(doc, doc = "EventPerf\n\nInstruction totals and maxima.")]
1108#[derive(CandidType, Clone, Debug, Default, Deserialize)]
1109pub struct EventPerf {
1110 pub(crate) load_inst_total: u128,
1112 pub(crate) save_inst_total: u128,
1113 pub(crate) delete_inst_total: u128,
1114
1115 pub(crate) load_inst_max: u64,
1117 pub(crate) save_inst_max: u64,
1118 pub(crate) delete_inst_max: u64,
1119}
1120
1121impl EventPerf {
1122 #[must_use]
1123 pub const fn new(
1124 load_inst_total: u128,
1125 save_inst_total: u128,
1126 delete_inst_total: u128,
1127 load_inst_max: u64,
1128 save_inst_max: u64,
1129 delete_inst_max: u64,
1130 ) -> Self {
1131 Self {
1132 load_inst_total,
1133 save_inst_total,
1134 delete_inst_total,
1135 load_inst_max,
1136 save_inst_max,
1137 delete_inst_max,
1138 }
1139 }
1140
1141 #[must_use]
1142 pub const fn load_inst_total(&self) -> u128 {
1143 self.load_inst_total
1144 }
1145
1146 #[must_use]
1147 pub const fn save_inst_total(&self) -> u128 {
1148 self.save_inst_total
1149 }
1150
1151 #[must_use]
1152 pub const fn delete_inst_total(&self) -> u128 {
1153 self.delete_inst_total
1154 }
1155
1156 #[must_use]
1157 pub const fn load_inst_max(&self) -> u64 {
1158 self.load_inst_max
1159 }
1160
1161 #[must_use]
1162 pub const fn save_inst_max(&self) -> u64 {
1163 self.save_inst_max
1164 }
1165
1166 #[must_use]
1167 pub const fn delete_inst_max(&self) -> u64 {
1168 self.delete_inst_max
1169 }
1170}
1171
1172thread_local! {
1173 static EVENT_STATE: RefCell<EventState> = RefCell::new(EventState::default());
1174}
1175
1176pub(crate) fn with_state<R>(f: impl FnOnce(&EventState) -> R) -> R {
1178 EVENT_STATE.with(|m| f(&m.borrow()))
1179}
1180
1181pub(crate) fn with_state_mut<R>(f: impl FnOnce(&mut EventState) -> R) -> R {
1183 EVENT_STATE.with(|m| f(&mut m.borrow_mut()))
1184}
1185
1186pub(super) fn reset() {
1188 with_state_mut(|m| *m = EventState::default());
1189}
1190
1191pub(crate) fn reset_all() {
1193 reset();
1194}
1195
1196pub(super) fn add_instructions(total: &mut u128, max: &mut u64, delta_inst: u64) {
1198 *total = total.saturating_add(u128::from(delta_inst));
1199 if delta_inst > *max {
1200 *max = delta_inst;
1201 }
1202}
1203
1204#[cfg_attr(doc, doc = "EventReport\n\nMetrics query payload.")]
1205#[derive(CandidType, Clone, Debug, Default, Deserialize)]
1206pub struct EventReport {
1207 counters: Option<EventCounters>,
1208 entity_counters: Vec<EntitySummary>,
1209 window_filter_matched: bool,
1210 requested_window_start_ms: Option<u64>,
1211 active_window_start_ms: u64,
1212}
1213
1214impl EventReport {
1215 #[must_use]
1216 pub(crate) const fn new(
1217 counters: Option<EventCounters>,
1218 entity_counters: Vec<EntitySummary>,
1219 window_filter_matched: bool,
1220 requested_window_start_ms: Option<u64>,
1221 active_window_start_ms: u64,
1222 ) -> Self {
1223 Self {
1224 counters,
1225 entity_counters,
1226 window_filter_matched,
1227 requested_window_start_ms,
1228 active_window_start_ms,
1229 }
1230 }
1231
1232 #[must_use]
1233 pub const fn counters(&self) -> Option<&EventCounters> {
1234 self.counters.as_ref()
1235 }
1236
1237 #[must_use]
1238 pub fn entity_counters(&self) -> &[EntitySummary] {
1239 &self.entity_counters
1240 }
1241
1242 #[must_use]
1243 pub const fn window_filter_matched(&self) -> bool {
1244 self.window_filter_matched
1245 }
1246
1247 #[must_use]
1248 pub const fn requested_window_start_ms(&self) -> Option<u64> {
1249 self.requested_window_start_ms
1250 }
1251
1252 #[must_use]
1253 pub const fn active_window_start_ms(&self) -> u64 {
1254 self.active_window_start_ms
1255 }
1256
1257 #[must_use]
1258 pub fn into_counters(self) -> Option<EventCounters> {
1259 self.counters
1260 }
1261
1262 #[must_use]
1263 pub fn into_entity_counters(self) -> Vec<EntitySummary> {
1264 self.entity_counters
1265 }
1266}
1267
1268pub mod compact_metric_code {
1274 pub const LOAD_CALLS: u16 = 1;
1276 pub const SAVE_CALLS: u16 = 2;
1278 pub const DELETE_CALLS: u16 = 3;
1280 pub const EXEC_SUCCESS: u16 = 4;
1282 pub const EXEC_ERRORS: u16 = 5;
1284 pub const EXEC_ABORTED: u16 = 6;
1286 pub const ROWS_LOADED: u16 = 7;
1288 pub const ROWS_SAVED: u16 = 8;
1290 pub const ROWS_DELETED: u16 = 9;
1292 pub const ROWS_SCANNED: u16 = 10;
1294 pub const ROWS_FILTERED: u16 = 11;
1296 pub const ROWS_EMITTED: u16 = 12;
1298 pub const SQL_INSERT_CALLS: u16 = 13;
1300 pub const SQL_INSERT_SELECT_CALLS: u16 = 14;
1302 pub const SQL_UPDATE_CALLS: u16 = 15;
1304 pub const SQL_DELETE_CALLS: u16 = 16;
1306 pub const SQL_WRITE_MATCHED_ROWS: u16 = 17;
1308 pub const SQL_WRITE_MUTATED_ROWS: u16 = 18;
1310 pub const SQL_WRITE_RETURNING_ROWS: u16 = 19;
1312 pub const CACHE_SHARED_QUERY_PLAN_HITS: u16 = 20;
1314 pub const CACHE_SHARED_QUERY_PLAN_MISSES: u16 = 21;
1316 pub const CACHE_SQL_COMPILED_COMMAND_HITS: u16 = 22;
1318 pub const CACHE_SQL_COMPILED_COMMAND_MISSES: u16 = 23;
1320 pub const SQL_WRITE_STAGED_ROWS: u16 = 24;
1322}
1323
1324#[cfg_attr(doc, doc = "CompactMetric\n\nCompact metrics counter.")]
1325#[derive(CandidType, Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq)]
1326pub struct CompactMetric(u16, u64);
1327
1328impl CompactMetric {
1329 #[must_use]
1330 pub(crate) const fn new(code: u16, value: u64) -> Self {
1331 Self(code, value)
1332 }
1333
1334 #[must_use]
1336 pub const fn code(&self) -> u16 {
1337 self.0
1338 }
1339
1340 #[must_use]
1342 pub const fn value(&self) -> u64 {
1343 self.1
1344 }
1345
1346 #[must_use]
1348 pub const fn into_code_and_value(self) -> (u16, u64) {
1349 (self.0, self.1)
1350 }
1351}
1352
1353#[cfg_attr(doc, doc = "CompactEventCounters\n\nCompact global metrics counters.")]
1354#[derive(CandidType, Clone, Debug, Default, Deserialize, Eq, PartialEq)]
1355pub struct CompactEventCounters(Vec<CompactMetric>, u64, u64);
1356
1357impl CompactEventCounters {
1358 #[must_use]
1359 pub(crate) const fn new(
1360 metrics: Vec<CompactMetric>,
1361 window_start_ms: u64,
1362 window_end_ms: u64,
1363 ) -> Self {
1364 Self(metrics, window_start_ms, window_end_ms)
1365 }
1366
1367 #[must_use]
1369 pub fn metrics(&self) -> &[CompactMetric] {
1370 &self.0
1371 }
1372
1373 #[must_use]
1375 pub const fn window_start_ms(&self) -> u64 {
1376 self.1
1377 }
1378
1379 #[must_use]
1381 pub const fn window_end_ms(&self) -> u64 {
1382 self.2
1383 }
1384
1385 #[must_use]
1387 pub const fn window_duration_ms(&self) -> u64 {
1388 self.2.saturating_sub(self.1)
1389 }
1390}
1391
1392#[cfg_attr(
1393 doc,
1394 doc = "CompactEntityMetrics\n\nCompact per-entity metrics counters."
1395)]
1396#[derive(CandidType, Clone, Debug, Default, Deserialize, Eq, PartialEq)]
1397pub struct CompactEntityMetrics(String, Vec<CompactMetric>);
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.0.as_str()
1409 }
1410
1411 #[must_use]
1413 pub fn metrics(&self) -> &[CompactMetric] {
1414 &self.1
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 Option<CompactEventCounters>,
1422 Vec<CompactEntityMetrics>,
1423 Option<u64>,
1424 u64,
1425);
1426
1427impl CompactMetricsReport {
1428 #[must_use]
1429 pub(crate) const fn new(
1430 counters: Option<CompactEventCounters>,
1431 entity_counters: Vec<CompactEntityMetrics>,
1432 requested_window_start_ms: Option<u64>,
1433 active_window_start_ms: u64,
1434 ) -> Self {
1435 Self(
1436 counters,
1437 entity_counters,
1438 requested_window_start_ms,
1439 active_window_start_ms,
1440 )
1441 }
1442
1443 #[must_use]
1445 pub const fn counters(&self) -> Option<&CompactEventCounters> {
1446 self.0.as_ref()
1447 }
1448
1449 #[must_use]
1451 pub fn entity_counters(&self) -> &[CompactEntityMetrics] {
1452 &self.1
1453 }
1454
1455 #[must_use]
1457 pub const fn window_filter_matched(&self) -> bool {
1458 self.0.is_some()
1459 }
1460
1461 #[must_use]
1463 pub const fn requested_window_start_ms(&self) -> Option<u64> {
1464 self.2
1465 }
1466
1467 #[must_use]
1469 pub const fn active_window_start_ms(&self) -> u64 {
1470 self.3
1471 }
1472}
1473
1474#[derive(CandidType, Clone, Debug, Default, Deserialize)]
1483pub struct EventCounters {
1484 pub(crate) ops: EventOps,
1485 pub(crate) perf: EventPerf,
1486 pub(crate) window_start_ms: u64,
1487 pub(crate) window_end_ms: u64,
1488 pub(crate) window_duration_ms: u64,
1489}
1490
1491impl EventCounters {
1492 #[must_use]
1493 pub(crate) const fn new(
1494 ops: EventOps,
1495 perf: EventPerf,
1496 window_start_ms: u64,
1497 window_end_ms: u64,
1498 ) -> Self {
1499 Self {
1500 ops,
1501 perf,
1502 window_start_ms,
1503 window_end_ms,
1504 window_duration_ms: window_end_ms.saturating_sub(window_start_ms),
1505 }
1506 }
1507
1508 #[must_use]
1509 pub const fn ops(&self) -> &EventOps {
1510 &self.ops
1511 }
1512
1513 #[must_use]
1514 pub const fn perf(&self) -> &EventPerf {
1515 &self.perf
1516 }
1517
1518 #[must_use]
1519 pub const fn window_start_ms(&self) -> u64 {
1520 self.window_start_ms
1521 }
1522
1523 #[must_use]
1524 pub const fn window_end_ms(&self) -> u64 {
1525 self.window_end_ms
1526 }
1527
1528 #[must_use]
1529 pub const fn window_duration_ms(&self) -> u64 {
1530 self.window_duration_ms
1531 }
1532}
1533
1534#[cfg_attr(doc, doc = "EntitySummary\n\nPer-entity metrics summary.")]
1535#[derive(CandidType, Clone, Debug, Default, Deserialize)]
1536pub struct EntitySummary {
1537 path: String,
1538 load_calls: u64,
1539 save_calls: u64,
1540 delete_calls: u64,
1541 save_insert_calls: u64,
1542 save_update_calls: u64,
1543 save_replace_calls: u64,
1544 exec_success: u64,
1545 exec_error_corruption: u64,
1546 exec_error_incompatible_persisted_format: u64,
1547 exec_error_not_found: u64,
1548 exec_error_internal: u64,
1549 exec_error_conflict: u64,
1550 exec_error_unsupported: u64,
1551 exec_error_invariant_violation: u64,
1552 exec_aborted: u64,
1553 cache_shared_query_plan_hits: u64,
1554 cache_shared_query_plan_misses: u64,
1555 cache_shared_query_plan_inserts: u64,
1556 cache_shared_query_plan_miss_cold: u64,
1557 cache_shared_query_plan_miss_distinct_key: u64,
1558 cache_shared_query_plan_miss_method_version: u64,
1559 cache_shared_query_plan_miss_schema_fingerprint: u64,
1560 cache_shared_query_plan_miss_visibility: u64,
1561 cache_sql_compiled_command_hits: u64,
1562 cache_sql_compiled_command_misses: u64,
1563 cache_sql_compiled_command_inserts: u64,
1564 cache_sql_compiled_command_miss_cold: u64,
1565 cache_sql_compiled_command_miss_distinct_key: u64,
1566 cache_sql_compiled_command_miss_method_version: u64,
1567 cache_sql_compiled_command_miss_schema_fingerprint: u64,
1568 cache_sql_compiled_command_miss_surface: u64,
1569 schema_reconcile_checks: u64,
1570 schema_reconcile_exact_match: u64,
1571 schema_reconcile_first_create: u64,
1572 schema_reconcile_latest_snapshot_corrupt: u64,
1573 schema_reconcile_rejected_field_slot: u64,
1574 schema_reconcile_rejected_other: u64,
1575 schema_reconcile_rejected_row_layout: u64,
1576 schema_reconcile_rejected_schema_version: u64,
1577 schema_reconcile_store_write_error: u64,
1578 schema_transition_checks: u64,
1579 schema_transition_append_only_nullable_fields: u64,
1580 schema_transition_exact_match: u64,
1581 schema_transition_rejected_entity_identity: u64,
1582 schema_transition_rejected_field_contract: u64,
1583 schema_transition_rejected_field_slot: u64,
1584 schema_transition_rejected_row_layout: u64,
1585 schema_transition_rejected_schema_version: u64,
1586 schema_transition_rejected_snapshot: u64,
1587 schema_store_snapshots: u64,
1588 schema_store_encoded_bytes: u64,
1589 schema_store_latest_snapshot_bytes: u64,
1590 accepted_schema_fields: u64,
1591 accepted_schema_nested_leaf_facts: u64,
1592 sql_compile_rejects: u64,
1593 sql_compile_reject_cache_key: u64,
1594 sql_compile_reject_parse: u64,
1595 sql_compile_reject_semantic: u64,
1596 plan_index: u64,
1597 plan_keys: u64,
1598 plan_range: u64,
1599 plan_full_scan: u64,
1600 plan_by_key: u64,
1601 plan_by_keys: u64,
1602 plan_key_range: u64,
1603 plan_index_branch_set: u64,
1604 plan_index_prefix: u64,
1605 plan_index_multi_lookup: u64,
1606 plan_index_range: u64,
1607 plan_explicit_full_scan: u64,
1608 plan_union: u64,
1609 plan_intersection: u64,
1610 plan_grouped_hash_materialized: u64,
1611 plan_grouped_ordered_materialized: u64,
1612 plan_choice_conflicting_primary_key_children_access_preferred: u64,
1613 plan_choice_constant_false_predicate: u64,
1614 plan_choice_empty_child_access_preferred: u64,
1615 plan_choice_full_scan_access: u64,
1616 plan_choice_intent_key_access_override: u64,
1617 plan_choice_limit_zero_window: u64,
1618 plan_choice_non_index_access: u64,
1619 plan_choice_planner_composite_non_index: u64,
1620 plan_choice_planner_full_scan_fallback: u64,
1621 plan_choice_planner_key_set_access: u64,
1622 plan_choice_planner_primary_key_lookup: u64,
1623 plan_choice_planner_primary_key_range: u64,
1624 plan_choice_required_order_primary_key_range_preferred: u64,
1625 plan_choice_singleton_primary_key_child_access_preferred: u64,
1626 prepared_shape_already_finalized: u64,
1627 prepared_shape_generated_fallback: u64,
1628 rows_loaded: u64,
1629 rows_saved: u64,
1630 rows_inserted: u64,
1631 rows_updated: u64,
1632 rows_replaced: u64,
1633 rows_scanned: u64,
1634 rows_filtered: u64,
1635 rows_aggregated: u64,
1636 rows_emitted: u64,
1637 load_candidate_rows_scanned: u64,
1638 load_candidate_rows_filtered: u64,
1639 load_result_rows_emitted: u64,
1640 rows_deleted: u64,
1641 sql_insert_calls: u64,
1642 sql_insert_select_calls: u64,
1643 sql_update_calls: u64,
1644 sql_delete_calls: u64,
1645 sql_write_staged_rows: u64,
1646 sql_write_matched_rows: u64,
1647 sql_write_mutated_rows: u64,
1648 sql_write_returning_rows: u64,
1649 sql_write_error_insert: u64,
1650 sql_write_error_insert_select: u64,
1651 sql_write_error_update: u64,
1652 sql_write_error_delete: u64,
1653 sql_write_error_corruption: u64,
1654 sql_write_error_incompatible_persisted_format: u64,
1655 sql_write_error_not_found: u64,
1656 sql_write_error_internal: u64,
1657 sql_write_error_conflict: u64,
1658 sql_write_error_unsupported: u64,
1659 sql_write_error_invariant_violation: u64,
1660 index_inserts: u64,
1661 index_removes: u64,
1662 reverse_index_inserts: u64,
1663 reverse_index_removes: u64,
1664 relation_reverse_lookups: u64,
1665 relation_delete_blocks: u64,
1666 write_rows_touched: u64,
1667 write_index_entries_changed: u64,
1668 write_reverse_index_entries_changed: u64,
1669 write_relation_checks: u64,
1670 unique_violations: u64,
1671 non_atomic_partial_commits: u64,
1672 non_atomic_partial_rows_committed: u64,
1673}
1674
1675impl EntitySummary {
1676 #[must_use]
1677 pub const fn path(&self) -> &str {
1678 self.path.as_str()
1679 }
1680
1681 #[must_use]
1682 pub const fn load_calls(&self) -> u64 {
1683 self.load_calls
1684 }
1685
1686 #[must_use]
1687 pub const fn save_calls(&self) -> u64 {
1688 self.save_calls
1689 }
1690
1691 #[must_use]
1692 pub const fn delete_calls(&self) -> u64 {
1693 self.delete_calls
1694 }
1695
1696 #[must_use]
1697 pub const fn save_insert_calls(&self) -> u64 {
1698 self.save_insert_calls
1699 }
1700
1701 #[must_use]
1702 pub const fn save_update_calls(&self) -> u64 {
1703 self.save_update_calls
1704 }
1705
1706 #[must_use]
1707 pub const fn save_replace_calls(&self) -> u64 {
1708 self.save_replace_calls
1709 }
1710
1711 #[must_use]
1712 pub const fn exec_success(&self) -> u64 {
1713 self.exec_success
1714 }
1715
1716 #[must_use]
1717 pub const fn exec_error_corruption(&self) -> u64 {
1718 self.exec_error_corruption
1719 }
1720
1721 #[must_use]
1722 pub const fn exec_error_incompatible_persisted_format(&self) -> u64 {
1723 self.exec_error_incompatible_persisted_format
1724 }
1725
1726 #[must_use]
1727 pub const fn exec_error_not_found(&self) -> u64 {
1728 self.exec_error_not_found
1729 }
1730
1731 #[must_use]
1732 pub const fn exec_error_internal(&self) -> u64 {
1733 self.exec_error_internal
1734 }
1735
1736 #[must_use]
1737 pub const fn exec_error_conflict(&self) -> u64 {
1738 self.exec_error_conflict
1739 }
1740
1741 #[must_use]
1742 pub const fn exec_error_unsupported(&self) -> u64 {
1743 self.exec_error_unsupported
1744 }
1745
1746 #[must_use]
1747 pub const fn exec_error_invariant_violation(&self) -> u64 {
1748 self.exec_error_invariant_violation
1749 }
1750
1751 #[must_use]
1752 pub const fn exec_aborted(&self) -> u64 {
1753 self.exec_aborted
1754 }
1755
1756 #[must_use]
1757 pub const fn cache_shared_query_plan_hits(&self) -> u64 {
1758 self.cache_shared_query_plan_hits
1759 }
1760
1761 #[must_use]
1762 pub const fn cache_shared_query_plan_misses(&self) -> u64 {
1763 self.cache_shared_query_plan_misses
1764 }
1765
1766 #[must_use]
1767 pub const fn cache_shared_query_plan_inserts(&self) -> u64 {
1768 self.cache_shared_query_plan_inserts
1769 }
1770
1771 #[must_use]
1772 pub const fn cache_shared_query_plan_miss_cold(&self) -> u64 {
1773 self.cache_shared_query_plan_miss_cold
1774 }
1775
1776 #[must_use]
1777 pub const fn cache_shared_query_plan_miss_distinct_key(&self) -> u64 {
1778 self.cache_shared_query_plan_miss_distinct_key
1779 }
1780
1781 #[must_use]
1782 pub const fn cache_shared_query_plan_miss_method_version(&self) -> u64 {
1783 self.cache_shared_query_plan_miss_method_version
1784 }
1785
1786 #[must_use]
1787 pub const fn cache_shared_query_plan_miss_schema_fingerprint(&self) -> u64 {
1788 self.cache_shared_query_plan_miss_schema_fingerprint
1789 }
1790
1791 #[must_use]
1792 pub const fn cache_shared_query_plan_miss_visibility(&self) -> u64 {
1793 self.cache_shared_query_plan_miss_visibility
1794 }
1795
1796 #[must_use]
1797 pub const fn cache_sql_compiled_command_hits(&self) -> u64 {
1798 self.cache_sql_compiled_command_hits
1799 }
1800
1801 #[must_use]
1802 pub const fn cache_sql_compiled_command_misses(&self) -> u64 {
1803 self.cache_sql_compiled_command_misses
1804 }
1805
1806 #[must_use]
1807 pub const fn cache_sql_compiled_command_inserts(&self) -> u64 {
1808 self.cache_sql_compiled_command_inserts
1809 }
1810
1811 #[must_use]
1812 pub const fn cache_sql_compiled_command_miss_cold(&self) -> u64 {
1813 self.cache_sql_compiled_command_miss_cold
1814 }
1815
1816 #[must_use]
1817 pub const fn cache_sql_compiled_command_miss_distinct_key(&self) -> u64 {
1818 self.cache_sql_compiled_command_miss_distinct_key
1819 }
1820
1821 #[must_use]
1822 pub const fn cache_sql_compiled_command_miss_method_version(&self) -> u64 {
1823 self.cache_sql_compiled_command_miss_method_version
1824 }
1825
1826 #[must_use]
1827 pub const fn cache_sql_compiled_command_miss_schema_fingerprint(&self) -> u64 {
1828 self.cache_sql_compiled_command_miss_schema_fingerprint
1829 }
1830
1831 #[must_use]
1832 pub const fn cache_sql_compiled_command_miss_surface(&self) -> u64 {
1833 self.cache_sql_compiled_command_miss_surface
1834 }
1835
1836 #[must_use]
1837 pub const fn schema_reconcile_checks(&self) -> u64 {
1838 self.schema_reconcile_checks
1839 }
1840
1841 #[must_use]
1842 pub const fn schema_reconcile_exact_match(&self) -> u64 {
1843 self.schema_reconcile_exact_match
1844 }
1845
1846 #[must_use]
1847 pub const fn schema_reconcile_first_create(&self) -> u64 {
1848 self.schema_reconcile_first_create
1849 }
1850
1851 #[must_use]
1852 pub const fn schema_reconcile_latest_snapshot_corrupt(&self) -> u64 {
1853 self.schema_reconcile_latest_snapshot_corrupt
1854 }
1855
1856 #[must_use]
1857 pub const fn schema_reconcile_rejected_field_slot(&self) -> u64 {
1858 self.schema_reconcile_rejected_field_slot
1859 }
1860
1861 #[must_use]
1862 pub const fn schema_reconcile_rejected_other(&self) -> u64 {
1863 self.schema_reconcile_rejected_other
1864 }
1865
1866 #[must_use]
1867 pub const fn schema_reconcile_rejected_row_layout(&self) -> u64 {
1868 self.schema_reconcile_rejected_row_layout
1869 }
1870
1871 #[must_use]
1872 pub const fn schema_reconcile_rejected_schema_version(&self) -> u64 {
1873 self.schema_reconcile_rejected_schema_version
1874 }
1875
1876 #[must_use]
1877 pub const fn schema_reconcile_store_write_error(&self) -> u64 {
1878 self.schema_reconcile_store_write_error
1879 }
1880
1881 #[must_use]
1882 pub const fn schema_transition_checks(&self) -> u64 {
1883 self.schema_transition_checks
1884 }
1885
1886 #[must_use]
1887 pub const fn schema_transition_append_only_nullable_fields(&self) -> u64 {
1888 self.schema_transition_append_only_nullable_fields
1889 }
1890
1891 #[must_use]
1892 pub const fn schema_transition_exact_match(&self) -> u64 {
1893 self.schema_transition_exact_match
1894 }
1895
1896 #[must_use]
1897 pub const fn schema_transition_rejected_entity_identity(&self) -> u64 {
1898 self.schema_transition_rejected_entity_identity
1899 }
1900
1901 #[must_use]
1902 pub const fn schema_transition_rejected_field_contract(&self) -> u64 {
1903 self.schema_transition_rejected_field_contract
1904 }
1905
1906 #[must_use]
1907 pub const fn schema_transition_rejected_field_slot(&self) -> u64 {
1908 self.schema_transition_rejected_field_slot
1909 }
1910
1911 #[must_use]
1912 pub const fn schema_transition_rejected_row_layout(&self) -> u64 {
1913 self.schema_transition_rejected_row_layout
1914 }
1915
1916 #[must_use]
1917 pub const fn schema_transition_rejected_schema_version(&self) -> u64 {
1918 self.schema_transition_rejected_schema_version
1919 }
1920
1921 #[must_use]
1922 pub const fn schema_transition_rejected_snapshot(&self) -> u64 {
1923 self.schema_transition_rejected_snapshot
1924 }
1925
1926 #[must_use]
1927 pub const fn schema_store_snapshots(&self) -> u64 {
1928 self.schema_store_snapshots
1929 }
1930
1931 #[must_use]
1932 pub const fn schema_store_encoded_bytes(&self) -> u64 {
1933 self.schema_store_encoded_bytes
1934 }
1935
1936 #[must_use]
1937 pub const fn schema_store_latest_snapshot_bytes(&self) -> u64 {
1938 self.schema_store_latest_snapshot_bytes
1939 }
1940
1941 #[must_use]
1942 pub const fn accepted_schema_fields(&self) -> u64 {
1943 self.accepted_schema_fields
1944 }
1945
1946 #[must_use]
1947 pub const fn accepted_schema_nested_leaf_facts(&self) -> u64 {
1948 self.accepted_schema_nested_leaf_facts
1949 }
1950
1951 #[must_use]
1952 pub const fn sql_compile_rejects(&self) -> u64 {
1953 self.sql_compile_rejects
1954 }
1955
1956 #[must_use]
1957 pub const fn sql_compile_reject_cache_key(&self) -> u64 {
1958 self.sql_compile_reject_cache_key
1959 }
1960
1961 #[must_use]
1962 pub const fn sql_compile_reject_parse(&self) -> u64 {
1963 self.sql_compile_reject_parse
1964 }
1965
1966 #[must_use]
1967 pub const fn sql_compile_reject_semantic(&self) -> u64 {
1968 self.sql_compile_reject_semantic
1969 }
1970
1971 #[must_use]
1972 pub const fn plan_index(&self) -> u64 {
1973 self.plan_index
1974 }
1975
1976 #[must_use]
1977 pub const fn plan_keys(&self) -> u64 {
1978 self.plan_keys
1979 }
1980
1981 #[must_use]
1982 pub const fn plan_range(&self) -> u64 {
1983 self.plan_range
1984 }
1985
1986 #[must_use]
1987 pub const fn plan_full_scan(&self) -> u64 {
1988 self.plan_full_scan
1989 }
1990
1991 #[must_use]
1992 pub const fn plan_by_key(&self) -> u64 {
1993 self.plan_by_key
1994 }
1995
1996 #[must_use]
1997 pub const fn plan_by_keys(&self) -> u64 {
1998 self.plan_by_keys
1999 }
2000
2001 #[must_use]
2002 pub const fn plan_key_range(&self) -> u64 {
2003 self.plan_key_range
2004 }
2005
2006 #[must_use]
2007 pub const fn plan_index_branch_set(&self) -> u64 {
2008 self.plan_index_branch_set
2009 }
2010
2011 #[must_use]
2012 pub const fn plan_index_prefix(&self) -> u64 {
2013 self.plan_index_prefix
2014 }
2015
2016 #[must_use]
2017 pub const fn plan_index_multi_lookup(&self) -> u64 {
2018 self.plan_index_multi_lookup
2019 }
2020
2021 #[must_use]
2022 pub const fn plan_index_range(&self) -> u64 {
2023 self.plan_index_range
2024 }
2025
2026 #[must_use]
2027 pub const fn plan_explicit_full_scan(&self) -> u64 {
2028 self.plan_explicit_full_scan
2029 }
2030
2031 #[must_use]
2032 pub const fn plan_union(&self) -> u64 {
2033 self.plan_union
2034 }
2035
2036 #[must_use]
2037 pub const fn plan_intersection(&self) -> u64 {
2038 self.plan_intersection
2039 }
2040
2041 #[must_use]
2042 pub const fn plan_grouped_hash_materialized(&self) -> u64 {
2043 self.plan_grouped_hash_materialized
2044 }
2045
2046 #[must_use]
2047 pub const fn plan_grouped_ordered_materialized(&self) -> u64 {
2048 self.plan_grouped_ordered_materialized
2049 }
2050
2051 #[must_use]
2052 pub const fn plan_choice_conflicting_primary_key_children_access_preferred(&self) -> u64 {
2053 self.plan_choice_conflicting_primary_key_children_access_preferred
2054 }
2055
2056 #[must_use]
2057 pub const fn plan_choice_constant_false_predicate(&self) -> u64 {
2058 self.plan_choice_constant_false_predicate
2059 }
2060
2061 #[must_use]
2062 pub const fn plan_choice_empty_child_access_preferred(&self) -> u64 {
2063 self.plan_choice_empty_child_access_preferred
2064 }
2065
2066 #[must_use]
2067 pub const fn plan_choice_full_scan_access(&self) -> u64 {
2068 self.plan_choice_full_scan_access
2069 }
2070
2071 #[must_use]
2072 pub const fn plan_choice_intent_key_access_override(&self) -> u64 {
2073 self.plan_choice_intent_key_access_override
2074 }
2075
2076 #[must_use]
2077 pub const fn plan_choice_limit_zero_window(&self) -> u64 {
2078 self.plan_choice_limit_zero_window
2079 }
2080
2081 #[must_use]
2082 pub const fn plan_choice_non_index_access(&self) -> u64 {
2083 self.plan_choice_non_index_access
2084 }
2085
2086 #[must_use]
2087 pub const fn plan_choice_planner_composite_non_index(&self) -> u64 {
2088 self.plan_choice_planner_composite_non_index
2089 }
2090
2091 #[must_use]
2092 pub const fn plan_choice_planner_full_scan_fallback(&self) -> u64 {
2093 self.plan_choice_planner_full_scan_fallback
2094 }
2095
2096 #[must_use]
2097 pub const fn plan_choice_planner_key_set_access(&self) -> u64 {
2098 self.plan_choice_planner_key_set_access
2099 }
2100
2101 #[must_use]
2102 pub const fn plan_choice_planner_primary_key_lookup(&self) -> u64 {
2103 self.plan_choice_planner_primary_key_lookup
2104 }
2105
2106 #[must_use]
2107 pub const fn plan_choice_planner_primary_key_range(&self) -> u64 {
2108 self.plan_choice_planner_primary_key_range
2109 }
2110
2111 #[must_use]
2112 pub const fn plan_choice_required_order_primary_key_range_preferred(&self) -> u64 {
2113 self.plan_choice_required_order_primary_key_range_preferred
2114 }
2115
2116 #[must_use]
2117 pub const fn plan_choice_singleton_primary_key_child_access_preferred(&self) -> u64 {
2118 self.plan_choice_singleton_primary_key_child_access_preferred
2119 }
2120
2121 #[must_use]
2122 pub const fn prepared_shape_already_finalized(&self) -> u64 {
2123 self.prepared_shape_already_finalized
2124 }
2125
2126 #[must_use]
2127 pub const fn prepared_shape_generated_fallback(&self) -> u64 {
2128 self.prepared_shape_generated_fallback
2129 }
2130
2131 #[must_use]
2132 pub const fn rows_loaded(&self) -> u64 {
2133 self.rows_loaded
2134 }
2135
2136 #[must_use]
2137 pub const fn rows_saved(&self) -> u64 {
2138 self.rows_saved
2139 }
2140
2141 #[must_use]
2142 pub const fn rows_inserted(&self) -> u64 {
2143 self.rows_inserted
2144 }
2145
2146 #[must_use]
2147 pub const fn rows_updated(&self) -> u64 {
2148 self.rows_updated
2149 }
2150
2151 #[must_use]
2152 pub const fn rows_replaced(&self) -> u64 {
2153 self.rows_replaced
2154 }
2155
2156 #[must_use]
2157 pub const fn rows_scanned(&self) -> u64 {
2158 self.rows_scanned
2159 }
2160
2161 #[must_use]
2162 pub const fn rows_filtered(&self) -> u64 {
2163 self.rows_filtered
2164 }
2165
2166 #[must_use]
2167 pub const fn rows_aggregated(&self) -> u64 {
2168 self.rows_aggregated
2169 }
2170
2171 #[must_use]
2172 pub const fn rows_emitted(&self) -> u64 {
2173 self.rows_emitted
2174 }
2175
2176 #[must_use]
2177 pub const fn load_candidate_rows_scanned(&self) -> u64 {
2178 self.load_candidate_rows_scanned
2179 }
2180
2181 #[must_use]
2182 pub const fn load_candidate_rows_filtered(&self) -> u64 {
2183 self.load_candidate_rows_filtered
2184 }
2185
2186 #[must_use]
2187 pub const fn load_result_rows_emitted(&self) -> u64 {
2188 self.load_result_rows_emitted
2189 }
2190
2191 #[must_use]
2192 pub const fn rows_deleted(&self) -> u64 {
2193 self.rows_deleted
2194 }
2195
2196 #[must_use]
2197 pub const fn sql_insert_calls(&self) -> u64 {
2198 self.sql_insert_calls
2199 }
2200
2201 #[must_use]
2202 pub const fn sql_insert_select_calls(&self) -> u64 {
2203 self.sql_insert_select_calls
2204 }
2205
2206 #[must_use]
2207 pub const fn sql_update_calls(&self) -> u64 {
2208 self.sql_update_calls
2209 }
2210
2211 #[must_use]
2212 pub const fn sql_delete_calls(&self) -> u64 {
2213 self.sql_delete_calls
2214 }
2215
2216 #[must_use]
2217 pub const fn sql_write_staged_rows(&self) -> u64 {
2218 self.sql_write_staged_rows
2219 }
2220
2221 #[must_use]
2222 pub const fn sql_write_matched_rows(&self) -> u64 {
2223 self.sql_write_matched_rows
2224 }
2225
2226 #[must_use]
2227 pub const fn sql_write_mutated_rows(&self) -> u64 {
2228 self.sql_write_mutated_rows
2229 }
2230
2231 #[must_use]
2232 pub const fn sql_write_returning_rows(&self) -> u64 {
2233 self.sql_write_returning_rows
2234 }
2235
2236 #[must_use]
2237 pub const fn sql_write_error_insert(&self) -> u64 {
2238 self.sql_write_error_insert
2239 }
2240
2241 #[must_use]
2242 pub const fn sql_write_error_insert_select(&self) -> u64 {
2243 self.sql_write_error_insert_select
2244 }
2245
2246 #[must_use]
2247 pub const fn sql_write_error_update(&self) -> u64 {
2248 self.sql_write_error_update
2249 }
2250
2251 #[must_use]
2252 pub const fn sql_write_error_delete(&self) -> u64 {
2253 self.sql_write_error_delete
2254 }
2255
2256 #[must_use]
2257 pub const fn sql_write_error_corruption(&self) -> u64 {
2258 self.sql_write_error_corruption
2259 }
2260
2261 #[must_use]
2262 pub const fn sql_write_error_incompatible_persisted_format(&self) -> u64 {
2263 self.sql_write_error_incompatible_persisted_format
2264 }
2265
2266 #[must_use]
2267 pub const fn sql_write_error_not_found(&self) -> u64 {
2268 self.sql_write_error_not_found
2269 }
2270
2271 #[must_use]
2272 pub const fn sql_write_error_internal(&self) -> u64 {
2273 self.sql_write_error_internal
2274 }
2275
2276 #[must_use]
2277 pub const fn sql_write_error_conflict(&self) -> u64 {
2278 self.sql_write_error_conflict
2279 }
2280
2281 #[must_use]
2282 pub const fn sql_write_error_unsupported(&self) -> u64 {
2283 self.sql_write_error_unsupported
2284 }
2285
2286 #[must_use]
2287 pub const fn sql_write_error_invariant_violation(&self) -> u64 {
2288 self.sql_write_error_invariant_violation
2289 }
2290
2291 #[must_use]
2292 pub const fn index_inserts(&self) -> u64 {
2293 self.index_inserts
2294 }
2295
2296 #[must_use]
2297 pub const fn index_removes(&self) -> u64 {
2298 self.index_removes
2299 }
2300
2301 #[must_use]
2302 pub const fn reverse_index_inserts(&self) -> u64 {
2303 self.reverse_index_inserts
2304 }
2305
2306 #[must_use]
2307 pub const fn reverse_index_removes(&self) -> u64 {
2308 self.reverse_index_removes
2309 }
2310
2311 #[must_use]
2312 pub const fn relation_reverse_lookups(&self) -> u64 {
2313 self.relation_reverse_lookups
2314 }
2315
2316 #[must_use]
2317 pub const fn relation_delete_blocks(&self) -> u64 {
2318 self.relation_delete_blocks
2319 }
2320
2321 #[must_use]
2322 pub const fn write_rows_touched(&self) -> u64 {
2323 self.write_rows_touched
2324 }
2325
2326 #[must_use]
2327 pub const fn write_index_entries_changed(&self) -> u64 {
2328 self.write_index_entries_changed
2329 }
2330
2331 #[must_use]
2332 pub const fn write_reverse_index_entries_changed(&self) -> u64 {
2333 self.write_reverse_index_entries_changed
2334 }
2335
2336 #[must_use]
2337 pub const fn write_relation_checks(&self) -> u64 {
2338 self.write_relation_checks
2339 }
2340
2341 #[must_use]
2342 pub const fn unique_violations(&self) -> u64 {
2343 self.unique_violations
2344 }
2345
2346 #[must_use]
2347 pub const fn non_atomic_partial_commits(&self) -> u64 {
2348 self.non_atomic_partial_commits
2349 }
2350
2351 #[must_use]
2352 pub const fn non_atomic_partial_rows_committed(&self) -> u64 {
2353 self.non_atomic_partial_rows_committed
2354 }
2355
2356 #[must_use]
2358 pub const fn load_selectivity_ratio(&self) -> Option<MetricRatio> {
2359 ratio(
2360 self.load_result_rows_emitted,
2361 self.load_candidate_rows_scanned,
2362 )
2363 }
2364
2365 #[must_use]
2367 pub const fn load_filter_ratio(&self) -> Option<MetricRatio> {
2368 ratio(
2369 self.load_candidate_rows_filtered,
2370 self.load_candidate_rows_scanned,
2371 )
2372 }
2373
2374 #[must_use]
2376 pub const fn sql_write_mutation_ratio(&self) -> Option<MetricRatio> {
2377 ratio(self.sql_write_mutated_rows, self.sql_write_matched_rows)
2378 }
2379
2380 #[must_use]
2382 pub const fn sql_write_returning_ratio(&self) -> Option<MetricRatio> {
2383 ratio(self.sql_write_returning_rows, self.sql_write_mutated_rows)
2384 }
2385
2386 #[must_use]
2388 pub const fn write_index_entries_per_row(&self) -> Option<MetricRatio> {
2389 ratio(self.write_index_entries_changed, self.write_rows_touched)
2390 }
2391
2392 #[must_use]
2394 pub const fn write_reverse_index_entries_per_row(&self) -> Option<MetricRatio> {
2395 ratio(
2396 self.write_reverse_index_entries_changed,
2397 self.write_rows_touched,
2398 )
2399 }
2400
2401 #[must_use]
2403 pub const fn write_relation_checks_per_row(&self) -> Option<MetricRatio> {
2404 ratio(self.write_relation_checks, self.write_rows_touched)
2405 }
2406
2407 #[expect(clippy::too_many_lines)]
2410 const fn activity_score(&self) -> u64 {
2411 self.load_calls
2412 .saturating_add(self.save_calls)
2413 .saturating_add(self.delete_calls)
2414 .saturating_add(self.save_insert_calls)
2415 .saturating_add(self.save_update_calls)
2416 .saturating_add(self.save_replace_calls)
2417 .saturating_add(self.exec_success)
2418 .saturating_add(self.exec_error_corruption)
2419 .saturating_add(self.exec_error_incompatible_persisted_format)
2420 .saturating_add(self.exec_error_not_found)
2421 .saturating_add(self.exec_error_internal)
2422 .saturating_add(self.exec_error_conflict)
2423 .saturating_add(self.exec_error_unsupported)
2424 .saturating_add(self.exec_error_invariant_violation)
2425 .saturating_add(self.exec_aborted)
2426 .saturating_add(self.cache_shared_query_plan_hits)
2427 .saturating_add(self.cache_shared_query_plan_misses)
2428 .saturating_add(self.cache_shared_query_plan_inserts)
2429 .saturating_add(self.cache_shared_query_plan_miss_cold)
2430 .saturating_add(self.cache_shared_query_plan_miss_distinct_key)
2431 .saturating_add(self.cache_shared_query_plan_miss_method_version)
2432 .saturating_add(self.cache_shared_query_plan_miss_schema_fingerprint)
2433 .saturating_add(self.cache_shared_query_plan_miss_visibility)
2434 .saturating_add(self.cache_sql_compiled_command_hits)
2435 .saturating_add(self.cache_sql_compiled_command_misses)
2436 .saturating_add(self.cache_sql_compiled_command_inserts)
2437 .saturating_add(self.cache_sql_compiled_command_miss_cold)
2438 .saturating_add(self.cache_sql_compiled_command_miss_distinct_key)
2439 .saturating_add(self.cache_sql_compiled_command_miss_method_version)
2440 .saturating_add(self.cache_sql_compiled_command_miss_schema_fingerprint)
2441 .saturating_add(self.cache_sql_compiled_command_miss_surface)
2442 .saturating_add(self.schema_reconcile_checks)
2443 .saturating_add(self.schema_reconcile_exact_match)
2444 .saturating_add(self.schema_reconcile_first_create)
2445 .saturating_add(self.schema_reconcile_latest_snapshot_corrupt)
2446 .saturating_add(self.schema_reconcile_rejected_field_slot)
2447 .saturating_add(self.schema_reconcile_rejected_other)
2448 .saturating_add(self.schema_reconcile_rejected_row_layout)
2449 .saturating_add(self.schema_reconcile_rejected_schema_version)
2450 .saturating_add(self.schema_reconcile_store_write_error)
2451 .saturating_add(self.schema_transition_checks)
2452 .saturating_add(self.schema_transition_append_only_nullable_fields)
2453 .saturating_add(self.schema_transition_exact_match)
2454 .saturating_add(self.schema_transition_rejected_entity_identity)
2455 .saturating_add(self.schema_transition_rejected_field_contract)
2456 .saturating_add(self.schema_transition_rejected_field_slot)
2457 .saturating_add(self.schema_transition_rejected_row_layout)
2458 .saturating_add(self.schema_transition_rejected_schema_version)
2459 .saturating_add(self.schema_transition_rejected_snapshot)
2460 .saturating_add(self.schema_store_snapshots)
2461 .saturating_add(self.schema_store_encoded_bytes)
2462 .saturating_add(self.schema_store_latest_snapshot_bytes)
2463 .saturating_add(self.accepted_schema_fields)
2464 .saturating_add(self.accepted_schema_nested_leaf_facts)
2465 .saturating_add(self.sql_compile_rejects)
2466 .saturating_add(self.sql_compile_reject_cache_key)
2467 .saturating_add(self.sql_compile_reject_parse)
2468 .saturating_add(self.sql_compile_reject_semantic)
2469 .saturating_add(self.plan_index)
2470 .saturating_add(self.plan_keys)
2471 .saturating_add(self.plan_range)
2472 .saturating_add(self.plan_full_scan)
2473 .saturating_add(self.plan_by_key)
2474 .saturating_add(self.plan_by_keys)
2475 .saturating_add(self.plan_key_range)
2476 .saturating_add(self.plan_index_branch_set)
2477 .saturating_add(self.plan_index_prefix)
2478 .saturating_add(self.plan_index_multi_lookup)
2479 .saturating_add(self.plan_index_range)
2480 .saturating_add(self.plan_explicit_full_scan)
2481 .saturating_add(self.plan_union)
2482 .saturating_add(self.plan_intersection)
2483 .saturating_add(self.plan_grouped_hash_materialized)
2484 .saturating_add(self.plan_grouped_ordered_materialized)
2485 .saturating_add(self.plan_choice_conflicting_primary_key_children_access_preferred)
2486 .saturating_add(self.plan_choice_constant_false_predicate)
2487 .saturating_add(self.plan_choice_empty_child_access_preferred)
2488 .saturating_add(self.plan_choice_full_scan_access)
2489 .saturating_add(self.plan_choice_intent_key_access_override)
2490 .saturating_add(self.plan_choice_limit_zero_window)
2491 .saturating_add(self.plan_choice_non_index_access)
2492 .saturating_add(self.plan_choice_planner_composite_non_index)
2493 .saturating_add(self.plan_choice_planner_full_scan_fallback)
2494 .saturating_add(self.plan_choice_planner_key_set_access)
2495 .saturating_add(self.plan_choice_planner_primary_key_lookup)
2496 .saturating_add(self.plan_choice_planner_primary_key_range)
2497 .saturating_add(self.plan_choice_required_order_primary_key_range_preferred)
2498 .saturating_add(self.plan_choice_singleton_primary_key_child_access_preferred)
2499 .saturating_add(self.prepared_shape_already_finalized)
2500 .saturating_add(self.prepared_shape_generated_fallback)
2501 .saturating_add(self.rows_loaded)
2502 .saturating_add(self.rows_saved)
2503 .saturating_add(self.rows_inserted)
2504 .saturating_add(self.rows_updated)
2505 .saturating_add(self.rows_replaced)
2506 .saturating_add(self.rows_scanned)
2507 .saturating_add(self.rows_filtered)
2508 .saturating_add(self.rows_aggregated)
2509 .saturating_add(self.rows_emitted)
2510 .saturating_add(self.load_candidate_rows_scanned)
2511 .saturating_add(self.load_candidate_rows_filtered)
2512 .saturating_add(self.load_result_rows_emitted)
2513 .saturating_add(self.rows_deleted)
2514 .saturating_add(self.sql_insert_calls)
2515 .saturating_add(self.sql_insert_select_calls)
2516 .saturating_add(self.sql_update_calls)
2517 .saturating_add(self.sql_delete_calls)
2518 .saturating_add(self.sql_write_staged_rows)
2519 .saturating_add(self.sql_write_matched_rows)
2520 .saturating_add(self.sql_write_mutated_rows)
2521 .saturating_add(self.sql_write_returning_rows)
2522 .saturating_add(self.sql_write_error_insert)
2523 .saturating_add(self.sql_write_error_insert_select)
2524 .saturating_add(self.sql_write_error_update)
2525 .saturating_add(self.sql_write_error_delete)
2526 .saturating_add(self.sql_write_error_corruption)
2527 .saturating_add(self.sql_write_error_incompatible_persisted_format)
2528 .saturating_add(self.sql_write_error_not_found)
2529 .saturating_add(self.sql_write_error_internal)
2530 .saturating_add(self.sql_write_error_conflict)
2531 .saturating_add(self.sql_write_error_unsupported)
2532 .saturating_add(self.sql_write_error_invariant_violation)
2533 .saturating_add(self.index_inserts)
2534 .saturating_add(self.index_removes)
2535 .saturating_add(self.reverse_index_inserts)
2536 .saturating_add(self.reverse_index_removes)
2537 .saturating_add(self.relation_reverse_lookups)
2538 .saturating_add(self.relation_delete_blocks)
2539 .saturating_add(self.write_rows_touched)
2540 .saturating_add(self.write_index_entries_changed)
2541 .saturating_add(self.write_reverse_index_entries_changed)
2542 .saturating_add(self.write_relation_checks)
2543 .saturating_add(self.unique_violations)
2544 .saturating_add(self.non_atomic_partial_commits)
2545 .saturating_add(self.non_atomic_partial_rows_committed)
2546 }
2547}
2548
2549#[expect(clippy::too_many_lines)]
2554fn entity_summary_from_counters(path: &str, ops: &EntityCounters) -> EntitySummary {
2555 EntitySummary {
2556 path: path.to_string(),
2557 load_calls: ops.load_calls,
2558 save_calls: ops.save_calls,
2559 delete_calls: ops.delete_calls,
2560 save_insert_calls: ops.save_insert_calls,
2561 save_update_calls: ops.save_update_calls,
2562 save_replace_calls: ops.save_replace_calls,
2563 exec_success: ops.exec_success,
2564 exec_error_corruption: ops.exec_error_corruption,
2565 exec_error_incompatible_persisted_format: ops.exec_error_incompatible_persisted_format,
2566 exec_error_not_found: ops.exec_error_not_found,
2567 exec_error_internal: ops.exec_error_internal,
2568 exec_error_conflict: ops.exec_error_conflict,
2569 exec_error_unsupported: ops.exec_error_unsupported,
2570 exec_error_invariant_violation: ops.exec_error_invariant_violation,
2571 exec_aborted: ops.exec_aborted,
2572 cache_shared_query_plan_hits: ops.cache_shared_query_plan_hits,
2573 cache_shared_query_plan_misses: ops.cache_shared_query_plan_misses,
2574 cache_shared_query_plan_inserts: ops.cache_shared_query_plan_inserts,
2575 cache_shared_query_plan_miss_cold: ops.cache_shared_query_plan_miss_cold,
2576 cache_shared_query_plan_miss_distinct_key: ops.cache_shared_query_plan_miss_distinct_key,
2577 cache_shared_query_plan_miss_method_version: ops
2578 .cache_shared_query_plan_miss_method_version,
2579 cache_shared_query_plan_miss_schema_fingerprint: ops
2580 .cache_shared_query_plan_miss_schema_fingerprint,
2581 cache_shared_query_plan_miss_visibility: ops.cache_shared_query_plan_miss_visibility,
2582 cache_sql_compiled_command_hits: ops.cache_sql_compiled_command_hits,
2583 cache_sql_compiled_command_misses: ops.cache_sql_compiled_command_misses,
2584 cache_sql_compiled_command_inserts: ops.cache_sql_compiled_command_inserts,
2585 cache_sql_compiled_command_miss_cold: ops.cache_sql_compiled_command_miss_cold,
2586 cache_sql_compiled_command_miss_distinct_key: ops
2587 .cache_sql_compiled_command_miss_distinct_key,
2588 cache_sql_compiled_command_miss_method_version: ops
2589 .cache_sql_compiled_command_miss_method_version,
2590 cache_sql_compiled_command_miss_schema_fingerprint: ops
2591 .cache_sql_compiled_command_miss_schema_fingerprint,
2592 cache_sql_compiled_command_miss_surface: ops.cache_sql_compiled_command_miss_surface,
2593 schema_reconcile_checks: ops.schema_reconcile_checks,
2594 schema_reconcile_exact_match: ops.schema_reconcile_exact_match,
2595 schema_reconcile_first_create: ops.schema_reconcile_first_create,
2596 schema_reconcile_latest_snapshot_corrupt: ops.schema_reconcile_latest_snapshot_corrupt,
2597 schema_reconcile_rejected_field_slot: ops.schema_reconcile_rejected_field_slot,
2598 schema_reconcile_rejected_other: ops.schema_reconcile_rejected_other,
2599 schema_reconcile_rejected_row_layout: ops.schema_reconcile_rejected_row_layout,
2600 schema_reconcile_rejected_schema_version: ops.schema_reconcile_rejected_schema_version,
2601 schema_reconcile_store_write_error: ops.schema_reconcile_store_write_error,
2602 schema_transition_checks: ops.schema_transition_checks,
2603 schema_transition_append_only_nullable_fields: ops
2604 .schema_transition_append_only_nullable_fields,
2605 schema_transition_exact_match: ops.schema_transition_exact_match,
2606 schema_transition_rejected_entity_identity: ops.schema_transition_rejected_entity_identity,
2607 schema_transition_rejected_field_contract: ops.schema_transition_rejected_field_contract,
2608 schema_transition_rejected_field_slot: ops.schema_transition_rejected_field_slot,
2609 schema_transition_rejected_row_layout: ops.schema_transition_rejected_row_layout,
2610 schema_transition_rejected_schema_version: ops.schema_transition_rejected_schema_version,
2611 schema_transition_rejected_snapshot: ops.schema_transition_rejected_snapshot,
2612 schema_store_snapshots: ops.schema_store_snapshots,
2613 schema_store_encoded_bytes: ops.schema_store_encoded_bytes,
2614 schema_store_latest_snapshot_bytes: ops.schema_store_latest_snapshot_bytes,
2615 accepted_schema_fields: ops.accepted_schema_fields,
2616 accepted_schema_nested_leaf_facts: ops.accepted_schema_nested_leaf_facts,
2617 sql_compile_rejects: ops.sql_compile_rejects,
2618 sql_compile_reject_cache_key: ops.sql_compile_reject_cache_key,
2619 sql_compile_reject_parse: ops.sql_compile_reject_parse,
2620 sql_compile_reject_semantic: ops.sql_compile_reject_semantic,
2621 plan_index: ops.plan_index,
2622 plan_keys: ops.plan_keys,
2623 plan_range: ops.plan_range,
2624 plan_full_scan: ops.plan_full_scan,
2625 plan_by_key: ops.plan_by_key,
2626 plan_by_keys: ops.plan_by_keys,
2627 plan_key_range: ops.plan_key_range,
2628 plan_index_branch_set: ops.plan_index_branch_set,
2629 plan_index_prefix: ops.plan_index_prefix,
2630 plan_index_multi_lookup: ops.plan_index_multi_lookup,
2631 plan_index_range: ops.plan_index_range,
2632 plan_explicit_full_scan: ops.plan_explicit_full_scan,
2633 plan_union: ops.plan_union,
2634 plan_intersection: ops.plan_intersection,
2635 plan_grouped_hash_materialized: ops.plan_grouped_hash_materialized,
2636 plan_grouped_ordered_materialized: ops.plan_grouped_ordered_materialized,
2637 plan_choice_conflicting_primary_key_children_access_preferred: ops
2638 .plan_choice_conflicting_primary_key_children_access_preferred,
2639 plan_choice_constant_false_predicate: ops.plan_choice_constant_false_predicate,
2640 plan_choice_empty_child_access_preferred: ops.plan_choice_empty_child_access_preferred,
2641 plan_choice_full_scan_access: ops.plan_choice_full_scan_access,
2642 plan_choice_intent_key_access_override: ops.plan_choice_intent_key_access_override,
2643 plan_choice_limit_zero_window: ops.plan_choice_limit_zero_window,
2644 plan_choice_non_index_access: ops.plan_choice_non_index_access,
2645 plan_choice_planner_composite_non_index: ops.plan_choice_planner_composite_non_index,
2646 plan_choice_planner_full_scan_fallback: ops.plan_choice_planner_full_scan_fallback,
2647 plan_choice_planner_key_set_access: ops.plan_choice_planner_key_set_access,
2648 plan_choice_planner_primary_key_lookup: ops.plan_choice_planner_primary_key_lookup,
2649 plan_choice_planner_primary_key_range: ops.plan_choice_planner_primary_key_range,
2650 plan_choice_required_order_primary_key_range_preferred: ops
2651 .plan_choice_required_order_primary_key_range_preferred,
2652 plan_choice_singleton_primary_key_child_access_preferred: ops
2653 .plan_choice_singleton_primary_key_child_access_preferred,
2654 prepared_shape_already_finalized: ops.prepared_shape_already_finalized,
2655 prepared_shape_generated_fallback: ops.prepared_shape_generated_fallback,
2656 rows_loaded: ops.rows_loaded,
2657 rows_saved: ops.rows_saved,
2658 rows_inserted: ops.rows_inserted,
2659 rows_updated: ops.rows_updated,
2660 rows_replaced: ops.rows_replaced,
2661 rows_scanned: ops.rows_scanned,
2662 rows_filtered: ops.rows_filtered,
2663 rows_aggregated: ops.rows_aggregated,
2664 rows_emitted: ops.rows_emitted,
2665 load_candidate_rows_scanned: ops.load_candidate_rows_scanned,
2666 load_candidate_rows_filtered: ops.load_candidate_rows_filtered,
2667 load_result_rows_emitted: ops.load_result_rows_emitted,
2668 rows_deleted: ops.rows_deleted,
2669 sql_insert_calls: ops.sql_insert_calls,
2670 sql_insert_select_calls: ops.sql_insert_select_calls,
2671 sql_update_calls: ops.sql_update_calls,
2672 sql_delete_calls: ops.sql_delete_calls,
2673 sql_write_staged_rows: ops.sql_write_staged_rows,
2674 sql_write_matched_rows: ops.sql_write_matched_rows,
2675 sql_write_mutated_rows: ops.sql_write_mutated_rows,
2676 sql_write_returning_rows: ops.sql_write_returning_rows,
2677 sql_write_error_insert: ops.sql_write_error_insert,
2678 sql_write_error_insert_select: ops.sql_write_error_insert_select,
2679 sql_write_error_update: ops.sql_write_error_update,
2680 sql_write_error_delete: ops.sql_write_error_delete,
2681 sql_write_error_corruption: ops.sql_write_error_corruption,
2682 sql_write_error_incompatible_persisted_format: ops
2683 .sql_write_error_incompatible_persisted_format,
2684 sql_write_error_not_found: ops.sql_write_error_not_found,
2685 sql_write_error_internal: ops.sql_write_error_internal,
2686 sql_write_error_conflict: ops.sql_write_error_conflict,
2687 sql_write_error_unsupported: ops.sql_write_error_unsupported,
2688 sql_write_error_invariant_violation: ops.sql_write_error_invariant_violation,
2689 index_inserts: ops.index_inserts,
2690 index_removes: ops.index_removes,
2691 reverse_index_inserts: ops.reverse_index_inserts,
2692 reverse_index_removes: ops.reverse_index_removes,
2693 relation_reverse_lookups: ops.relation_reverse_lookups,
2694 relation_delete_blocks: ops.relation_delete_blocks,
2695 write_rows_touched: ops.write_rows_touched,
2696 write_index_entries_changed: ops.write_index_entries_changed,
2697 write_reverse_index_entries_changed: ops.write_reverse_index_entries_changed,
2698 write_relation_checks: ops.write_relation_checks,
2699 unique_violations: ops.unique_violations,
2700 non_atomic_partial_commits: ops.non_atomic_partial_commits,
2701 non_atomic_partial_rows_committed: ops.non_atomic_partial_rows_committed,
2702 }
2703}
2704
2705fn push_compact_metric(metrics: &mut Vec<CompactMetric>, code: u16, value: u64) {
2706 if value != 0 {
2707 metrics.push(CompactMetric::new(code, value));
2708 }
2709}
2710
2711const fn event_ops_exec_errors(ops: &EventOps) -> u64 {
2712 ops.exec_error_corruption
2713 .saturating_add(ops.exec_error_incompatible_persisted_format)
2714 .saturating_add(ops.exec_error_not_found)
2715 .saturating_add(ops.exec_error_internal)
2716 .saturating_add(ops.exec_error_conflict)
2717 .saturating_add(ops.exec_error_unsupported)
2718 .saturating_add(ops.exec_error_invariant_violation)
2719}
2720
2721const fn entity_ops_exec_errors(ops: &EntityCounters) -> u64 {
2722 ops.exec_error_corruption
2723 .saturating_add(ops.exec_error_incompatible_persisted_format)
2724 .saturating_add(ops.exec_error_not_found)
2725 .saturating_add(ops.exec_error_internal)
2726 .saturating_add(ops.exec_error_conflict)
2727 .saturating_add(ops.exec_error_unsupported)
2728 .saturating_add(ops.exec_error_invariant_violation)
2729}
2730
2731fn compact_event_metrics(ops: &EventOps) -> Vec<CompactMetric> {
2732 use compact_metric_code::{
2733 CACHE_SHARED_QUERY_PLAN_HITS, CACHE_SHARED_QUERY_PLAN_MISSES,
2734 CACHE_SQL_COMPILED_COMMAND_HITS, CACHE_SQL_COMPILED_COMMAND_MISSES, DELETE_CALLS,
2735 EXEC_ABORTED, EXEC_ERRORS, EXEC_SUCCESS, LOAD_CALLS, ROWS_DELETED, ROWS_EMITTED,
2736 ROWS_FILTERED, ROWS_LOADED, ROWS_SAVED, ROWS_SCANNED, SAVE_CALLS, SQL_DELETE_CALLS,
2737 SQL_INSERT_CALLS, SQL_INSERT_SELECT_CALLS, SQL_UPDATE_CALLS, SQL_WRITE_MATCHED_ROWS,
2738 SQL_WRITE_MUTATED_ROWS, SQL_WRITE_RETURNING_ROWS, SQL_WRITE_STAGED_ROWS,
2739 };
2740
2741 let mut metrics = Vec::new();
2742 push_compact_metric(&mut metrics, LOAD_CALLS, ops.load_calls);
2743 push_compact_metric(&mut metrics, SAVE_CALLS, ops.save_calls);
2744 push_compact_metric(&mut metrics, DELETE_CALLS, ops.delete_calls);
2745 push_compact_metric(&mut metrics, EXEC_SUCCESS, ops.exec_success);
2746 push_compact_metric(&mut metrics, EXEC_ERRORS, event_ops_exec_errors(ops));
2747 push_compact_metric(&mut metrics, EXEC_ABORTED, ops.exec_aborted);
2748 push_compact_metric(&mut metrics, ROWS_LOADED, ops.rows_loaded);
2749 push_compact_metric(&mut metrics, ROWS_SAVED, ops.rows_saved);
2750 push_compact_metric(&mut metrics, ROWS_DELETED, ops.rows_deleted);
2751 push_compact_metric(&mut metrics, ROWS_SCANNED, ops.rows_scanned);
2752 push_compact_metric(&mut metrics, ROWS_FILTERED, ops.rows_filtered);
2753 push_compact_metric(&mut metrics, ROWS_EMITTED, ops.rows_emitted);
2754 push_compact_metric(&mut metrics, SQL_INSERT_CALLS, ops.sql_insert_calls);
2755 push_compact_metric(
2756 &mut metrics,
2757 SQL_INSERT_SELECT_CALLS,
2758 ops.sql_insert_select_calls,
2759 );
2760 push_compact_metric(&mut metrics, SQL_UPDATE_CALLS, ops.sql_update_calls);
2761 push_compact_metric(&mut metrics, SQL_DELETE_CALLS, ops.sql_delete_calls);
2762 push_compact_metric(
2763 &mut metrics,
2764 SQL_WRITE_MATCHED_ROWS,
2765 ops.sql_write_matched_rows,
2766 );
2767 push_compact_metric(
2768 &mut metrics,
2769 SQL_WRITE_MUTATED_ROWS,
2770 ops.sql_write_mutated_rows,
2771 );
2772 push_compact_metric(
2773 &mut metrics,
2774 SQL_WRITE_RETURNING_ROWS,
2775 ops.sql_write_returning_rows,
2776 );
2777 push_compact_metric(
2778 &mut metrics,
2779 SQL_WRITE_STAGED_ROWS,
2780 ops.sql_write_staged_rows,
2781 );
2782 push_compact_metric(
2783 &mut metrics,
2784 CACHE_SHARED_QUERY_PLAN_HITS,
2785 ops.cache_shared_query_plan_hits,
2786 );
2787 push_compact_metric(
2788 &mut metrics,
2789 CACHE_SHARED_QUERY_PLAN_MISSES,
2790 ops.cache_shared_query_plan_misses,
2791 );
2792 push_compact_metric(
2793 &mut metrics,
2794 CACHE_SQL_COMPILED_COMMAND_HITS,
2795 ops.cache_sql_compiled_command_hits,
2796 );
2797 push_compact_metric(
2798 &mut metrics,
2799 CACHE_SQL_COMPILED_COMMAND_MISSES,
2800 ops.cache_sql_compiled_command_misses,
2801 );
2802
2803 metrics
2804}
2805
2806fn compact_entity_metrics(ops: &EntityCounters) -> Vec<CompactMetric> {
2807 use compact_metric_code::{
2808 CACHE_SHARED_QUERY_PLAN_HITS, CACHE_SHARED_QUERY_PLAN_MISSES,
2809 CACHE_SQL_COMPILED_COMMAND_HITS, CACHE_SQL_COMPILED_COMMAND_MISSES, DELETE_CALLS,
2810 EXEC_ABORTED, EXEC_ERRORS, EXEC_SUCCESS, LOAD_CALLS, ROWS_DELETED, ROWS_EMITTED,
2811 ROWS_FILTERED, ROWS_LOADED, ROWS_SAVED, ROWS_SCANNED, SAVE_CALLS, SQL_DELETE_CALLS,
2812 SQL_INSERT_CALLS, SQL_INSERT_SELECT_CALLS, SQL_UPDATE_CALLS, SQL_WRITE_MATCHED_ROWS,
2813 SQL_WRITE_MUTATED_ROWS, SQL_WRITE_RETURNING_ROWS, SQL_WRITE_STAGED_ROWS,
2814 };
2815
2816 let mut metrics = Vec::new();
2817 push_compact_metric(&mut metrics, LOAD_CALLS, ops.load_calls);
2818 push_compact_metric(&mut metrics, SAVE_CALLS, ops.save_calls);
2819 push_compact_metric(&mut metrics, DELETE_CALLS, ops.delete_calls);
2820 push_compact_metric(&mut metrics, EXEC_SUCCESS, ops.exec_success);
2821 push_compact_metric(&mut metrics, EXEC_ERRORS, entity_ops_exec_errors(ops));
2822 push_compact_metric(&mut metrics, EXEC_ABORTED, ops.exec_aborted);
2823 push_compact_metric(&mut metrics, ROWS_LOADED, ops.rows_loaded);
2824 push_compact_metric(&mut metrics, ROWS_SAVED, ops.rows_saved);
2825 push_compact_metric(&mut metrics, ROWS_DELETED, ops.rows_deleted);
2826 push_compact_metric(&mut metrics, ROWS_SCANNED, ops.rows_scanned);
2827 push_compact_metric(&mut metrics, ROWS_FILTERED, ops.rows_filtered);
2828 push_compact_metric(&mut metrics, ROWS_EMITTED, ops.rows_emitted);
2829 push_compact_metric(&mut metrics, SQL_INSERT_CALLS, ops.sql_insert_calls);
2830 push_compact_metric(
2831 &mut metrics,
2832 SQL_INSERT_SELECT_CALLS,
2833 ops.sql_insert_select_calls,
2834 );
2835 push_compact_metric(&mut metrics, SQL_UPDATE_CALLS, ops.sql_update_calls);
2836 push_compact_metric(&mut metrics, SQL_DELETE_CALLS, ops.sql_delete_calls);
2837 push_compact_metric(
2838 &mut metrics,
2839 SQL_WRITE_MATCHED_ROWS,
2840 ops.sql_write_matched_rows,
2841 );
2842 push_compact_metric(
2843 &mut metrics,
2844 SQL_WRITE_MUTATED_ROWS,
2845 ops.sql_write_mutated_rows,
2846 );
2847 push_compact_metric(
2848 &mut metrics,
2849 SQL_WRITE_RETURNING_ROWS,
2850 ops.sql_write_returning_rows,
2851 );
2852 push_compact_metric(
2853 &mut metrics,
2854 SQL_WRITE_STAGED_ROWS,
2855 ops.sql_write_staged_rows,
2856 );
2857 push_compact_metric(
2858 &mut metrics,
2859 CACHE_SHARED_QUERY_PLAN_HITS,
2860 ops.cache_shared_query_plan_hits,
2861 );
2862 push_compact_metric(
2863 &mut metrics,
2864 CACHE_SHARED_QUERY_PLAN_MISSES,
2865 ops.cache_shared_query_plan_misses,
2866 );
2867 push_compact_metric(
2868 &mut metrics,
2869 CACHE_SQL_COMPILED_COMMAND_HITS,
2870 ops.cache_sql_compiled_command_hits,
2871 );
2872 push_compact_metric(
2873 &mut metrics,
2874 CACHE_SQL_COMPILED_COMMAND_MISSES,
2875 ops.cache_sql_compiled_command_misses,
2876 );
2877
2878 metrics
2879}
2880
2881#[must_use]
2891pub(super) fn report_window_start(window_start_ms: Option<u64>) -> EventReport {
2892 let snap = with_state(Clone::clone);
2893 if let Some(requested_window_start_ms) = window_start_ms
2894 && requested_window_start_ms > snap.window_start_ms
2895 {
2896 return EventReport::new(
2897 None,
2898 Vec::new(),
2899 false,
2900 window_start_ms,
2901 snap.window_start_ms,
2902 );
2903 }
2904
2905 let mut entity_counters: Vec<EntitySummary> = Vec::new();
2906 for (path, ops) in &snap.entities {
2907 entity_counters.push(entity_summary_from_counters(path, ops));
2908 }
2909
2910 entity_counters.sort_by(|a, b| {
2911 b.activity_score()
2912 .cmp(&a.activity_score())
2913 .then_with(|| b.rows_loaded.cmp(&a.rows_loaded))
2914 .then_with(|| b.rows_saved.cmp(&a.rows_saved))
2915 .then_with(|| b.rows_scanned.cmp(&a.rows_scanned))
2916 .then_with(|| b.rows_deleted.cmp(&a.rows_deleted))
2917 .then_with(|| a.path.cmp(&b.path))
2918 });
2919
2920 EventReport::new(
2921 Some(EventCounters::new(
2922 snap.ops.clone(),
2923 snap.perf.clone(),
2924 snap.window_start_ms,
2925 now_millis(),
2926 )),
2927 entity_counters,
2928 true,
2929 window_start_ms,
2930 snap.window_start_ms,
2931 )
2932}
2933
2934#[must_use]
2936pub(super) fn compact_report_window_start(window_start_ms: Option<u64>) -> CompactMetricsReport {
2937 let snap = with_state(Clone::clone);
2938 if let Some(requested_window_start_ms) = window_start_ms
2939 && requested_window_start_ms > snap.window_start_ms
2940 {
2941 return CompactMetricsReport::new(None, Vec::new(), window_start_ms, snap.window_start_ms);
2942 }
2943
2944 let mut entity_counters: Vec<CompactEntityMetrics> = Vec::new();
2945 for (path, ops) in &snap.entities {
2946 let metrics = compact_entity_metrics(ops);
2947 if !metrics.is_empty() {
2948 entity_counters.push(CompactEntityMetrics::new(path.clone(), metrics));
2949 }
2950 }
2951
2952 entity_counters.sort_by(|a, b| {
2953 let a_activity = compact_metrics_activity(a.metrics());
2954 let b_activity = compact_metrics_activity(b.metrics());
2955 b_activity
2956 .cmp(&a_activity)
2957 .then_with(|| a.path().cmp(b.path()))
2958 });
2959
2960 CompactMetricsReport::new(
2961 Some(CompactEventCounters::new(
2962 compact_event_metrics(&snap.ops),
2963 snap.window_start_ms,
2964 now_millis(),
2965 )),
2966 entity_counters,
2967 window_start_ms,
2968 snap.window_start_ms,
2969 )
2970}
2971
2972fn compact_metrics_activity(metrics: &[CompactMetric]) -> u64 {
2973 metrics
2974 .iter()
2975 .fold(0, |total, metric| total.saturating_add(metric.value()))
2976}