ic_backup/ops/persistence/download_journal/metrics/
mod.rs1use super::DownloadJournalGuard;
4pub use ic_metrics::{MeasurementAggregate, MeasurementHistogram, MeasurementSummary};
9use std::{
10 sync::PoisonError,
11 time::{Duration, Instant},
12};
13
14const EMPTY_CHUNK_HISTOGRAM: MeasurementHistogram<4> =
15 match MeasurementHistogram::new([0, 32 * 1024, 256 * 1024, 1024 * 1024]) {
16 Ok(histogram) => histogram,
17 Err(_) => panic!("prepared chunk bounds must be strictly increasing"),
18 };
19
20#[derive(Clone, Copy, Debug, Eq, PartialEq)]
36pub struct IcSnapshotLocalMetrics {
37 verification_success_ns: MeasurementSummary,
38 verification_failure_ns: MeasurementSummary,
39 upload_metadata_success_ns: MeasurementSummary,
40 upload_metadata_failure_ns: MeasurementSummary,
41 upload_data_success_ns: MeasurementSummary,
42 upload_data_failure_ns: MeasurementSummary,
43 prepared_chunk_bytes: MeasurementHistogram<4>,
44}
45
46impl Default for IcSnapshotLocalMetrics {
47 fn default() -> Self {
48 Self {
49 verification_success_ns: MeasurementSummary::EMPTY,
50 verification_failure_ns: MeasurementSummary::EMPTY,
51 upload_metadata_success_ns: MeasurementSummary::EMPTY,
52 upload_metadata_failure_ns: MeasurementSummary::EMPTY,
53 upload_data_success_ns: MeasurementSummary::EMPTY,
54 upload_data_failure_ns: MeasurementSummary::EMPTY,
55 prepared_chunk_bytes: EMPTY_CHUNK_HISTOGRAM,
56 }
57 }
58}
59
60impl IcSnapshotLocalMetrics {
61 #[must_use]
63 pub const fn verification_success_ns(self) -> MeasurementSummary {
64 self.verification_success_ns
65 }
66 #[must_use]
68 pub const fn verification_failure_ns(self) -> MeasurementSummary {
69 self.verification_failure_ns
70 }
71 #[must_use]
73 pub const fn upload_metadata_success_ns(self) -> MeasurementSummary {
74 self.upload_metadata_success_ns
75 }
76 #[must_use]
78 pub const fn upload_metadata_failure_ns(self) -> MeasurementSummary {
79 self.upload_metadata_failure_ns
80 }
81 #[must_use]
83 pub const fn upload_data_success_ns(self) -> MeasurementSummary {
84 self.upload_data_success_ns
85 }
86 #[must_use]
88 pub const fn upload_data_failure_ns(self) -> MeasurementSummary {
89 self.upload_data_failure_ns
90 }
91 #[must_use]
96 pub const fn prepared_chunk_bytes(self) -> MeasurementAggregate {
97 self.prepared_chunk_bytes.aggregate()
98 }
99 #[must_use]
108 pub const fn prepared_chunk_bytes_histogram(self) -> MeasurementHistogram<4> {
109 self.prepared_chunk_bytes
110 }
111
112 fn record(
113 &mut self,
114 operation: LocalOperation,
115 elapsed: Duration,
116 succeeded: bool,
117 chunk_bytes: Option<usize>,
118 ) {
119 let duration = u64::try_from(elapsed.as_nanos());
120 let summary = match (operation, succeeded) {
121 (LocalOperation::Verification, true) => &mut self.verification_success_ns,
122 (LocalOperation::Verification, false) => &mut self.verification_failure_ns,
123 (LocalOperation::UploadMetadata, true) => &mut self.upload_metadata_success_ns,
124 (LocalOperation::UploadMetadata, false) => &mut self.upload_metadata_failure_ns,
125 (LocalOperation::UploadData, true) => &mut self.upload_data_success_ns,
126 (LocalOperation::UploadData, false) => &mut self.upload_data_failure_ns,
127 };
128 if let Ok(duration) = duration {
130 summary.record(duration);
131 }
132 if let (LocalOperation::UploadData, true, Some(bytes)) = (operation, succeeded, chunk_bytes)
133 && let Ok(bytes) = u64::try_from(bytes)
134 {
135 self.prepared_chunk_bytes.record(bytes);
136 }
137 }
138}
139
140#[derive(Clone, Copy)]
141pub(super) enum LocalOperation {
142 Verification,
143 UploadMetadata,
144 UploadData,
145}
146
147impl DownloadJournalGuard<'_> {
148 #[must_use]
156 pub fn ic_snapshot_metrics(&self) -> IcSnapshotLocalMetrics {
157 *self
158 .ic_snapshot_metrics
159 .lock()
160 .unwrap_or_else(PoisonError::into_inner)
161 }
162
163 pub(super) fn record_ic_snapshot_metrics(
164 &self,
165 operation: LocalOperation,
166 started: Instant,
167 succeeded: bool,
168 chunk_bytes: Option<usize>,
169 ) {
170 let elapsed = started.elapsed();
171 self.ic_snapshot_metrics
172 .lock()
173 .unwrap_or_else(PoisonError::into_inner)
174 .record(operation, elapsed, succeeded, chunk_bytes);
175 }
176}
177
178#[cfg(test)]
179mod tests;