use std::time::{Duration, Instant};
use crate::snapshot::{ItemKind, Snapshot};
use crate::util;
use crate::{Descriptive, HandlesObservations, Observation, PutsSnapshot};
use super::*;
pub struct Panel<L> {
label_filter: LabelFilter<L>,
name: Option<String>,
title: Option<String>,
description: Option<String>,
counter: Option<InstrumentAdapter<L, Counter>>,
gauge: Option<GaugeAdapter<L>>,
meter: Option<InstrumentAdapter<L, Meter>>,
histogram: Option<InstrumentAdapter<L, Histogram>>,
panels: Vec<Panel<L>>,
handlers: Vec<Box<dyn HandlesObservations<Label = L>>>,
snapshooters: Vec<Box<dyn PutsSnapshot>>,
last_update: Instant,
max_inactivity_duration: Option<Duration>,
}
impl<L> Panel<L>
where
L: Eq + Send + 'static,
{
pub fn new<F: Into<LabelFilter<L>>>(accept: F) -> Panel<L> {
Panel {
label_filter: accept.into(),
name: None,
title: None,
description: None,
counter: None,
gauge: None,
meter: None,
histogram: None,
panels: Vec::new(),
handlers: Vec::new(),
snapshooters: Vec::new(),
last_update: Instant::now(),
max_inactivity_duration: None,
}
}
pub fn named<T: Into<String>, F: Into<LabelFilter<L>>>(accept: F, name: T) -> Panel<L> {
let mut panel = Self::new(accept);
panel.name = Some(name.into());
panel
}
#[deprecated(since = "0.9.24", note = "use 'named'")]
pub fn with_name<T: Into<String>>(label: L, name: T) -> Panel<L> {
Self::named(label, name)
}
pub fn accept<F: Into<LabelFilter<L>>>(accept: F) -> Self {
Self::new(accept)
}
pub fn accept_named<T: Into<String>, F: Into<LabelFilter<L>>>(accept: F, name: T) -> Self {
Self::named(accept, name)
}
pub fn accept_all_named<T: Into<String>>(name: T) -> Panel<L> {
Self::named(AcceptAllLabels, name)
}
pub fn accept_all() -> Panel<L> {
Self::new(AcceptAllLabels)
}
#[deprecated(since = "0.10.9", note = "use 'add_histogram'")]
pub fn set_counter<I: Into<InstrumentAdapter<L, Counter>>>(&mut self, counter: I) {
self.counter = Some(counter.into());
}
pub fn add_counter<I: Into<InstrumentAdapter<L, Counter>>>(&mut self, counter: I) {
if self.counter.is_none() {
self.counter = Some(counter.into());
} else {
self.add_handler(counter.into())
}
}
pub fn counter<I: Into<InstrumentAdapter<L, Counter>>>(mut self, counter: I) -> Self {
self.add_counter(counter);
self
}
#[deprecated(since = "0.10.9", note = "use 'add_gauge'")]
pub fn set_gauge<I: Into<GaugeAdapter<L>>>(&mut self, gauge: I) {
self.gauge = Some(gauge.into());
}
pub fn gauge<I: Into<GaugeAdapter<L>>>(mut self, gauge: I) -> Self {
self.add_gauge(gauge);
self
}
pub fn add_gauge<I: Into<GaugeAdapter<L>>>(&mut self, gauge: I) {
if self.gauge.is_none() {
self.gauge = Some(gauge.into());
} else {
self.add_handler(gauge.into())
}
}
#[deprecated(since = "0.10.9", note = "use 'add_meter'")]
pub fn set_meter<I: Into<InstrumentAdapter<L, Meter>>>(&mut self, meter: I) {
self.meter = Some(meter.into());
}
pub fn meter<I: Into<InstrumentAdapter<L, Meter>>>(mut self, meter: I) -> Self {
self.add_meter(meter);
self
}
pub fn add_meter<I: Into<InstrumentAdapter<L, Meter>>>(&mut self, meter: I) {
if self.meter.is_none() {
self.meter = Some(meter.into());
} else {
self.add_handler(meter.into())
}
}
#[deprecated(since = "0.10.9", note = "use 'add_histogram'")]
pub fn set_histogram<I: Into<InstrumentAdapter<L, Histogram>>>(&mut self, histogram: I) {
self.histogram = Some(histogram.into());
}
pub fn add_histogram<I: Into<InstrumentAdapter<L, Histogram>>>(&mut self, histogram: I) {
if self.histogram.is_none() {
self.histogram = Some(histogram.into());
} else {
self.add_handler(histogram.into())
}
}
pub fn histogram<I: Into<InstrumentAdapter<L, Histogram>>>(mut self, histogram: I) -> Self {
self.add_histogram(histogram);
self
}
pub fn add_snapshooter<T: PutsSnapshot>(&mut self, snapshooter: T) {
self.snapshooters.push(Box::new(snapshooter));
}
pub fn snapshooter<T: PutsSnapshot>(mut self, snapshooter: T) -> Self {
self.add_snapshooter(snapshooter);
self
}
pub fn add_instrument<I: Instrument>(&mut self, instrument: I) {
self.handlers
.push(Box::new(InstrumentAdapter::new(instrument)));
}
pub fn instrument<T: Instrument>(mut self, instrument: T) -> Self {
self.add_instrument(instrument);
self
}
pub fn add_panel(&mut self, panel: Panel<L>) {
self.panels.push(panel);
}
pub fn panel(mut self, panel: Panel<L>) -> Self {
self.add_panel(panel);
self
}
pub fn add_handler<H: HandlesObservations<Label = L>>(&mut self, handler: H) {
self.handlers.push(Box::new(handler));
}
pub fn handler<H: HandlesObservations<Label = L>>(mut self, handler: H) -> Self {
self.add_handler(handler);
self
}
pub fn name(&self) -> Option<&str> {
self.name.as_ref().map(|n| &**n)
}
pub fn set_name<T: Into<String>>(&mut self, name: T) {
self.name = Some(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 inactivity_limit(mut self, limit: Duration) -> Self {
self.set_inactivity_limit(limit);
self
}
pub fn set_inactivity_limit(&mut self, limit: Duration) {
self.max_inactivity_duration = Some(limit);
}
pub fn accepts_label(&self, label: &L) -> bool {
self.label_filter.accepts(label)
}
fn put_values_into_snapshot(&self, into: &mut Snapshot, descriptive: bool) {
util::put_default_descriptives(self, into, descriptive);
if let Some(d) = self.max_inactivity_duration {
if self.last_update.elapsed() > d {
into.items
.push(("_inactive".to_string(), ItemKind::Boolean(true)));
into.items
.push(("_active".to_string(), ItemKind::Boolean(false)));
return;
} else {
into.items
.push(("_inactive".to_string(), ItemKind::Boolean(false)));
into.items
.push(("_active".to_string(), ItemKind::Boolean(true)));
}
};
self.counter
.as_ref()
.iter()
.for_each(|x| x.put_snapshot(into, descriptive));
self.gauge
.as_ref()
.iter()
.for_each(|x| x.put_snapshot(into, descriptive));
self.meter
.as_ref()
.iter()
.for_each(|x| x.put_snapshot(into, descriptive));
self.histogram
.as_ref()
.iter()
.for_each(|x| x.put_snapshot(into, descriptive));
self.panels
.iter()
.for_each(|p| p.put_snapshot(into, descriptive));
self.snapshooters
.iter()
.for_each(|p| p.put_snapshot(into, descriptive));
self.handlers
.iter()
.for_each(|p| p.put_snapshot(into, descriptive));
}
}
impl<L> PutsSnapshot for Panel<L>
where
L: Eq + Send + 'static,
{
fn put_snapshot(&self, into: &mut Snapshot, descriptive: bool) {
if let Some(ref name) = self.name {
let mut new_level = Snapshot::default();
self.put_values_into_snapshot(&mut new_level, descriptive);
into.items
.push((name.clone(), ItemKind::Snapshot(new_level)));
} else {
self.put_values_into_snapshot(into, descriptive);
}
}
}
impl<L> HandlesObservations for Panel<L>
where
L: Eq + Send + 'static,
{
type Label = L;
fn handle_observation(&mut self, observation: &Observation<Self::Label>) -> usize {
if !self.label_filter.accepts(observation.label()) {
return 0;
}
let mut instruments_updated = 0;
self.counter
.iter_mut()
.for_each(|x| instruments_updated += x.handle_observation(&observation));
self.gauge
.iter_mut()
.for_each(|x| instruments_updated += x.handle_observation(&observation));
self.meter
.iter_mut()
.for_each(|x| instruments_updated += x.handle_observation(&observation));
self.histogram
.iter_mut()
.for_each(|x| instruments_updated += x.handle_observation(&observation));
self.panels
.iter_mut()
.for_each(|x| instruments_updated += x.handle_observation(&observation));
self.handlers
.iter_mut()
.for_each(|x| instruments_updated += x.handle_observation(&observation));
instruments_updated
}
}
impl<L> Descriptive for Panel<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)
}
}