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::Unknown, "unknown");
238 assert_enum_serde_contract(ReadinessStatus::NotEvaluated, "not_evaluated");
239 assert_enum_serde_contract(RuntimeStatus::Failing, "failing");
240 assert_enum_serde_contract(TimerStatus::NotRegistered, "not_registered");
241 assert_enum_serde_contract(FailureSeverity::Critical, "critical");
242 assert_enum_serde_contract(RuntimeCheckStatus::NotEvaluated, "not_evaluated");
243 assert_enum_serde_contract(RuntimeDiagnosticSeverity::Unsupported, "unsupported");
244 assert_enum_serde_contract(RuntimeFieldVisibility::OperatorOnly, "operator_only");
245 assert_enum_serde_contract(RuntimeStateDomainStatus::NotEvaluated, "not_evaluated");
246 }
247
248 fn assert_enum_candid_contract<T>(value: T)
249 where
250 T: CandidType + Clone + Debug + DeserializeOwned + Eq,
251 {
252 let bytes = Encode!(&value).expect("encode runtime enum");
253 let decoded = Decode!(&bytes, T).expect("decode runtime enum");
254
255 assert_eq!(decoded, value);
256 }
257
258 fn assert_enum_serde_contract<T>(value: T, label: &str)
259 where
260 T: Clone + Debug + DeserializeOwned + Eq + Serialize,
261 {
262 let encoded = serde_cbor::to_vec(&value).expect("encode runtime enum label");
263 let serialized_label: String =
264 serde_cbor::from_slice(&encoded).expect("decode runtime enum label");
265 assert_eq!(serialized_label, label);
266
267 let label_bytes = serde_cbor::to_vec(&label).expect("encode canonical runtime enum label");
268 let decoded: T =
269 serde_cbor::from_slice(&label_bytes).expect("decode canonical runtime enum label");
270 assert_eq!(decoded, value);
271 }
272}