#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(
feature = "serialization",
derive(serde::Serialize, serde::Deserialize)
)]
pub enum MetricKind {
Counter {
value: i64,
},
Gauge {
value: u64,
max: u64,
},
Status {
up: bool,
},
Text {
text: String,
},
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(
feature = "serialization",
derive(serde::Serialize, serde::Deserialize)
)]
pub struct MetricWidget {
pub(super) label: String,
pub(super) kind: MetricKind,
pub(super) history: Vec<u64>,
pub(super) max_history: usize,
}
impl MetricWidget {
pub fn counter(label: impl Into<String>, value: i64) -> Self {
Self {
label: label.into(),
kind: MetricKind::Counter { value },
history: Vec::new(),
max_history: 20,
}
}
pub fn gauge(label: impl Into<String>, value: u64, max: u64) -> Self {
Self {
label: label.into(),
kind: MetricKind::Gauge { value, max },
history: Vec::new(),
max_history: 20,
}
}
pub fn status(label: impl Into<String>, up: bool) -> Self {
Self {
label: label.into(),
kind: MetricKind::Status { up },
history: Vec::new(),
max_history: 0,
}
}
pub fn text(label: impl Into<String>, text: impl Into<String>) -> Self {
Self {
label: label.into(),
kind: MetricKind::Text { text: text.into() },
history: Vec::new(),
max_history: 0,
}
}
pub fn with_max_history(mut self, max: usize) -> Self {
self.max_history = max;
self
}
pub fn label(&self) -> &str {
&self.label
}
pub fn kind(&self) -> &MetricKind {
&self.kind
}
pub fn history(&self) -> &[u64] {
&self.history
}
pub fn display_value(&self) -> String {
match &self.kind {
MetricKind::Counter { value } => value.to_string(),
MetricKind::Gauge { value, max } => format!("{}/{}", value, max),
MetricKind::Status { up } => {
if *up {
"UP".to_string()
} else {
"DOWN".to_string()
}
}
MetricKind::Text { text } => text.clone(),
}
}
pub fn set_counter_value(&mut self, value: i64) {
if let MetricKind::Counter { value: ref mut v } = self.kind {
*v = value;
if self.max_history > 0 {
self.history.push(value.unsigned_abs());
while self.history.len() > self.max_history {
self.history.remove(0);
}
}
}
}
pub fn set_gauge_value(&mut self, value: u64) {
if let MetricKind::Gauge {
value: ref mut v,
max,
} = self.kind
{
*v = value.min(max);
if self.max_history > 0 {
self.history.push(value);
while self.history.len() > self.max_history {
self.history.remove(0);
}
}
}
}
pub fn set_status(&mut self, up: bool) {
if let MetricKind::Status { up: ref mut u } = self.kind {
*u = up;
}
}
pub fn set_text(&mut self, text: impl Into<String>) {
if let MetricKind::Text { text: ref mut t } = self.kind {
*t = text.into();
}
}
pub fn increment(&mut self, amount: i64) {
if let MetricKind::Counter { ref mut value } = self.kind {
*value += amount;
if self.max_history > 0 {
self.history.push(value.unsigned_abs());
while self.history.len() > self.max_history {
self.history.remove(0);
}
}
}
}
pub fn gauge_percentage(&self) -> Option<f64> {
match &self.kind {
MetricKind::Gauge { value, max } if *max > 0 => Some(*value as f64 / *max as f64),
_ => None,
}
}
}