Skip to content

Commit

Permalink
metrics: return histograms for time metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
Keksoj committed Oct 26, 2023
1 parent 55580c6 commit 0e42e87
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 17 deletions.
18 changes: 16 additions & 2 deletions command/src/command.proto
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ message FilteredMetrics {
uint64 time = 3;
Percentiles percentiles = 4;
FilteredTimeSerie time_serie = 5;
FilteredHistogram histogram = 6;
}
}

Expand All @@ -583,7 +584,6 @@ message FilteredTimeSerie {
repeated uint32 last_hour = 3;
}


message Percentiles {
required uint64 samples = 1;
required uint64 p_50 = 2;
Expand All @@ -595,6 +595,20 @@ message Percentiles {
required uint64 p_100 = 8;
}

// a histogram meant to be translated to prometheus
message FilteredHistogram {
required uint64 sum = 1;
required uint64 count = 2;
repeated Bucket buckets = 3;
}

// a prometheus histogram bucket
message Bucket {
required uint64 count = 1;
// upper range of the bucket (le = less or equal)
required uint64 le = 2;
}

message RequestCounts {
map<string, int32> map = 1;
}
}
68 changes: 53 additions & 15 deletions lib/src/metrics/local_drain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ use std::{
use hdrhistogram::Histogram;

use sozu_command::proto::command::{
filtered_metrics, response_content::ContentType, AvailableMetrics, BackendMetrics,
ClusterMetrics, FilteredMetrics, MetricsConfiguration, Percentiles, QueryMetricsOptions,
ResponseContent, WorkerMetrics,
filtered_metrics, response_content::ContentType, AvailableMetrics, BackendMetrics, Bucket,
ClusterMetrics, FilteredHistogram, FilteredMetrics, MetricsConfiguration, Percentiles,
QueryMetricsOptions, ResponseContent, WorkerMetrics,
};

use crate::metrics::{MetricError, MetricValue, Subscriber};

/// This is how the metrics are stored in the local drain
/// metrics as stored in the local drain
#[derive(Debug, Clone)]
pub enum AggregatedMetric {
Gauge(usize),
Expand Down Expand Up @@ -88,6 +88,30 @@ impl AggregatedMetric {
}
}

/// filter "inside" metrics by names, turn them into sendable ones
fn filter_aggregated_metrics(
aggregated: &BTreeMap<String, AggregatedMetric>,
metric_names: &Vec<String>,
) -> BTreeMap<String, FilteredMetrics> {
let mut to_filter = aggregated.clone();
if !metric_names.is_empty() {
to_filter.retain(|key, _| metric_names.contains(key));
}

let mut filtered_metrics = BTreeMap::new();
for (name, metric) in to_filter {
filtered_metrics.insert(name.to_owned(), metric.to_filtered());
// convert time metrics to a histogram format, on top of percentiles
match metric {
AggregatedMetric::Time(ref hist) => {
filtered_metrics.insert(format!("{}_hist", name), filter_histogram(hist));
}
_ => {}
}
}
filtered_metrics
}

pub fn histogram_to_percentiles(hist: &Histogram<u32>) -> Percentiles {
Percentiles {
samples: hist.len(),
Expand All @@ -101,6 +125,30 @@ pub fn histogram_to_percentiles(hist: &Histogram<u32>) -> Percentiles {
}
}

pub fn filter_histogram(hist: &Histogram<u32>) -> FilteredMetrics {
let count = hist.len();
let mean = hist.mean();
let min = hist.min();
let max = hist.max();
let sum = (count as f64 * mean) as u64;
let range = max - min;
let number_of_buckets = 10;
let mut buckets = Vec::new();

for i in 0..number_of_buckets {
let le = min + (i * range) / number_of_buckets;
let count = hist.count_between(min, min + le);
buckets.push(Bucket { le, count });
}
FilteredMetrics {
inner: Some(filtered_metrics::Inner::Histogram(FilteredHistogram {
sum,
count,
buckets,
})),
}
}

#[derive(Copy, Clone, Debug, PartialEq)]
enum MetricKind {
Gauge,
Expand Down Expand Up @@ -306,17 +354,7 @@ impl LocalDrain {
&mut self,
metric_names: &Vec<String>,
) -> BTreeMap<String, FilteredMetrics> {
self.proxy_metrics
.iter()
.filter(|(key, _)| {
if metric_names.is_empty() {
true
} else {
metric_names.contains(key)
}
})
.map(|(key, value)| (key.to_string(), value.to_filtered()))
.collect()
filter_aggregated_metrics(&self.proxy_metrics, metric_names)
}

pub fn dump_cluster_metrics(
Expand Down

0 comments on commit 0e42e87

Please sign in to comment.