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::CanisterOps);
144
145 assert_count(&entries, &["install", "app", "failed", "missing_wasm"], 1);
146 }
147
148 #[test]
150 fn wasm_store_metrics_api_records_rows() {
151 metrics::reset_for_tests();
152
153 WasmStoreMetricsApi::record(
154 WasmStoreMetricOperation::SourceResolve,
155 WasmStoreMetricSource::Store,
156 WasmStoreMetricOutcome::Failed,
157 WasmStoreMetricReason::StoreCall,
158 );
159
160 let entries = metrics::entries(MetricsKind::WasmStore);
161
162 assert_count(
163 &entries,
164 &["source_resolve", "store", "failed", "store_call"],
165 1,
166 );
167 }
168
169 #[test]
171 fn lifecycle_metrics_api_records_runtime_and_bootstrap_rows() {
172 metrics::reset_for_tests();
173
174 LifecycleMetricsApi::record_runtime(
175 LifecycleMetricPhase::Init,
176 LifecycleMetricRole::Root,
177 LifecycleMetricOutcome::Completed,
178 );
179 LifecycleMetricsApi::record_bootstrap(
180 LifecycleMetricPhase::PostUpgrade,
181 LifecycleMetricRole::Nonroot,
182 LifecycleMetricOutcome::Scheduled,
183 );
184
185 let entries = metrics::entries(MetricsKind::Lifecycle);
186
187 assert_count(&entries, &["init", "root", "runtime", "completed"], 1);
188 assert_count(
189 &entries,
190 &["post_upgrade", "nonroot", "bootstrap", "scheduled"],
191 1,
192 );
193 }
194
195 fn assert_count(entries: &[crate::dto::metrics::MetricEntry], labels: &[&str], count: u64) {
197 let entry = entries
198 .iter()
199 .find(|entry| {
200 entry
201 .labels
202 .iter()
203 .map(String::as_str)
204 .eq(labels.iter().copied())
205 })
206 .expect("metric entry should exist");
207
208 assert!(matches!(&entry.value, MetricValue::Count(actual) if *actual == count));
209 }
210 }
211}