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 domain::metrics::MetricsKind, dto::metrics::MetricValue, ids::CanisterRole,
127 ops::runtime::metrics,
128 };
129
130 #[test]
132 fn canister_ops_metrics_api_records_rows() {
133 metrics::reset_for_tests();
134
135 CanisterOpsMetricsApi::record(
136 CanisterOpsMetricOperation::Install,
137 &CanisterRole::new("app"),
138 CanisterOpsMetricOutcome::Failed,
139 CanisterOpsMetricReason::MissingWasm,
140 );
141
142 let entries = metrics::entries(MetricsKind::Core);
143
144 assert_count(
145 &entries,
146 &["canister_ops", "install", "app", "failed", "missing_wasm"],
147 1,
148 );
149 }
150
151 #[test]
153 fn wasm_store_metrics_api_records_rows() {
154 metrics::reset_for_tests();
155
156 WasmStoreMetricsApi::record(
157 WasmStoreMetricOperation::SourceResolve,
158 WasmStoreMetricSource::Store,
159 WasmStoreMetricOutcome::Failed,
160 WasmStoreMetricReason::StoreCall,
161 );
162
163 let entries = metrics::entries(MetricsKind::Storage);
164
165 assert_count(
166 &entries,
167 &[
168 "wasm_store",
169 "source_resolve",
170 "store",
171 "failed",
172 "store_call",
173 ],
174 1,
175 );
176 }
177
178 #[test]
180 fn lifecycle_metrics_api_records_runtime_and_bootstrap_rows() {
181 metrics::reset_for_tests();
182
183 LifecycleMetricsApi::record_runtime(
184 LifecycleMetricPhase::Init,
185 LifecycleMetricRole::Root,
186 LifecycleMetricOutcome::Completed,
187 );
188 LifecycleMetricsApi::record_bootstrap(
189 LifecycleMetricPhase::PostUpgrade,
190 LifecycleMetricRole::Nonroot,
191 LifecycleMetricOutcome::Scheduled,
192 );
193
194 let entries = metrics::entries(MetricsKind::Core);
195
196 assert_count(
197 &entries,
198 &["lifecycle", "init", "root", "runtime", "completed"],
199 1,
200 );
201 assert_count(
202 &entries,
203 &[
204 "lifecycle",
205 "post_upgrade",
206 "nonroot",
207 "bootstrap",
208 "scheduled",
209 ],
210 1,
211 );
212 }
213
214 fn assert_count(entries: &[crate::dto::metrics::MetricEntry], labels: &[&str], count: u64) {
216 let entry = entries
217 .iter()
218 .find(|entry| {
219 entry
220 .labels
221 .iter()
222 .map(String::as_str)
223 .eq(labels.iter().copied())
224 })
225 .expect("metric entry should exist");
226
227 std::assert_matches!(
228 &entry.value,
229 MetricValue::Count(actual) if *actual == count
230 );
231 }
232 }
233}