diff --git a/CHANGELOG.md b/CHANGELOG.md index c71fd37..d4592d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.11.0] - unreleased + +- Add support for OpenMetrics Info metrics (see [PR 18]). + +[PR 18]: https://github.com/mxinden/rust-open-metrics-client/pull/18 + ## [0.10.1] - 2021-05-31 ### Added - Implement `Encode` for `u32`. diff --git a/Cargo.toml b/Cargo.toml index 1a74367..d1d82f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "open-metrics-client" -version = "0.10.1" +version = "0.11.0" authors = ["Max Inden "] edition = "2018" description = "Open Metrics client library allowing users to natively instrument applications." diff --git a/README.md b/README.md index c03b339..e713357 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,6 @@ behind the Open Metrics specification. Not being compliant with all requirements (`MUST` and `MUST NOT`) of the specification is considered a bug and likely to be fixed in the future. Contributions in all forms are most welcome. -- Info metric. - - State set metric. - Enforce "A Histogram MetricPoint MUST contain at least one bucket". diff --git a/src/encoding/text.rs b/src/encoding/text.rs index 646c684..81d9e1c 100644 --- a/src/encoding/text.rs +++ b/src/encoding/text.rs @@ -29,6 +29,7 @@ use crate::metrics::exemplar::{CounterWithExemplar, Exemplar, HistogramWithExemp use crate::metrics::family::Family; use crate::metrics::gauge::{self, Gauge}; use crate::metrics::histogram::Histogram; +use crate::metrics::info::Info; use crate::metrics::{MetricType, TypedMetric}; use crate::registry::{Registry, Unit}; @@ -167,6 +168,7 @@ impl Encode for MetricType { MetricType::Counter => "counter", MetricType::Gauge => "gauge", MetricType::Histogram => "histogram", + MetricType::Info => "info", MetricType::Unknown => "unknown", }; @@ -540,6 +542,28 @@ fn encode_histogram_with_maybe_exemplars( Ok(()) } +///////////////////////////////////////////////////////////////////////////////// +// Info + +impl EncodeMetric for Info +where + S: Clone + std::hash::Hash + Eq + Encode, +{ + fn encode(&self, mut encoder: Encoder) -> Result<(), std::io::Error> { + encoder + .encode_suffix("info")? + .no_bucket()? + .encode_value(1u32)? + .no_exemplar()?; + + Ok(()) + } + + fn metric_type(&self) -> MetricType { + Self::TYPE + } +} + #[cfg(test)] mod tests { use super::*; @@ -639,6 +663,24 @@ mod tests { parse_with_python_client(String::from_utf8(encoded).unwrap()); } + #[test] + fn encode_info() { + let mut registry = Registry::default(); + let info = Info::new(vec![("os".to_string(), "GNU/linux".to_string())]); + registry.register("my_info_metric", "My info metric", info); + + let mut encoded = Vec::new(); + encode(&mut encoded, ®istry).unwrap(); + + let expected = "# HELP my_info_metric My info metric.\n".to_owned() + + "# TYPE my_info_metric info\n" + + "my_info_metric_info 1\n" + + "# EOF\n"; + assert_eq!(expected, String::from_utf8(encoded.clone()).unwrap()); + + parse_with_python_client(String::from_utf8(encoded).unwrap()); + } + #[test] fn encode_histogram() { let mut registry = Registry::default(); diff --git a/src/metrics.rs b/src/metrics.rs index a1a314e..5a21654 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -5,6 +5,7 @@ pub mod exemplar; pub mod family; pub mod gauge; pub mod histogram; +pub mod info; /// A metric that is aware of its Open Metrics metric type. pub trait TypedMetric { @@ -16,11 +17,11 @@ pub enum MetricType { Counter, Gauge, Histogram, + Info, Unknown, // Not (yet) supported metric types. // // GaugeHistogram, - // Info, // StateSet, // Summary } diff --git a/src/metrics/info.rs b/src/metrics/info.rs new file mode 100644 index 0000000..aa67509 --- /dev/null +++ b/src/metrics/info.rs @@ -0,0 +1,25 @@ +//! Module implementing an Open Metrics info metric. +//! +//! See [`Info`] for details. + +use crate::metrics::{MetricType, TypedMetric}; + +/// Open Metrics [`Info`] metric "to expose textual information which SHOULD NOT +/// change during process lifetime". +/// +/// ``` +/// # use open_metrics_client::metrics::info::Info; +/// +/// let _info = Info::new(vec![("os", "GNU/linux")]); +/// ``` +pub struct Info(S); + +impl Info { + pub fn new(label_set: S) -> Self { + Self(label_set) + } +} + +impl TypedMetric for Info { + const TYPE: MetricType = MetricType::Info; +}