canic_core/api/lifecycle/
mod.rs1pub mod nonroot;
2pub mod root;
3
4pub mod metrics {
5 use crate::{
6 ids::CanisterRole,
7 ops::runtime::metrics::{
8 canister_ops::CanisterOpsMetrics, lifecycle::LifecycleMetrics,
9 wasm_store::WasmStoreMetrics,
10 },
11 };
12
13 pub use crate::ops::runtime::metrics::canister_ops::{
14 CanisterOpsMetricOperation, CanisterOpsMetricOutcome, CanisterOpsMetricReason,
15 };
16
17 pub use crate::ops::runtime::metrics::lifecycle::{
18 LifecycleMetricOutcome, LifecycleMetricPhase, LifecycleMetricRole, LifecycleMetricStage,
19 };
20
21 pub use crate::ops::runtime::metrics::wasm_store::{
22 WasmStoreMetricOperation, WasmStoreMetricOutcome, WasmStoreMetricReason,
23 WasmStoreMetricSource,
24 };
25
26 pub struct CanisterOpsMetricsApi;
31
32 impl CanisterOpsMetricsApi {
33 pub fn record(
35 operation: CanisterOpsMetricOperation,
36 role: &CanisterRole,
37 outcome: CanisterOpsMetricOutcome,
38 reason: CanisterOpsMetricReason,
39 ) {
40 CanisterOpsMetrics::record(operation, role, outcome, reason);
41 }
42
43 pub fn record_unscoped(
45 operation: CanisterOpsMetricOperation,
46 outcome: CanisterOpsMetricOutcome,
47 reason: CanisterOpsMetricReason,
48 ) {
49 CanisterOpsMetrics::record_unscoped(operation, outcome, reason);
50 }
51
52 pub fn record_unknown_role(
54 operation: CanisterOpsMetricOperation,
55 outcome: CanisterOpsMetricOutcome,
56 reason: CanisterOpsMetricReason,
57 ) {
58 CanisterOpsMetrics::record_unknown_role(operation, outcome, reason);
59 }
60 }
61
62 pub struct WasmStoreMetricsApi;
67
68 impl WasmStoreMetricsApi {
69 pub fn record(
71 operation: WasmStoreMetricOperation,
72 source: WasmStoreMetricSource,
73 outcome: WasmStoreMetricOutcome,
74 reason: WasmStoreMetricReason,
75 ) {
76 WasmStoreMetrics::record(operation, source, outcome, reason);
77 }
78 }
79
80 pub struct LifecycleMetricsApi;
85
86 impl LifecycleMetricsApi {
87 pub fn record(
89 phase: LifecycleMetricPhase,
90 role: LifecycleMetricRole,
91 stage: LifecycleMetricStage,
92 outcome: LifecycleMetricOutcome,
93 ) {
94 LifecycleMetrics::record(phase, role, stage, outcome);
95 }
96
97 pub fn record_runtime(
99 phase: LifecycleMetricPhase,
100 role: LifecycleMetricRole,
101 outcome: LifecycleMetricOutcome,
102 ) {
103 Self::record(phase, role, LifecycleMetricStage::Runtime, outcome);
104 }
105
106 pub fn record_bootstrap(
108 phase: LifecycleMetricPhase,
109 role: LifecycleMetricRole,
110 outcome: LifecycleMetricOutcome,
111 ) {
112 Self::record(phase, role, LifecycleMetricStage::Bootstrap, outcome);
113 }
114 }
115
116 #[cfg(test)]
117 mod tests {
118 use super::{
119 CanisterOpsMetricOperation, CanisterOpsMetricOutcome, CanisterOpsMetricReason,
120 CanisterOpsMetricsApi, LifecycleMetricOutcome, LifecycleMetricPhase,
121 LifecycleMetricRole, LifecycleMetricsApi, WasmStoreMetricOperation,
122 WasmStoreMetricOutcome, WasmStoreMetricReason, WasmStoreMetricSource,
123 WasmStoreMetricsApi,
124 };
125 use crate::{
126 dto::metrics::{MetricValue, MetricsKind},
127 ids::CanisterRole,
128 ops::runtime::metrics,
129 };
130
131 #[test]
133 fn canister_ops_metrics_api_records_rows() {
134 metrics::reset_for_tests();
135
136 CanisterOpsMetricsApi::record(
137 CanisterOpsMetricOperation::Install,
138 &CanisterRole::new("app"),
139 CanisterOpsMetricOutcome::Failed,
140 CanisterOpsMetricReason::MissingWasm,
141 );
142
143 let entries = metrics::entries(MetricsKind::Core);
144
145 assert_count(
146 &entries,
147 &["canister_ops", "install", "app", "failed", "missing_wasm"],
148 1,
149 );
150 }
151
152 #[test]
154 fn wasm_store_metrics_api_records_rows() {
155 metrics::reset_for_tests();
156
157 WasmStoreMetricsApi::record(
158 WasmStoreMetricOperation::SourceResolve,
159 WasmStoreMetricSource::Store,
160 WasmStoreMetricOutcome::Failed,
161 WasmStoreMetricReason::StoreCall,
162 );
163
164 let entries = metrics::entries(MetricsKind::Storage);
165
166 assert_count(
167 &entries,
168 &[
169 "wasm_store",
170 "source_resolve",
171 "store",
172 "failed",
173 "store_call",
174 ],
175 1,
176 );
177 }
178
179 #[test]
181 fn lifecycle_metrics_api_records_runtime_and_bootstrap_rows() {
182 metrics::reset_for_tests();
183
184 LifecycleMetricsApi::record_runtime(
185 LifecycleMetricPhase::Init,
186 LifecycleMetricRole::Root,
187 LifecycleMetricOutcome::Completed,
188 );
189 LifecycleMetricsApi::record_bootstrap(
190 LifecycleMetricPhase::PostUpgrade,
191 LifecycleMetricRole::Nonroot,
192 LifecycleMetricOutcome::Scheduled,
193 );
194
195 let entries = metrics::entries(MetricsKind::Core);
196
197 assert_count(
198 &entries,
199 &["lifecycle", "init", "root", "runtime", "completed"],
200 1,
201 );
202 assert_count(
203 &entries,
204 &[
205 "lifecycle",
206 "post_upgrade",
207 "nonroot",
208 "bootstrap",
209 "scheduled",
210 ],
211 1,
212 );
213 }
214
215 fn assert_count(entries: &[crate::dto::metrics::MetricEntry], labels: &[&str], count: u64) {
217 let entry = entries
218 .iter()
219 .find(|entry| {
220 entry
221 .labels
222 .iter()
223 .map(String::as_str)
224 .eq(labels.iter().copied())
225 })
226 .expect("metric entry should exist");
227
228 assert!(matches!(&entry.value, MetricValue::Count(actual) if *actual == count));
229 }
230 }
231}