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