mirror of
https://github.com/mailscope/kumomta.git
synced 2026-09-21 09:05:32 +00:00
kcli top: auto add all histograms
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::top::accumulator::*;
|
||||
use crate::top::{SeriesChartOptions, SeriesFactory, TimeSeries};
|
||||
use crate::top::{Histogram, HistogramFactory, SeriesChartOptions, SeriesFactory, TimeSeries};
|
||||
use kumo_prometheus::parser::Metric;
|
||||
|
||||
pub struct ThreadPoolFactory {}
|
||||
@@ -121,3 +121,39 @@ impl SeriesFactory for HistogramEventAvgFactory {
|
||||
series
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HistogramHistoFactory {}
|
||||
|
||||
impl HistogramFactory for HistogramHistoFactory {
|
||||
fn matches(&self, metric: &Metric) -> Option<String> {
|
||||
if metric.is_histogram() {
|
||||
let h = metric.as_histogram();
|
||||
|
||||
match h.labels.values().next() {
|
||||
Some(l) => {
|
||||
let label = l.as_str();
|
||||
if label == "init" || label == "pre_init" {
|
||||
return None;
|
||||
}
|
||||
Some(format!("{} - {label}", h.name.as_str()))
|
||||
}
|
||||
None => Some(h.name.as_str().to_string()),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn factory(&self, _series_name: &str, metric: &Metric) -> Histogram {
|
||||
let h = metric.as_histogram();
|
||||
match h.labels.iter().next() {
|
||||
Some((key, value)) => Histogram::new_with_label_match(
|
||||
metric.name().to_string(),
|
||||
key.to_string(),
|
||||
value.to_string(),
|
||||
"s",
|
||||
),
|
||||
None => Histogram::new(metric.name().to_string(), "s"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,3 +72,10 @@ impl Histogram {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HistogramFactory {
|
||||
/// Returns the name that should be created for this metric
|
||||
fn matches(&self, metric: &Metric) -> Option<String>;
|
||||
/// Constructs the appropriate histogram for this metric
|
||||
fn factory(&self, series_name: &str, metric: &Metric) -> Histogram;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ impl TopCommand {
|
||||
state.add_factory(HistogramEventFreqFactory {});
|
||||
state.add_factory(HistogramEventAvgFactory {});
|
||||
|
||||
state.add_histogram_factory(HistogramHistoFactory {});
|
||||
|
||||
state.add_series(
|
||||
"message_count",
|
||||
TimeSeries::new(DirectAccumulator::new("message_count")),
|
||||
@@ -144,21 +146,6 @@ impl TopCommand {
|
||||
)),
|
||||
);
|
||||
|
||||
state.add_histogram(
|
||||
"Inbound SMTP Transaction Duration",
|
||||
Histogram::new("smtpsrv_transaction_duration", "s"),
|
||||
);
|
||||
|
||||
state.add_histogram(
|
||||
"Inbound SMTP Data Receive Latency",
|
||||
Histogram::new("smtpsrv_read_data_duration", "s"),
|
||||
);
|
||||
|
||||
state.add_histogram(
|
||||
"Inbound SMTP Data Process Latency",
|
||||
Histogram::new("smtpsrv_process_data_duration", "s"),
|
||||
);
|
||||
|
||||
let mut ticker = tokio::time::interval(Duration::from_secs(self.update_interval));
|
||||
ticker.set_missed_tick_behavior(MissedTickBehavior::Skip);
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ pub struct State {
|
||||
time_series: HashMap<String, TimeSeries>,
|
||||
histograms: HashMap<String, Histogram>,
|
||||
factories: Vec<Box<dyn SeriesFactory + 'static>>,
|
||||
histo_factories: Vec<Box<dyn HistogramFactory + 'static>>,
|
||||
error: String,
|
||||
vert_scroll: ScrollbarState,
|
||||
vert_scroll_position: usize,
|
||||
@@ -96,6 +97,10 @@ impl State {
|
||||
self.factories.push(Box::new(f));
|
||||
}
|
||||
|
||||
pub fn add_histogram_factory(&mut self, f: impl HistogramFactory + 'static) {
|
||||
self.histo_factories.push(Box::new(f));
|
||||
}
|
||||
|
||||
fn accumulate_series(&mut self, metric: &Metric) {
|
||||
let mut new_series = vec![];
|
||||
for factory in &self.factories {
|
||||
@@ -114,6 +119,19 @@ impl State {
|
||||
series.accumulate(metric);
|
||||
}
|
||||
|
||||
let mut new_histo = vec![];
|
||||
for factory in &self.histo_factories {
|
||||
if let Some(name) = factory.matches(metric) {
|
||||
if !self.histograms.contains_key(&name) {
|
||||
let histogram = factory.factory(&name, metric);
|
||||
new_histo.push((name, histogram));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (name, histo) in new_histo {
|
||||
self.add_histogram(name, histo);
|
||||
}
|
||||
|
||||
for histo in self.histograms.values_mut() {
|
||||
histo.accumulate(metric);
|
||||
}
|
||||
@@ -413,8 +431,12 @@ impl State {
|
||||
.vert_scroll_position
|
||||
.min(content_length.saturating_sub(1));
|
||||
|
||||
let mut names: Vec<_> = self.histograms.keys().map(|s| s.to_string()).collect();
|
||||
names.sort();
|
||||
|
||||
let mut y = area.top();
|
||||
for (caption, histo) in self.histograms.iter().skip(vert_scroll_position) {
|
||||
for caption in names.iter().skip(vert_scroll_position) {
|
||||
let histo = self.histograms.get(caption).expect("caption to be valid");
|
||||
let heatmap = HeatMap::new(histo, caption).block(Block::bordered());
|
||||
let height = heatmap.height() + 2 /* borders */;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user