1use crate::dto::prelude::*;
2use crate::ids::BuildNetwork;
3
4pub use crate::domain::runtime::{
5 FailureSeverity, HealthStatus, ReadinessStatus, RuntimeCheckStatus, RuntimeDiagnosticSeverity,
6 RuntimeFieldVisibility, RuntimeStateDomainStatus, RuntimeStatus, TimerStatus,
7};
8
9pub const RUNTIME_INTROSPECTION_SCHEMA_VERSION: u32 = 1;
10
11#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
16pub struct CanicHealthStatus {
17 pub schema_version: u32,
18 pub status: HealthStatus,
19 pub observed_at_ns: Option<u64>,
20 pub checks: Vec<RuntimeCheck>,
21}
22
23#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
28pub struct CanicReadinessStatus {
29 pub schema_version: u32,
30 pub role: Option<String>,
31 pub status: ReadinessStatus,
32 pub observed_at_ns: u64,
33 pub checks: Vec<RuntimeCheck>,
34 pub blockers: Vec<RuntimeDiagnostic>,
35 pub warnings: Vec<RuntimeDiagnostic>,
36}
37
38#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
43pub struct CanicRuntimeStatus {
44 pub schema_version: u32,
45 pub observed_at_ns: u64,
46 pub canister_id: Principal,
47 pub role: Option<String>,
48 pub root: Option<Principal>,
49 pub build_network: Option<BuildNetwork>,
50 pub build: RuntimeBuildInfo,
51 pub features: Vec<RuntimeFeatureStatus>,
52 pub topology: Option<RuntimeTopologyStatus>,
53 pub timers: Vec<CanicTimerStatus>,
54 pub state: Option<RuntimeStateSummary>,
55 pub auth: Option<RuntimeAuthStatusSummary>,
56 pub blob_storage: Option<RuntimeBlobStorageStatusSummary>,
57 pub recent_failures: Vec<RecentFailure>,
58 pub visibility: Vec<RuntimeVisibilityEntry>,
59 pub readiness: CanicReadinessStatus,
60 pub status: RuntimeStatus,
61}
62
63#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
68pub struct RuntimeBuildInfo {
69 pub package_name: String,
70 pub package_version: String,
71 pub canic_version: String,
72 pub canister_version: u64,
73}
74
75#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
80pub struct RuntimeCheck {
81 pub category: String,
82 pub code: String,
83 pub status: RuntimeCheckStatus,
84 pub subject: String,
85 pub detail: String,
86 pub next: Option<String>,
87 pub source: String,
88}
89
90#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
95pub struct RuntimeDiagnostic {
96 pub category: String,
97 pub code: String,
98 pub severity: RuntimeDiagnosticSeverity,
99 pub subject: String,
100 pub detail: String,
101 pub next: Option<String>,
102 pub source: String,
103}
104
105#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
110pub struct RuntimeFeatureStatus {
111 pub name: String,
112 pub enabled: bool,
113 pub visibility: RuntimeFieldVisibility,
114 pub source: String,
115}
116
117#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
122pub struct RuntimeTopologyStatus {
123 pub root: Option<Principal>,
124 pub parent: Option<Principal>,
125 pub subnet: Option<Principal>,
126 pub source: String,
127}
128
129#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
134pub struct CanicTimerStatus {
135 pub name: String,
136 pub subsystem: String,
137 pub status: TimerStatus,
138 pub enabled: bool,
139 pub registered: bool,
140 pub last_success_at_ns: Option<u64>,
141 pub last_failure_at_ns: Option<u64>,
142 pub next_due_at_ns: Option<u64>,
143 pub consecutive_failures: u64,
144 pub last_error_code: Option<String>,
145 pub last_error_summary: Option<String>,
146}
147
148#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
153pub struct RuntimeStateSummary {
154 pub manifest_schema_version: u32,
155 pub domains: Vec<RuntimeStateDomainSummary>,
156 pub total_stable_memory_pages: Option<u64>,
157}
158
159#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
164pub struct RuntimeStateDomainSummary {
165 pub domain: String,
166 pub version: u32,
167 pub storage: String,
168 pub memory_id: Option<u8>,
169 pub status: RuntimeStateDomainStatus,
170}
171
172#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
177pub struct RuntimeAuthStatusSummary {
178 pub auth_features: Vec<RuntimeFeatureStatus>,
179}
180
181#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
186pub struct RuntimeBlobStorageStatusSummary {
187 pub blob_storage_features: Vec<RuntimeFeatureStatus>,
188}
189
190#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
195pub struct RecentFailure {
196 pub occurred_at_ns: u64,
197 pub subsystem: String,
198 pub code: String,
199 pub severity: FailureSeverity,
200 pub summary: String,
201 pub correlation_id: Option<String>,
202 pub redacted: bool,
203}
204
205#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
210pub struct RuntimeVisibilityEntry {
211 pub field: String,
212 pub visibility: RuntimeFieldVisibility,
213}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218 use candid::{Decode, Encode};
219 use serde::Serialize;
220 use serde::de::DeserializeOwned;
221 use std::fmt::Debug;
222
223 #[test]
224 fn runtime_enums_roundtrip_candid_with_canonical_variant_labels() {
225 assert_enum_candid_contract(HealthStatus::Unknown);
226 assert_enum_candid_contract(ReadinessStatus::NotEvaluated);
227 assert_enum_candid_contract(RuntimeStatus::Failing);
228 assert_enum_candid_contract(TimerStatus::NotRegistered);
229 assert_enum_candid_contract(FailureSeverity::Critical);
230 assert_enum_candid_contract(RuntimeCheckStatus::NotEvaluated);
231 assert_enum_candid_contract(RuntimeDiagnosticSeverity::Unsupported);
232 assert_enum_candid_contract(RuntimeFieldVisibility::OperatorOnly);
233 assert_enum_candid_contract(RuntimeStateDomainStatus::NotEvaluated);
234 }
235
236 #[test]
237 fn runtime_enums_serialize_canonical_snake_case_labels() {
238 assert_enum_serde_contract(HealthStatus::Healthy, HealthStatus::Healthy.label());
239 assert_enum_serde_contract(HealthStatus::Degraded, HealthStatus::Degraded.label());
240 assert_enum_serde_contract(HealthStatus::Unhealthy, HealthStatus::Unhealthy.label());
241 assert_enum_serde_contract(HealthStatus::Unknown, HealthStatus::Unknown.label());
242
243 assert_enum_serde_contract(ReadinessStatus::Ready, ReadinessStatus::Ready.label());
244 assert_enum_serde_contract(ReadinessStatus::Degraded, ReadinessStatus::Degraded.label());
245 assert_enum_serde_contract(ReadinessStatus::NotReady, ReadinessStatus::NotReady.label());
246 assert_enum_serde_contract(
247 ReadinessStatus::NotEvaluated,
248 ReadinessStatus::NotEvaluated.label(),
249 );
250
251 assert_enum_serde_contract(RuntimeStatus::Ok, RuntimeStatus::Ok.label());
252 assert_enum_serde_contract(RuntimeStatus::Degraded, RuntimeStatus::Degraded.label());
253 assert_enum_serde_contract(RuntimeStatus::Failing, RuntimeStatus::Failing.label());
254 assert_enum_serde_contract(RuntimeStatus::Unknown, RuntimeStatus::Unknown.label());
255
256 assert_enum_serde_contract(TimerStatus::Healthy, TimerStatus::Healthy.label());
257 assert_enum_serde_contract(TimerStatus::Delayed, TimerStatus::Delayed.label());
258 assert_enum_serde_contract(TimerStatus::Failing, TimerStatus::Failing.label());
259 assert_enum_serde_contract(TimerStatus::Disabled, TimerStatus::Disabled.label());
260 assert_enum_serde_contract(
261 TimerStatus::NotRegistered,
262 TimerStatus::NotRegistered.label(),
263 );
264 assert_enum_serde_contract(TimerStatus::Unknown, TimerStatus::Unknown.label());
265
266 assert_enum_serde_contract(FailureSeverity::Info, FailureSeverity::Info.label());
267 assert_enum_serde_contract(FailureSeverity::Warning, FailureSeverity::Warning.label());
268 assert_enum_serde_contract(FailureSeverity::Error, FailureSeverity::Error.label());
269 assert_enum_serde_contract(FailureSeverity::Critical, FailureSeverity::Critical.label());
270
271 assert_enum_serde_contract(RuntimeCheckStatus::Pass, RuntimeCheckStatus::Pass.label());
272 assert_enum_serde_contract(RuntimeCheckStatus::Warn, RuntimeCheckStatus::Warn.label());
273 assert_enum_serde_contract(RuntimeCheckStatus::Fail, RuntimeCheckStatus::Fail.label());
274 assert_enum_serde_contract(
275 RuntimeCheckStatus::NotEvaluated,
276 RuntimeCheckStatus::NotEvaluated.label(),
277 );
278
279 assert_enum_serde_contract(
280 RuntimeDiagnosticSeverity::Info,
281 RuntimeDiagnosticSeverity::Info.label(),
282 );
283 assert_enum_serde_contract(
284 RuntimeDiagnosticSeverity::Warning,
285 RuntimeDiagnosticSeverity::Warning.label(),
286 );
287 assert_enum_serde_contract(
288 RuntimeDiagnosticSeverity::Blocked,
289 RuntimeDiagnosticSeverity::Blocked.label(),
290 );
291 assert_enum_serde_contract(
292 RuntimeDiagnosticSeverity::Unsupported,
293 RuntimeDiagnosticSeverity::Unsupported.label(),
294 );
295
296 assert_enum_serde_contract(
297 RuntimeFieldVisibility::PublicSafe,
298 RuntimeFieldVisibility::PublicSafe.label(),
299 );
300 assert_enum_serde_contract(
301 RuntimeFieldVisibility::OperatorOnly,
302 RuntimeFieldVisibility::OperatorOnly.label(),
303 );
304 assert_enum_serde_contract(
305 RuntimeFieldVisibility::ControllerOnly,
306 RuntimeFieldVisibility::ControllerOnly.label(),
307 );
308 assert_enum_serde_contract(
309 RuntimeFieldVisibility::FeatureGated,
310 RuntimeFieldVisibility::FeatureGated.label(),
311 );
312 assert_enum_serde_contract(
313 RuntimeFieldVisibility::Disabled,
314 RuntimeFieldVisibility::Disabled.label(),
315 );
316
317 assert_enum_serde_contract(
318 RuntimeStateDomainStatus::Ok,
319 RuntimeStateDomainStatus::Ok.label(),
320 );
321 assert_enum_serde_contract(
322 RuntimeStateDomainStatus::Warning,
323 RuntimeStateDomainStatus::Warning.label(),
324 );
325 assert_enum_serde_contract(
326 RuntimeStateDomainStatus::Failing,
327 RuntimeStateDomainStatus::Failing.label(),
328 );
329 assert_enum_serde_contract(
330 RuntimeStateDomainStatus::NotEvaluated,
331 RuntimeStateDomainStatus::NotEvaluated.label(),
332 );
333 }
334
335 fn assert_enum_candid_contract<T>(value: T)
336 where
337 T: CandidType + Clone + Debug + DeserializeOwned + Eq,
338 {
339 let bytes = Encode!(&value).expect("encode runtime enum");
340 let decoded = Decode!(&bytes, T).expect("decode runtime enum");
341
342 assert_eq!(decoded, value);
343 }
344
345 fn assert_enum_serde_contract<T>(value: T, label: &str)
346 where
347 T: Clone + Debug + DeserializeOwned + Eq + Serialize,
348 {
349 let encoded = crate::cdk::serialize::serialize(&value).expect("encode runtime enum label");
350 let serialized_label: String =
351 crate::cdk::serialize::deserialize(&encoded).expect("decode runtime enum label");
352 assert_eq!(serialized_label, label);
353
354 let label_bytes =
355 crate::cdk::serialize::serialize(&label).expect("encode canonical runtime enum label");
356 let decoded: T = crate::cdk::serialize::deserialize(&label_bytes)
357 .expect("decode canonical runtime enum label");
358 assert_eq!(decoded, value);
359 }
360}