From 3745f36ab122ce2f05e9bd668f2ae1732db0839f Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Wed, 2 Feb 2022 15:20:29 +0100 Subject: [PATCH] metrics: use builder pattern for adding tags Rather than going from a list of `(&str, &str)` tuples to a `HashMap`, add a `.tag()` builder method and use `Cow` behind the scenes to efficiently allow the caller to choose between a static literal and a `String` value. Previously the methods forced `&str` slices and then always-copied those into `String`s even if the caller could just *move* it. Signed-off-by: Wolfgang Bumiller --- proxmox-metrics/src/lib.rs | 52 ++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/proxmox-metrics/src/lib.rs b/proxmox-metrics/src/lib.rs index 75c22e39..a55f0afc 100644 --- a/proxmox-metrics/src/lib.rs +++ b/proxmox-metrics/src/lib.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::collections::HashMap; use std::sync::Arc; @@ -14,10 +15,10 @@ pub use influxdb::{influxdb_http, influxdb_udp, test_influxdb_http, test_influxd /// Structured data for the metric server. pub struct MetricsData { /// The category of measurements. - pub measurement: String, + pub measurement: Cow<'static, str>, /// A list of to attach to the measurements. - pub tags: HashMap, + pub tags: HashMap, Cow<'static, str>>, /// The actual values to send. Only plain (not-nested) objects are supported at the moment. pub values: Value, @@ -27,25 +28,44 @@ pub struct MetricsData { } impl MetricsData { - /// Convenient helper to create from references. - pub fn new( - measurement: &str, - tags: &[(&str, &str)], - ctime: i64, - values: V, - ) -> Result { - let mut new_tags = HashMap::new(); - for (key, value) in tags { - new_tags.insert(key.to_string(), value.to_string()); - } - + /// Create a new metrics data entry. + /// + /// ``` + /// # use proxmox_metrics::MetricsData; + /// # fn test( + /// # ctime: i64, + /// # stat: &'static str, + /// # nodename: String, + /// # ) -> Result<(), anyhow::Error> { + /// let data = MetricsData::new("memory", ctime, stat)? + /// .tag("object", "host") + /// .tag("host", nodename); + /// # Ok(()) + /// # } + /// # test(0, "foo", "nodename".to_string()).unwrap(); + /// ``` + pub fn new(measurement: S, ctime: i64, values: V) -> Result + where + S: Into>, + V: Serialize, + { Ok(Self { - measurement: measurement.to_string(), - tags: new_tags, values: serde_json::to_value(values)?, + measurement: measurement.into(), + tags: HashMap::new(), ctime, }) } + + /// Add a tag. + pub fn tag(mut self, key: K, value: V) -> Self + where + K: Into>, + V: Into>, + { + self.tags.insert(key.into(), value.into()); + self + } } /// Helper to send a list of [`MetricsData`] to a list of [`Metrics`].