|
| 1 | +// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| 2 | +// SPDX-License-Identifier: Apache-2.0 |
| 3 | + |
| 4 | +//! Defines the metrics system for memory devices. |
| 5 | +//! |
| 6 | +//! # Metrics format |
| 7 | +//! The metrics are flushed in JSON when requested by vmm::logger::metrics::METRICS.write(). |
| 8 | +//! |
| 9 | +//! ## JSON example with metrics: |
| 10 | +//! ```json |
| 11 | +//! "memory_hotplug": { |
| 12 | +//! "activate_fails": "SharedIncMetric", |
| 13 | +//! "queue_event_fails": "SharedIncMetric", |
| 14 | +//! "queue_event_count": "SharedIncMetric", |
| 15 | +//! ... |
| 16 | +//! } |
| 17 | +//! } |
| 18 | +//! ``` |
| 19 | +//! Each `memory` field in the example above is a serializable `VirtioMemDeviceMetrics` structure |
| 20 | +//! collecting metrics such as `activate_fails`, `queue_event_fails` etc. for the memoty hotplug |
| 21 | +//! device. |
| 22 | +//! Since Firecrakcer only supports one virtio-mem device, there is no per device metrics and |
| 23 | +//! `memory_hotplug` represents the aggregate entropy metrics. |
| 24 | +
|
| 25 | +use serde::ser::SerializeMap; |
| 26 | +use serde::{Serialize, Serializer}; |
| 27 | + |
| 28 | +use crate::logger::{LatencyAggregateMetrics, SharedIncMetric}; |
| 29 | + |
| 30 | +/// Stores aggregated virtio-mem metrics |
| 31 | +pub(super) static METRICS: VirtioMemDeviceMetrics = VirtioMemDeviceMetrics::new(); |
| 32 | + |
| 33 | +/// Called by METRICS.flush(), this function facilitates serialization of virtio-mem device metrics. |
| 34 | +pub fn flush_metrics<S: Serializer>(serializer: S) -> Result<S::Ok, S::Error> { |
| 35 | + let mut seq = serializer.serialize_map(Some(1))?; |
| 36 | + seq.serialize_entry("memory_hotplug", &METRICS)?; |
| 37 | + seq.end() |
| 38 | +} |
| 39 | + |
| 40 | +#[derive(Debug, Serialize)] |
| 41 | +pub(super) struct VirtioMemDeviceMetrics { |
| 42 | + /// Number of device activation failures |
| 43 | + pub activate_fails: SharedIncMetric, |
| 44 | + /// Number of queue event handling failures |
| 45 | + pub queue_event_fails: SharedIncMetric, |
| 46 | + /// Number of queue events handled |
| 47 | + pub queue_event_count: SharedIncMetric, |
| 48 | +} |
| 49 | + |
| 50 | +impl VirtioMemDeviceMetrics { |
| 51 | + /// Const default construction. |
| 52 | + const fn new() -> Self { |
| 53 | + Self { |
| 54 | + activate_fails: SharedIncMetric::new(), |
| 55 | + queue_event_fails: SharedIncMetric::new(), |
| 56 | + queue_event_count: SharedIncMetric::new(), |
| 57 | + } |
| 58 | + } |
| 59 | +} |
| 60 | + |
| 61 | +#[cfg(test)] |
| 62 | +pub mod tests { |
| 63 | + use super::*; |
| 64 | + use crate::logger::IncMetric; |
| 65 | + |
| 66 | + #[test] |
| 67 | + fn test_memory_hotplug_metrics() { |
| 68 | + let mem_metrics: VirtioMemDeviceMetrics = VirtioMemDeviceMetrics::new(); |
| 69 | + let mem_metrics_local: String = serde_json::to_string(&mem_metrics).unwrap(); |
| 70 | + // the 1st serialize flushes the metrics and resets values to 0 so that |
| 71 | + // we can compare the values with local metrics. |
| 72 | + serde_json::to_string(&METRICS).unwrap(); |
| 73 | + let mem_metrics_global: String = serde_json::to_string(&METRICS).unwrap(); |
| 74 | + assert_eq!(mem_metrics_local, mem_metrics_global); |
| 75 | + mem_metrics.queue_event_count.inc(); |
| 76 | + assert_eq!(mem_metrics.queue_event_count.count(), 1); |
| 77 | + } |
| 78 | +} |
0 commit comments