Skip to main content

canic_core/workflow/metrics/
query.rs

1use crate::{
2    dto::{
3        metrics::{
4            AccessMetricEntry, CyclesFundingMetricEntry, DelegationMetricEntry, EndpointHealth,
5            HttpMetricEntry, IccMetricEntry, RootCapabilityMetricEntry, SystemMetricEntry,
6            TimerMetricEntry,
7        },
8        page::{Page, PageRequest},
9    },
10    ops::{
11        perf::PerfOps,
12        runtime::metrics::{
13            MetricsOps,
14            mapper::{
15                AccessMetricEntryMapper, CyclesFundingMetricEntryMapper,
16                DelegationMetricEntryMapper, EndpointHealthMapper, HttpMetricEntryMapper,
17                IccMetricEntryMapper, RootCapabilityMetricEntryMapper, SystemMetricEntryMapper,
18                TimerMetricEntryMapper,
19            },
20        },
21    },
22    perf::PerfEntry,
23    workflow::view::paginate::paginate_vec,
24};
25
26///
27/// MetricsQuery
28///
29/// Read-only query façade over metric snapshots.
30/// Responsible for mapping, sorting, and pagination only.
31///
32
33pub struct MetricsQuery;
34
35impl MetricsQuery {
36    #[must_use]
37    pub fn system_snapshot() -> Vec<SystemMetricEntry> {
38        let snapshot = MetricsOps::system_snapshot();
39        let mut entries = SystemMetricEntryMapper::record_to_view(snapshot.entries);
40
41        entries.sort_by(|a, b| a.kind.cmp(&b.kind));
42
43        entries
44    }
45
46    #[must_use]
47    pub fn icc_page(page: PageRequest) -> Page<IccMetricEntry> {
48        let snapshot = MetricsOps::icc_snapshot();
49        let mut entries = IccMetricEntryMapper::record_to_view(snapshot.entries);
50
51        entries.sort_by(|a, b| {
52            a.target
53                .as_slice()
54                .cmp(b.target.as_slice())
55                .then_with(|| a.method.cmp(&b.method))
56        });
57
58        paginate_vec(entries, page)
59    }
60
61    #[must_use]
62    pub fn http_page(page: PageRequest) -> Page<HttpMetricEntry> {
63        let snapshot = MetricsOps::http_snapshot();
64        let mut entries = HttpMetricEntryMapper::record_to_view(snapshot.entries);
65
66        entries.sort_by(|a, b| a.method.cmp(&b.method).then_with(|| a.label.cmp(&b.label)));
67
68        paginate_vec(entries, page)
69    }
70
71    #[must_use]
72    pub fn timer_page(page: PageRequest) -> Page<TimerMetricEntry> {
73        let snapshot = MetricsOps::timer_snapshot();
74        let mut entries = TimerMetricEntryMapper::record_to_view(snapshot.entries);
75
76        entries.sort_by(|a, b| {
77            a.mode
78                .cmp(&b.mode)
79                .then_with(|| a.delay_ms.cmp(&b.delay_ms))
80                .then_with(|| a.label.cmp(&b.label))
81        });
82
83        paginate_vec(entries, page)
84    }
85
86    #[must_use]
87    pub fn access_page(page: PageRequest) -> Page<AccessMetricEntry> {
88        let snapshot = MetricsOps::access_snapshot();
89        let mut entries = AccessMetricEntryMapper::record_to_view(snapshot.entries);
90
91        entries.sort_by(|a, b| {
92            a.endpoint
93                .cmp(&b.endpoint)
94                .then_with(|| a.kind.cmp(&b.kind))
95                .then_with(|| a.predicate.cmp(&b.predicate))
96        });
97
98        paginate_vec(entries, page)
99    }
100
101    #[must_use]
102    pub fn delegation_page(page: PageRequest) -> Page<DelegationMetricEntry> {
103        let snapshot = MetricsOps::delegation_snapshot();
104        let mut entries = DelegationMetricEntryMapper::record_to_view(snapshot.entries);
105
106        entries.sort_by(|a, b| a.authority.as_slice().cmp(b.authority.as_slice()));
107
108        paginate_vec(entries, page)
109    }
110
111    #[must_use]
112    pub fn root_capability_page(page: PageRequest) -> Page<RootCapabilityMetricEntry> {
113        let snapshot = MetricsOps::root_capability_snapshot();
114        let mut entries = RootCapabilityMetricEntryMapper::record_to_view(snapshot.entries);
115
116        entries.sort_by(|a, b| {
117            a.capability
118                .cmp(&b.capability)
119                .then_with(|| a.event_type.cmp(&b.event_type))
120                .then_with(|| a.outcome.cmp(&b.outcome))
121                .then_with(|| a.proof_mode.cmp(&b.proof_mode))
122        });
123
124        paginate_vec(entries, page)
125    }
126
127    #[must_use]
128    pub fn cycles_funding_page(page: PageRequest) -> Page<CyclesFundingMetricEntry> {
129        let snapshot = MetricsOps::cycles_funding_snapshot();
130        let mut entries = CyclesFundingMetricEntryMapper::record_to_view(snapshot.entries);
131
132        entries.sort_by(|a, b| {
133            a.metric
134                .cmp(&b.metric)
135                .then_with(|| a.child_principal.cmp(&b.child_principal))
136                .then_with(|| a.reason.cmp(&b.reason))
137        });
138
139        paginate_vec(entries, page)
140    }
141
142    #[must_use]
143    pub fn perf_page(page: PageRequest) -> Page<PerfEntry> {
144        let snapshot = PerfOps::snapshot();
145        paginate_vec(snapshot.entries, page)
146    }
147
148    #[must_use]
149    pub fn endpoint_health_page(
150        page: PageRequest,
151        exclude_endpoint: Option<&str>,
152    ) -> Page<EndpointHealth> {
153        let snapshot = MetricsOps::endpoint_health_snapshot();
154        let mut entries = EndpointHealthMapper::record_to_view(
155            snapshot.attempts,
156            snapshot.results,
157            snapshot.access,
158            exclude_endpoint,
159        );
160
161        entries.sort_by(|a, b| a.endpoint.cmp(&b.endpoint));
162
163        paginate_vec(entries, page)
164    }
165}