vmm/devices/virtio/vsock/metrics.rs
1// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Defines the metrics system for vsock 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//! "vsock": {
12//! "activate_fails": "SharedIncMetric",
13//! "cfg_fails": "SharedIncMetric",
14//! "rx_queue_event_fails": "SharedIncMetric",
15//! "tx_queue_event_fails": "SharedIncMetric",
16//! "ev_queue_event_fails": "SharedIncMetric",
17//! "muxer_event_fails": "SharedIncMetric",
18//! ...
19//! }
20//! }
21//! ```
22//! Each `vsock` field in the example above is a serializable `VsockDeviceMetrics` structure
23//! collecting metrics such as `activate_fails`, `cfg_fails`, etc. for the Vsock device.
24//! Since vsock doesn't support multiple devices, there is no per device metrics and
25//! `vsock` represents the aggregate metrics for all vsock connections.
26//!
27//! # Design
28//! The main design goals of this system are:
29//! * Have a consistent approach of keeping device related metrics in the individual devices
30//! modules.
31//! * To decouple vsock device metrics from logger module by moving VsockDeviceMetrics out of
32//! FirecrackerDeviceMetrics.
33//! * Rely on `serde` to provide the actual serialization for writing the metrics.
34//!
35//! The system implements 1 type of metrics:
36//! * Shared Incremental Metrics (SharedIncMetrics) - dedicated for the metrics which need a counter
37//! (i.e the number of times an API request failed). These metrics are reset upon flush.
38
39use serde::ser::SerializeMap;
40use serde::{Serialize, Serializer};
41
42use crate::logger::SharedIncMetric;
43
44/// Stores aggregate metrics of all Vsock connections/actions
45pub(super) static METRICS: VsockDeviceMetrics = VsockDeviceMetrics::new();
46
47/// Called by METRICS.flush(), this function facilitates serialization of vsock device metrics.
48pub fn flush_metrics<S: Serializer>(serializer: S) -> Result<S::Ok, S::Error> {
49 let mut seq = serializer.serialize_map(Some(1))?;
50 seq.serialize_entry("vsock", &METRICS)?;
51 seq.end()
52}
53
54/// Vsock-related metrics.
55#[derive(Debug, Serialize)]
56pub(super) struct VsockDeviceMetrics {
57 /// Number of times when activate failed on a vsock device.
58 pub activate_fails: SharedIncMetric,
59 /// Number of times when interacting with the space config of a vsock device failed.
60 pub cfg_fails: SharedIncMetric,
61 /// Number of times when handling RX queue events on a vsock device failed.
62 pub rx_queue_event_fails: SharedIncMetric,
63 /// Number of times when handling TX queue events on a vsock device failed.
64 pub tx_queue_event_fails: SharedIncMetric,
65 /// Number of times when handling event queue events on a vsock device failed.
66 pub ev_queue_event_fails: SharedIncMetric,
67 /// Number of times when handling muxer events on a vsock device failed.
68 pub muxer_event_fails: SharedIncMetric,
69 /// Number of times when handling connection events on a vsock device failed.
70 pub conn_event_fails: SharedIncMetric,
71 /// Number of events associated with the receiving queue.
72 pub rx_queue_event_count: SharedIncMetric,
73 /// Number of events associated with the transmitting queue.
74 pub tx_queue_event_count: SharedIncMetric,
75 /// Number of bytes received.
76 pub rx_bytes_count: SharedIncMetric,
77 /// Number of transmitted bytes.
78 pub tx_bytes_count: SharedIncMetric,
79 /// Number of packets received.
80 pub rx_packets_count: SharedIncMetric,
81 /// Number of transmitted packets.
82 pub tx_packets_count: SharedIncMetric,
83 /// Number of added connections.
84 pub conns_added: SharedIncMetric,
85 /// Number of killed connections.
86 pub conns_killed: SharedIncMetric,
87 /// Number of removed connections.
88 pub conns_removed: SharedIncMetric,
89 /// How many times the killq has been resynced.
90 pub killq_resync: SharedIncMetric,
91 /// How many flush fails have been seen.
92 pub tx_flush_fails: SharedIncMetric,
93 /// How many write fails have been seen.
94 pub tx_write_fails: SharedIncMetric,
95 /// Number of times read() has failed.
96 pub rx_read_fails: SharedIncMetric,
97}
98
99impl VsockDeviceMetrics {
100 // We need this because vsock::metrics::METRICS does not accept
101 // VsockDeviceMetrics::default()
102 const fn new() -> Self {
103 Self {
104 activate_fails: SharedIncMetric::new(),
105 cfg_fails: SharedIncMetric::new(),
106 rx_queue_event_fails: SharedIncMetric::new(),
107 tx_queue_event_fails: SharedIncMetric::new(),
108 ev_queue_event_fails: SharedIncMetric::new(),
109 muxer_event_fails: SharedIncMetric::new(),
110 conn_event_fails: SharedIncMetric::new(),
111 rx_queue_event_count: SharedIncMetric::new(),
112 tx_queue_event_count: SharedIncMetric::new(),
113 rx_bytes_count: SharedIncMetric::new(),
114 tx_bytes_count: SharedIncMetric::new(),
115 rx_packets_count: SharedIncMetric::new(),
116 tx_packets_count: SharedIncMetric::new(),
117 conns_added: SharedIncMetric::new(),
118 conns_killed: SharedIncMetric::new(),
119 conns_removed: SharedIncMetric::new(),
120 killq_resync: SharedIncMetric::new(),
121 tx_flush_fails: SharedIncMetric::new(),
122 tx_write_fails: SharedIncMetric::new(),
123 rx_read_fails: SharedIncMetric::new(),
124 }
125 }
126}
127
128#[cfg(test)]
129pub mod tests {
130 use super::*;
131 use crate::logger::IncMetric;
132
133 #[test]
134 fn test_vsock_dev_metrics() {
135 let vsock_metrics: VsockDeviceMetrics = VsockDeviceMetrics::new();
136 let vsock_metrics_local: String = serde_json::to_string(&vsock_metrics).unwrap();
137 // the 1st serialize flushes the metrics and resets values to 0 so that
138 // we can compare the values with local metrics.
139 serde_json::to_string(&METRICS).unwrap();
140 let vsock_metrics_global: String = serde_json::to_string(&METRICS).unwrap();
141 assert_eq!(vsock_metrics_local, vsock_metrics_global);
142 vsock_metrics.conns_added.inc();
143 assert_eq!(vsock_metrics.conns_added.count(), 1);
144 }
145}