system_update_committer/metadata/
inspect.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use super::errors::MetadataError;
6use fuchsia_inspect as finspect;
7use std::time::Duration;
8
9/// Updates inspect state based on the result of the verifications. The inspect hierarchy is
10/// constructed in a way that's compatible with Lapis.
11pub(super) fn write_to_inspect(
12    node: &finspect::Node,
13    res: Result<(), &MetadataError>,
14    total_duration: Duration,
15) {
16    // We need to convert duration to a u64 because that's the largest size integer that inspect
17    // can accept. This is safe because duration will be max 1 hour, which fits into u64.
18    // For context, 2^64 microseconds is over 5000 centuries.
19    let total_duration_u64 = total_duration.as_micros().try_into().unwrap_or(u64::MAX);
20
21    match res {
22        Ok(()) => node.record_child("ota_verification_duration", |duration_node| {
23            duration_node.record_uint("success", total_duration_u64)
24        }),
25        Err(MetadataError::Timeout) => {
26            node.record_child("ota_verification_duration", |duration_node| {
27                duration_node.record_uint("failure_timeout", total_duration_u64);
28            });
29            node.record_child("ota_verification_failure", |reason_node| {
30                reason_node.record_uint("timeout", 1);
31            });
32        }
33        Err(MetadataError::HealthVerification(_)) => {
34            node.record_child("ota_verification_duration", |duration_node| {
35                duration_node.record_uint("failure_health_check", total_duration_u64);
36            });
37            node.record_child("ota_verification_failure", |reason_node| {
38                reason_node.record_uint("verify", 1);
39            });
40        }
41        Err(_) => {
42            node.record_child("ota_verification_duration", |duration_node| {
43                duration_node.record_uint("failure_internal", total_duration_u64);
44            });
45            node.record_child("ota_verification_failure", |reason_node| {
46                reason_node.record_uint("internal", 1);
47            });
48        }
49    };
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55    use diagnostics_assertions::assert_data_tree;
56    use fuchsia_inspect::Inspector;
57
58    #[test]
59    fn success() {
60        let inspector = Inspector::default();
61
62        let () = write_to_inspect(inspector.root(), Ok(()), Duration::from_micros(2));
63
64        assert_data_tree! {
65            inspector,
66            root: {
67                "ota_verification_duration": {
68                    "success" : 2u64,
69                }
70            }
71        }
72    }
73
74    #[test]
75    fn failure_verify() {
76        let inspector = Inspector::default();
77
78        let () = write_to_inspect(
79            inspector.root(),
80            Err(&MetadataError::HealthVerification(
81                crate::metadata::errors::HealthVerificationError::Unhealthy(zx::Status::INTERNAL),
82            )),
83            Duration::from_micros(2),
84        );
85
86        assert_data_tree! {
87            inspector,
88            root: {
89                "ota_verification_duration": {
90                    "failure_health_check" : 2u64,
91                },
92                "ota_verification_failure": {
93                    "verify": 1u64,
94                }
95            }
96        }
97    }
98
99    #[test]
100    fn failure_timeout() {
101        let inspector = Inspector::default();
102
103        let () = write_to_inspect(
104            inspector.root(),
105            Err(&MetadataError::Timeout),
106            Duration::from_micros(2),
107        );
108
109        assert_data_tree! {
110            inspector,
111            root: {
112                "ota_verification_duration": {
113                    "failure_timeout" : 2u64,
114                },
115                "ota_verification_failure": {
116                    "timeout": 1u64,
117                }
118            }
119        }
120    }
121
122    #[test]
123    fn failure_internal() {
124        let inspector = Inspector::default();
125
126        let () = write_to_inspect(
127            inspector.root(),
128            Err(&MetadataError::Unblock),
129            Duration::from_micros(2),
130        );
131
132        assert_data_tree! {
133            inspector,
134            root: {
135                "ota_verification_duration": {
136                    "failure_internal" : 2u64,
137                },
138                "ota_verification_failure": {
139                    "internal": 1u64,
140                }
141            }
142        }
143    }
144
145    /// Verify the reported duration is u64::MAX (millis), even if the actual duration is longer.
146    #[test]
147    fn success_duration_max_u64() {
148        let inspector = Inspector::default();
149
150        let () = write_to_inspect(inspector.root(), Ok(()), Duration::new(u64::MAX, 0));
151
152        assert_data_tree! {
153            inspector,
154            root: {
155                "ota_verification_duration": {
156                    "success" : u64::MAX,
157                }
158            }
159        }
160    }
161}