canic_core/workflow/metrics/
query.rs1use crate::{
2 dto::{
3 metrics::{
4 AccessMetricEntry, CyclesFundingMetricEntry, DelegationMetricEntry, EndpointHealth,
5 HttpMetricEntry, IccMetricEntry, MetricsKind, MetricsRequest, MetricsResponse,
6 RootCapabilityMetricEntry, SystemMetricEntry, 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
26pub struct MetricsQuery;
34
35impl MetricsQuery {
36 #[must_use]
37 pub fn dispatch(req: MetricsRequest) -> MetricsResponse {
38 match req.kind {
39 MetricsKind::System => MetricsResponse::System(Self::system_snapshot()),
40 MetricsKind::Icc => MetricsResponse::Icc(Self::icc_page(req.page)),
41 MetricsKind::Http => MetricsResponse::Http(Self::http_page(req.page)),
42 MetricsKind::Timer => MetricsResponse::Timer(Self::timer_page(req.page)),
43 MetricsKind::Access => MetricsResponse::Access(Self::access_page(req.page)),
44 MetricsKind::Delegation => MetricsResponse::Delegation(Self::delegation_page(req.page)),
45 MetricsKind::RootCapability => {
46 MetricsResponse::RootCapability(Self::root_capability_page(req.page))
47 }
48 MetricsKind::CyclesFunding => {
49 MetricsResponse::CyclesFunding(Self::cycles_funding_page(req.page))
50 }
51 MetricsKind::Perf => MetricsResponse::Perf(Self::perf_page(req.page)),
52 MetricsKind::EndpointHealth => MetricsResponse::EndpointHealth(
53 Self::endpoint_health_page(req.page, Some(crate::protocol::CANIC_METRICS)),
54 ),
55 }
56 }
57
58 #[must_use]
59 pub fn system_snapshot() -> Vec<SystemMetricEntry> {
60 let snapshot = MetricsOps::system_snapshot();
61 let mut entries = SystemMetricEntryMapper::record_to_view(snapshot.entries);
62
63 entries.sort_by(|a, b| a.kind.cmp(&b.kind));
64
65 entries
66 }
67
68 #[must_use]
69 pub fn icc_page(page: PageRequest) -> Page<IccMetricEntry> {
70 let snapshot = MetricsOps::icc_snapshot();
71 let mut entries = IccMetricEntryMapper::record_to_view(snapshot.entries);
72
73 entries.sort_by(|a, b| {
74 a.target
75 .as_slice()
76 .cmp(b.target.as_slice())
77 .then_with(|| a.method.cmp(&b.method))
78 });
79
80 paginate_vec(entries, page)
81 }
82
83 #[must_use]
84 pub fn http_page(page: PageRequest) -> Page<HttpMetricEntry> {
85 let snapshot = MetricsOps::http_snapshot();
86 let mut entries = HttpMetricEntryMapper::record_to_view(snapshot.entries);
87
88 entries.sort_by(|a, b| a.method.cmp(&b.method).then_with(|| a.label.cmp(&b.label)));
89
90 paginate_vec(entries, page)
91 }
92
93 #[must_use]
94 pub fn timer_page(page: PageRequest) -> Page<TimerMetricEntry> {
95 let snapshot = MetricsOps::timer_snapshot();
96 let mut entries = TimerMetricEntryMapper::record_to_view(snapshot.entries);
97
98 entries.sort_by(|a, b| {
99 a.mode
100 .cmp(&b.mode)
101 .then_with(|| a.delay_ms.cmp(&b.delay_ms))
102 .then_with(|| a.label.cmp(&b.label))
103 });
104
105 paginate_vec(entries, page)
106 }
107
108 #[must_use]
109 pub fn access_page(page: PageRequest) -> Page<AccessMetricEntry> {
110 let snapshot = MetricsOps::access_snapshot();
111 let mut entries = AccessMetricEntryMapper::record_to_view(snapshot.entries);
112
113 entries.sort_by(|a, b| {
114 a.endpoint
115 .cmp(&b.endpoint)
116 .then_with(|| a.kind.cmp(&b.kind))
117 .then_with(|| a.predicate.cmp(&b.predicate))
118 });
119
120 paginate_vec(entries, page)
121 }
122
123 #[must_use]
124 pub fn delegation_page(page: PageRequest) -> Page<DelegationMetricEntry> {
125 let snapshot = MetricsOps::delegation_snapshot();
126 let mut entries = DelegationMetricEntryMapper::record_to_view(snapshot.entries);
127
128 entries.sort_by(|a, b| a.authority.as_slice().cmp(b.authority.as_slice()));
129
130 paginate_vec(entries, page)
131 }
132
133 #[must_use]
134 pub fn root_capability_page(page: PageRequest) -> Page<RootCapabilityMetricEntry> {
135 let snapshot = MetricsOps::root_capability_snapshot();
136 let mut entries = RootCapabilityMetricEntryMapper::record_to_view(snapshot.entries);
137
138 entries.sort_by(|a, b| {
139 a.capability
140 .cmp(&b.capability)
141 .then_with(|| a.event_type.cmp(&b.event_type))
142 .then_with(|| a.outcome.cmp(&b.outcome))
143 .then_with(|| a.proof_mode.cmp(&b.proof_mode))
144 });
145
146 paginate_vec(entries, page)
147 }
148
149 #[must_use]
150 pub fn cycles_funding_page(page: PageRequest) -> Page<CyclesFundingMetricEntry> {
151 let snapshot = MetricsOps::cycles_funding_snapshot();
152 let mut entries = CyclesFundingMetricEntryMapper::record_to_view(snapshot.entries);
153
154 entries.sort_by(|a, b| {
155 a.metric
156 .cmp(&b.metric)
157 .then_with(|| a.child_principal.cmp(&b.child_principal))
158 .then_with(|| a.reason.cmp(&b.reason))
159 });
160
161 paginate_vec(entries, page)
162 }
163
164 #[must_use]
165 pub fn perf_page(page: PageRequest) -> Page<PerfEntry> {
166 let snapshot = PerfOps::snapshot();
167 paginate_vec(snapshot.entries, page)
168 }
169
170 #[must_use]
171 pub fn endpoint_health_page(
172 page: PageRequest,
173 exclude_endpoint: Option<&str>,
174 ) -> Page<EndpointHealth> {
175 let snapshot = MetricsOps::endpoint_health_snapshot();
176 let mut entries = EndpointHealthMapper::record_to_view(
177 snapshot.attempts,
178 snapshot.results,
179 snapshot.access,
180 exclude_endpoint,
181 );
182
183 entries.sort_by(|a, b| a.endpoint.cmp(&b.endpoint));
184
185 paginate_vec(entries, page)
186 }
187}