use std::time::{Duration, Instant};
use crate::instruments::meter::{MeterRate, MeterSnapshot};
use crate::instruments::{BorrowedLabelAndUpdate, Instrument, Meter, Update, Updates};
use crate::snapshot::{ItemKind, Snapshot};
use crate::util;
use crate::{Descriptive, HandlesObservations, Observation, PutsSnapshot};
pub struct MultiMeter<L> {
name: String,
title: Option<String>,
description: Option<String>,
lower_cutoff: f64,
one_minute_rate_enabled: bool,
five_minute_rate_enabled: bool,
fifteen_minute_rate_enabled: bool,
meters: Vec<(L, Meter)>,
}
impl<L> MultiMeter<L>
where
L: Eq + Send + 'static,
{
pub fn new_with_defaults<T: Into<String>>(name: T) -> MultiMeter<L> {
MultiMeter {
name: name.into(),
title: None,
description: None,
lower_cutoff: 0.001,
one_minute_rate_enabled: true,
five_minute_rate_enabled: false,
fifteen_minute_rate_enabled: false,
meters: Vec::new(),
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn set_name<T: Into<String>>(&mut self, name: T) {
self.name = name.into();
}
pub fn set_title<T: Into<String>>(&mut self, title: T) {
self.title = Some(title.into())
}
pub fn set_description<T: Into<String>>(&mut self, description: T) {
self.description = Some(description.into())
}
pub fn set_enable_one_minute_rate_enabled(&mut self, enabled: bool) {
self.one_minute_rate_enabled = enabled;
self.meters
.iter_mut()
.for_each(|(_, m)| m.set_enable_one_minute_rate_enabled(enabled));
}
pub fn set_five_minute_rate_enabled(&mut self, enabled: bool) {
self.five_minute_rate_enabled = enabled;
self.meters
.iter_mut()
.for_each(|(_, m)| m.set_five_minute_rate_enabled(enabled));
}
pub fn set_fifteen_minute_rate_enabled(&mut self, enabled: bool) {
self.fifteen_minute_rate_enabled = enabled;
self.meters
.iter_mut()
.for_each(|(_, m)| m.set_fifteen_minute_rate_enabled(enabled));
}
pub fn set_lower_cutoff(&mut self, cutoff: f64) {
self.lower_cutoff = cutoff;
self.meters
.iter_mut()
.for_each(|(_, m)| m.set_lower_cutoff(cutoff));
}
pub fn add_meter<N: Into<String>, T: Into<String>, D: Into<String>>(
&mut self,
label: L,
name: N,
title: Option<T>,
description: Option<D>,
) {
let mut meter = Meter::new_with_defaults(name);
title.into_iter().for_each(|t| meter.set_title(t));
description
.into_iter()
.for_each(|d| meter.set_description(d));
meter.set_enable_one_minute_rate_enabled(self.one_minute_rate_enabled);
meter.set_five_minute_rate_enabled(self.five_minute_rate_enabled);
meter.set_fifteen_minute_rate_enabled(self.fifteen_minute_rate_enabled);
meter.set_lower_cutoff(self.lower_cutoff);
self.meters.push((label, meter))
}
fn put_values_into_snapshot(&self, into: &mut Snapshot, descriptive: bool) {
let _snapshots: Vec<_> = self.meters.iter().map(|(_, m)| m.get_snapshot()).collect();
}
}
impl<L> PutsSnapshot for MultiMeter<L>
where
L: Clone + Eq + Send + 'static,
{
fn put_snapshot(&self, into: &mut Snapshot, descriptive: bool) {
util::put_postfixed_descriptives(self, &self.name, into, descriptive);
let mut new_level = Snapshot::default();
self.put_values_into_snapshot(&mut new_level, descriptive);
into.push(self.name.clone(), ItemKind::Snapshot(new_level));
}
}
impl<L> HandlesObservations for MultiMeter<L>
where
L: Clone + Eq + Send + 'static,
{
type Label = L;
fn handle_observation(&mut self, observation: &Observation<Self::Label>) -> usize {
let BorrowedLabelAndUpdate(incoming_label, update) = observation.into();
let mut instruments_updated = 0;
self.meters
.iter_mut()
.filter(|(label, _)| incoming_label == label)
.for_each(|(_, meter)| instruments_updated += meter.update(&update));
instruments_updated
}
}
impl<L> ::Descriptive for MultiMeter<L> {
fn title(&self) -> Option<&str> {
self.title.as_ref().map(|n| &**n)
}
fn description(&self) -> Option<&str> {
self.description.as_ref().map(|n| &**n)
}
}