Skip to main content

canic_core/dto/
runtime.rs

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