diff --git a/Cargo.toml b/Cargo.toml index 7e919c71..c63f731a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,9 @@ hyper = { version = "0.14.16", features = ["server", "http1", "tcp"] } [build-dependencies] prost-build = { version = "0.11.0", optional = true } +[[example]] +name = "prune" + [[bench]] name = "baseline" harness = false diff --git a/examples/prune.rs b/examples/prune.rs new file mode 100644 index 00000000..370b0ba6 --- /dev/null +++ b/examples/prune.rs @@ -0,0 +1,78 @@ +use std::fmt::Error; +use std::sync::{Arc, Mutex}; +use std::sync::atomic::AtomicU64; +use std::thread; +use std::time::Duration; +use tokio::time::Instant; +use prometheus_client::encoding::{text::encode, EncodeMetric, MetricEncoder}; +use prometheus_client::metrics::family::Family; +use prometheus_client::metrics::{MetricType, TypedMetric}; +use prometheus_client::metrics::counter::Atomic; +use prometheus_client::registry::Registry; +use prometheus_client_derive_encode::EncodeLabelSet; + +#[derive(Default, Debug)] +struct MyCounter { + value: Arc, + last_access: Arc>> +} + +impl TypedMetric for MyCounter { + +} + +impl MyCounter { + pub fn get(&self) -> u64 { + self.value.get() + } + pub fn inc(&self) -> u64 { + let mut last = self.last_access.lock().unwrap(); + *last = Some(Instant::now()); + self.value.inc() + } +} + +impl EncodeMetric for MyCounter { + fn encode(&self, mut encoder: MetricEncoder) -> Result<(), Error> { + encoder.encode_counter::<(), _, u64>(&self.get(), None) + } + + fn metric_type(&self) -> MetricType { + todo!() + } +} + +#[derive(Clone, Hash, Default, Debug, PartialEq, Eq, EncodeLabelSet)] +struct Labels { + name: String +} + +fn main() { + let mut registry = Registry::default(); + + let metric: Family = Family::default(); + registry.register( + "my_custom_metric", + "test", + metric.clone(), + ); + metric.get_or_create(&Labels{name: "apple".to_string()}).inc(); + metric.get_or_create(&Labels{name: "banana".to_string()}).inc(); + + let mut encoded = String::new(); + encode(&mut encoded, ®istry).unwrap(); + + println!("Scrape output:\n{}", encoded); + thread::sleep(Duration::from_secs(1)); + metric.get_or_create(&Labels{name: "banana".to_string()}).inc(); + let now = Instant::now(); + metric.retain(|a, b | { + let last = b.last_access.lock().unwrap().unwrap(); + now.saturating_duration_since(last) > Duration::from_secs(1) + }); + + let mut encoded = String::new(); + encode(&mut encoded, ®istry).unwrap(); + + println!("Scrape output:\n{}", encoded); +} diff --git a/src/metrics/family.rs b/src/metrics/family.rs index 2f23b198..0bf3ce56 100644 --- a/src/metrics/family.rs +++ b/src/metrics/family.rs @@ -288,6 +288,14 @@ impl> Family(&self, f: F) + where + F: FnMut(&S, &mut M) -> bool + { + self.metrics.write().retain(f) + } + pub(crate) fn read(&self) -> RwLockReadGuard> { self.metrics.read() }