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)]
34pub struct IcSnapshotLocalMetrics {
35 verification_success_ns: MeasurementSummary,
36 verification_failure_ns: MeasurementSummary,
37 upload_metadata_success_ns: MeasurementSummary,
38 upload_metadata_failure_ns: MeasurementSummary,
39 upload_data_success_ns: MeasurementSummary,
40 upload_data_failure_ns: MeasurementSummary,
41 prepared_chunk_bytes: MeasurementHistogram<4>,
42}
43
44impl Default for IcSnapshotLocalMetrics {
45 fn default() -> Self {
46 Self {
47 verification_success_ns: MeasurementSummary::EMPTY,
48 verification_failure_ns: MeasurementSummary::EMPTY,
49 upload_metadata_success_ns: MeasurementSummary::EMPTY,
50 upload_metadata_failure_ns: MeasurementSummary::EMPTY,
51 upload_data_success_ns: MeasurementSummary::EMPTY,
52 upload_data_failure_ns: MeasurementSummary::EMPTY,
53 prepared_chunk_bytes: EMPTY_CHUNK_HISTOGRAM,
54 }
55 }
56}
57
58impl IcSnapshotLocalMetrics {
59 #[must_use]
61 pub const fn verification_success_ns(self) -> MeasurementSummary {
62 self.verification_success_ns
63 }
64 #[must_use]
66 pub const fn verification_failure_ns(self) -> MeasurementSummary {
67 self.verification_failure_ns
68 }
69 #[must_use]
71 pub const fn upload_metadata_success_ns(self) -> MeasurementSummary {
72 self.upload_metadata_success_ns
73 }
74 #[must_use]
76 pub const fn upload_metadata_failure_ns(self) -> MeasurementSummary {
77 self.upload_metadata_failure_ns
78 }
79 #[must_use]
81 pub const fn upload_data_success_ns(self) -> MeasurementSummary {
82 self.upload_data_success_ns
83 }
84 #[must_use]
86 pub const fn upload_data_failure_ns(self) -> MeasurementSummary {
87 self.upload_data_failure_ns
88 }
89 #[must_use]
94 pub const fn prepared_chunk_bytes(self) -> MeasurementAggregate {
95 self.prepared_chunk_bytes.aggregate()
96 }
97 #[must_use]
106 pub const fn prepared_chunk_bytes_histogram(self) -> MeasurementHistogram<4> {
107 self.prepared_chunk_bytes
108 }
109
110 fn record(
111 &mut self,
112 operation: LocalOperation,
113 elapsed: Duration,
114 succeeded: bool,
115 chunk_bytes: Option<usize>,
116 ) {
117 let duration = u64::try_from(elapsed.as_nanos());
118 let summary = match (operation, succeeded) {
119 (LocalOperation::Verification, true) => &mut self.verification_success_ns,
120 (LocalOperation::Verification, false) => &mut self.verification_failure_ns,
121 (LocalOperation::UploadMetadata, true) => &mut self.upload_metadata_success_ns,
122 (LocalOperation::UploadMetadata, false) => &mut self.upload_metadata_failure_ns,
123 (LocalOperation::UploadData, true) => &mut self.upload_data_success_ns,
124 (LocalOperation::UploadData, false) => &mut self.upload_data_failure_ns,
125 };
126 if let Ok(duration) = duration {
128 summary.record(duration);
129 }
130 if let (LocalOperation::UploadData, true, Some(bytes)) = (operation, succeeded, chunk_bytes)
131 && let Ok(bytes) = u64::try_from(bytes)
132 {
133 self.prepared_chunk_bytes.record(bytes);
134 }
135 }
136}
137
138#[derive(Clone, Copy)]
139pub(super) enum LocalOperation {
140 Verification,
141 UploadMetadata,
142 UploadData,
143}
144
145impl DownloadJournalGuard<'_> {
146 #[must_use]
154 pub fn ic_snapshot_metrics(&self) -> IcSnapshotLocalMetrics {
155 *self
156 .ic_snapshot_metrics
157 .lock()
158 .unwrap_or_else(PoisonError::into_inner)
159 }
160
161 pub(super) fn record_ic_snapshot_metrics(
162 &self,
163 operation: LocalOperation,
164 started: Instant,
165 succeeded: bool,
166 chunk_bytes: Option<usize>,
167 ) {
168 let elapsed = started.elapsed();
169 self.ic_snapshot_metrics
170 .lock()
171 .unwrap_or_else(PoisonError::into_inner)
172 .record(operation, elapsed, succeeded, chunk_bytes);
173 }
174}
175
176#[cfg(test)]
177mod tests;