You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2025/03/27 02:11:22 UTC
(opendal) branch implement-prom-client updated (d85ff5588 -> 9d57edf0c)
This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a change to branch implement-prom-client
in repository https://gitbox.apache.org/repos/asf/opendal.git
discard d85ff5588 refactor: Migrate PrometheusClientLayer to support IO metrics
omit ff23d9847 refactor(core): Add good default histogram buckets for metrics
add 43bb35111 refactor(core): Add good default histogram buckets for metrics (#5886)
new 9d57edf0c refactor: Migrate PrometheusClientLayer to support IO metrics
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (d85ff5588)
\
N -- N -- N refs/heads/implement-prom-client (9d57edf0c)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
(opendal) 01/01: refactor: Migrate PrometheusClientLayer to support IO metrics
Posted by xu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch implement-prom-client
in repository https://gitbox.apache.org/repos/asf/opendal.git
commit 9d57edf0c6283f23a502216d041df6b5cad01f00
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Thu Mar 27 10:10:08 2025 +0800
refactor: Migrate PrometheusClientLayer to support IO metrics
Signed-off-by: Xuanwo <gi...@xuanwo.io>
---
core/src/layers/prometheus_client.rs | 650 ++++++++++++++++-------------------
1 file changed, 289 insertions(+), 361 deletions(-)
diff --git a/core/src/layers/prometheus_client.rs b/core/src/layers/prometheus_client.rs
index de5c1f4a1..07c03d552 100644
--- a/core/src/layers/prometheus_client.rs
+++ b/core/src/layers/prometheus_client.rs
@@ -16,7 +16,6 @@
// under the License.
use std::fmt;
-use std::sync::Arc;
use std::time::Duration;
use prometheus_client::encoding::EncodeLabel;
@@ -25,9 +24,11 @@ use prometheus_client::encoding::LabelSetEncoder;
use prometheus_client::metrics::counter::Counter;
use prometheus_client::metrics::family::Family;
use prometheus_client::metrics::family::MetricConstructor;
-use prometheus_client::metrics::histogram::exponential_buckets;
+use prometheus_client::metrics::gauge::Gauge;
use prometheus_client::metrics::histogram::Histogram;
+use prometheus_client::registry::Metric;
use prometheus_client::registry::Registry;
+use prometheus_client::registry::Unit;
use crate::layers::observe;
use crate::raw::*;
@@ -85,58 +86,8 @@ pub struct PrometheusClientLayer {
impl PrometheusClientLayer {
/// Create a [`PrometheusClientLayerBuilder`] to set the configuration of metrics.
- ///
- /// # Default Configuration
- ///
- /// - `operation_duration_seconds_buckets`: `exponential_buckets(0.01, 2.0, 16)`
- /// - `operation_bytes_buckets`: `exponential_buckets(1.0, 2.0, 16)`
- /// - `path_label`: `0`
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # use log::debug;
- /// # use opendal::layers::PrometheusClientLayer;
- /// # use opendal::services;
- /// # use opendal::Operator;
- /// # use opendal::Result;
- ///
- /// # #[tokio::main]
- /// # async fn main() -> Result<()> {
- /// // Pick a builder and configure it.
- /// let builder = services::Memory::default();
- /// let mut registry = prometheus_client::registry::Registry::default();
- ///
- /// let duration_seconds_buckets =
- /// prometheus_client::metrics::histogram::exponential_buckets(0.01, 2.0, 16).collect();
- /// let bytes_buckets =
- /// prometheus_client::metrics::histogram::exponential_buckets(1.0, 2.0, 16).collect();
- /// let op = Operator::new(builder)?
- /// .layer(
- /// PrometheusClientLayer::builder()
- /// .operation_duration_seconds_buckets(duration_seconds_buckets)
- /// .operation_bytes_buckets(bytes_buckets)
- /// .path_label(0)
- /// .register(&mut registry),
- /// )
- /// .finish();
- /// debug!("operator: {op:?}");
- ///
- /// Ok(())
- /// # }
- /// ```
pub fn builder() -> PrometheusClientLayerBuilder {
- let operation_duration_seconds_buckets = exponential_buckets(0.01, 2.0, 16).collect();
- let operation_bytes_buckets = exponential_buckets(1.0, 2.0, 16).collect();
- let http_request_duration_seconds_buckets = exponential_buckets(0.01, 2.0, 16).collect();
- let http_request_bytes_buckets = exponential_buckets(1.0, 2.0, 16).collect();
- PrometheusClientLayerBuilder::new(
- operation_duration_seconds_buckets,
- operation_bytes_buckets,
- http_request_duration_seconds_buckets,
- http_request_bytes_buckets,
- 0,
- )
+ PrometheusClientLayerBuilder::default()
}
}
@@ -150,217 +101,73 @@ impl<A: Access> Layer<A> for PrometheusClientLayer {
/// [`PrometheusClientLayerBuilder`] is a config builder to build a [`PrometheusClientLayer`].
pub struct PrometheusClientLayerBuilder {
- operation_duration_seconds_buckets: Vec<f64>,
- operation_bytes_buckets: Vec<f64>,
- http_request_duration_seconds_buckets: Vec<f64>,
- http_request_bytes_buckets: Vec<f64>,
- path_label_level: usize,
+ bytes_buckets: Vec<f64>,
+ bytes_rate_buckets: Vec<f64>,
+ entries_buckets: Vec<f64>,
+ entries_rate_buckets: Vec<f64>,
+ duration_seconds_buckets: Vec<f64>,
+ ttfb_buckets: Vec<f64>,
}
-impl PrometheusClientLayerBuilder {
- fn new(
- operation_duration_seconds_buckets: Vec<f64>,
- operation_bytes_buckets: Vec<f64>,
- http_request_duration_seconds_buckets: Vec<f64>,
- http_request_bytes_buckets: Vec<f64>,
- path_label_level: usize,
- ) -> Self {
+impl Default for PrometheusClientLayerBuilder {
+ fn default() -> Self {
Self {
- operation_duration_seconds_buckets,
- operation_bytes_buckets,
- http_request_duration_seconds_buckets,
- http_request_bytes_buckets,
- path_label_level,
+ bytes_buckets: observe::DEFAULT_BYTES_BUCKETS.to_vec(),
+ bytes_rate_buckets: observe::DEFAULT_BYTES_RATE_BUCKETS.to_vec(),
+ entries_buckets: observe::DEFAULT_ENTRIES_BUCKETS.to_vec(),
+ entries_rate_buckets: observe::DEFAULT_ENTRIES_RATE_BUCKETS.to_vec(),
+ duration_seconds_buckets: observe::DEFAULT_DURATION_SECONDS_BUCKETS.to_vec(),
+ ttfb_buckets: observe::DEFAULT_TTFB_BUCKETS.to_vec(),
}
}
+}
- /// Set buckets for `operation_duration_seconds` histogram.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # use log::debug;
- /// # use opendal::layers::PrometheusClientLayer;
- /// # use opendal::services;
- /// # use opendal::Operator;
- /// # use opendal::Result;
- ///
- /// # #[tokio::main]
- /// # async fn main() -> Result<()> {
- /// // Pick a builder and configure it.
- /// let builder = services::Memory::default();
- /// let mut registry = prometheus_client::registry::Registry::default();
- ///
- /// let buckets =
- /// prometheus_client::metrics::histogram::exponential_buckets(0.01, 2.0, 16).collect();
- /// let op = Operator::new(builder)?
- /// .layer(
- /// PrometheusClientLayer::builder()
- /// .operation_duration_seconds_buckets(buckets)
- /// .register(&mut registry),
- /// )
- /// .finish();
- /// debug!("operator: {op:?}");
- ///
- /// Ok(())
- /// # }
- /// ```
- pub fn operation_duration_seconds_buckets(mut self, buckets: Vec<f64>) -> Self {
+impl PrometheusClientLayerBuilder {
+ /// Set buckets for bytes related histogram like `operation_bytes`.
+ pub fn bytes_buckets(mut self, buckets: Vec<f64>) -> Self {
if !buckets.is_empty() {
- self.operation_duration_seconds_buckets = buckets;
+ self.bytes_buckets = buckets;
}
self
}
- /// Set buckets for `operation_bytes` histogram.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # use log::debug;
- /// # use opendal::layers::PrometheusClientLayer;
- /// # use opendal::services;
- /// # use opendal::Operator;
- /// # use opendal::Result;
- ///
- /// # #[tokio::main]
- /// # async fn main() -> Result<()> {
- /// // Pick a builder and configure it.
- /// let builder = services::Memory::default();
- /// let mut registry = prometheus_client::registry::Registry::default();
- ///
- /// let buckets =
- /// prometheus_client::metrics::histogram::exponential_buckets(1.0, 2.0, 16).collect();
- /// let op = Operator::new(builder)?
- /// .layer(
- /// PrometheusClientLayer::builder()
- /// .operation_bytes_buckets(buckets)
- /// .register(&mut registry),
- /// )
- /// .finish();
- /// debug!("operator: {op:?}");
- ///
- /// Ok(())
- /// # }
- /// ```
- pub fn operation_bytes_buckets(mut self, buckets: Vec<f64>) -> Self {
+ /// Set buckets for bytes rate related histogram like `operation_bytes_rate`.
+ pub fn bytes_rate_buckets(mut self, buckets: Vec<f64>) -> Self {
if !buckets.is_empty() {
- self.operation_bytes_buckets = buckets;
+ self.bytes_rate_buckets = buckets;
}
self
}
- /// Set buckets for `http_request_duration_seconds` histogram.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # use log::debug;
- /// # use opendal::layers::PrometheusClientLayer;
- /// # use opendal::services;
- /// # use opendal::Operator;
- /// # use opendal::Result;
- ///
- /// # #[tokio::main]
- /// # async fn main() -> Result<()> {
- /// // Pick a builder and configure it.
- /// let builder = services::Memory::default();
- /// let mut registry = prometheus_client::registry::Registry::default();
- ///
- /// let buckets =
- /// prometheus_client::metrics::histogram::exponential_buckets(0.01, 2.0, 16).collect();
- /// let op = Operator::new(builder)?
- /// .layer(
- /// PrometheusClientLayer::builder()
- /// .http_request_duration_seconds_buckets(buckets)
- /// .register(&mut registry),
- /// )
- /// .finish();
- /// debug!("operator: {op:?}");
- ///
- /// Ok(())
- /// # }
- /// ```
- pub fn http_request_duration_seconds_buckets(mut self, buckets: Vec<f64>) -> Self {
+ /// Set buckets for entries related histogram like `operation_entries`.
+ pub fn entries_buckets(mut self, buckets: Vec<f64>) -> Self {
if !buckets.is_empty() {
- self.http_request_duration_seconds_buckets = buckets;
+ self.entries_buckets = buckets;
}
self
}
- /// Set buckets for `operation_bytes` histogram.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # use log::debug;
- /// # use opendal::layers::PrometheusClientLayer;
- /// # use opendal::services;
- /// # use opendal::Operator;
- /// # use opendal::Result;
- ///
- /// # #[tokio::main]
- /// # async fn main() -> Result<()> {
- /// // Pick a builder and configure it.
- /// let builder = services::Memory::default();
- /// let mut registry = prometheus_client::registry::Registry::default();
- ///
- /// let buckets =
- /// prometheus_client::metrics::histogram::exponential_buckets(1.0, 2.0, 16).collect();
- /// let op = Operator::new(builder)?
- /// .layer(
- /// PrometheusClientLayer::builder()
- /// .http_request_bytes_buckets(buckets)
- /// .register(&mut registry),
- /// )
- /// .finish();
- /// debug!("operator: {op:?}");
- ///
- /// Ok(())
- /// # }
- /// ```
- pub fn http_request_bytes_buckets(mut self, buckets: Vec<f64>) -> Self {
+ /// Set buckets for entries rate related histogram like `operation_entries_rate`.
+ pub fn entries_rate_buckets(mut self, buckets: Vec<f64>) -> Self {
if !buckets.is_empty() {
- self.http_request_bytes_buckets = buckets;
+ self.entries_rate_buckets = buckets;
}
self
}
- /// Set the level of path label.
- ///
- /// - level = 0: we will ignore the path label.
- /// - level > 0: the path label will be the path split by "/" and get the last n level,
- /// if n=1 and input path is "abc/def/ghi", and then we will get "abc/" as the path label.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # use log::debug;
- /// # use opendal::layers::PrometheusClientLayer;
- /// # use opendal::services;
- /// # use opendal::Operator;
- /// # use opendal::Result;
- ///
- /// # #[tokio::main]
- /// # async fn main() -> Result<()> {
- /// // Pick a builder and configure it.
- /// let builder = services::Memory::default();
- /// let mut registry = prometheus_client::registry::Registry::default();
- ///
- /// let op = Operator::new(builder)?
- /// .layer(
- /// PrometheusClientLayer::builder()
- /// .path_label(1)
- /// .register(&mut registry),
- /// )
- /// .finish();
- /// debug!("operator: {op:?}");
- ///
- /// Ok(())
- /// # }
- /// ```
- pub fn path_label(mut self, level: usize) -> Self {
- self.path_label_level = level;
+ /// Set buckets for duration seconds related histogram like `operation_duration_seconds`.
+ pub fn duration_seconds_buckets(mut self, buckets: Vec<f64>) -> Self {
+ if !buckets.is_empty() {
+ self.duration_seconds_buckets = buckets;
+ }
+ self
+ }
+
+ /// Set buckets for ttfb related histogram like `operation_ttfb_seconds`.
+ pub fn ttfb_buckets(mut self, buckets: Vec<f64>) -> Self {
+ if !buckets.is_empty() {
+ self.ttfb_buckets = buckets;
+ }
self
}
@@ -390,60 +197,168 @@ impl PrometheusClientLayerBuilder {
/// # }
/// ```
pub fn register(self, registry: &mut Registry) -> PrometheusClientLayer {
- let operation_duration_seconds =
+ let operation_bytes =
Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
- buckets: self.operation_duration_seconds_buckets,
+ buckets: self.bytes_buckets.clone(),
});
- let operation_bytes =
+ let operation_bytes_rate =
+ Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
+ buckets: self.bytes_rate_buckets.clone(),
+ });
+ let operation_entries =
Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
- buckets: self.operation_bytes_buckets,
+ buckets: self.entries_buckets.clone(),
+ });
+ let operation_entries_rate =
+ Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
+ buckets: self.entries_rate_buckets.clone(),
+ });
+ let operation_duration_seconds =
+ Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
+ buckets: self.duration_seconds_buckets.clone(),
});
let operation_errors_total = Family::<OperationLabels, Counter>::default();
- let http_request_duration_seconds =
+ let operation_executing = Family::<OperationLabels, Gauge>::default();
+ let operation_ttfb_seconds =
Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
- buckets: self.http_request_duration_seconds_buckets,
+ buckets: self.ttfb_buckets.clone(),
});
+
+ let http_executing = Family::<OperationLabels, Gauge>::default();
let http_request_bytes =
Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
- buckets: self.http_request_bytes_buckets,
+ buckets: self.bytes_buckets.clone(),
+ });
+ let http_request_bytes_rate =
+ Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
+ buckets: self.bytes_rate_buckets.clone(),
+ });
+ let http_request_duration_seconds =
+ Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
+ buckets: self.duration_seconds_buckets.clone(),
+ });
+ let http_response_bytes =
+ Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
+ buckets: self.bytes_buckets.clone(),
+ });
+ let http_response_bytes_rate =
+ Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
+ buckets: self.bytes_rate_buckets.clone(),
});
+ let http_response_duration_seconds =
+ Family::<OperationLabels, Histogram, _>::new_with_constructor(HistogramConstructor {
+ buckets: self.duration_seconds_buckets.clone(),
+ });
+ let http_connection_errors_total = Family::<OperationLabels, Counter>::default();
+ let http_status_errors_total = Family::<OperationLabels, Counter>::default();
- registry.register(
- observe::METRIC_OPERATION_DURATION_SECONDS.name(),
- observe::METRIC_OPERATION_DURATION_SECONDS.help(),
- operation_duration_seconds.clone(),
- );
- registry.register(
- observe::METRIC_OPERATION_BYTES.name(),
- observe::METRIC_OPERATION_BYTES.help(),
+ register_metric(
+ registry,
operation_bytes.clone(),
+ observe::MetricValue::OperationBytes(0),
);
- // `prometheus-client` will automatically add `_total` suffix into the name of counter
- // metrics, so we can't use `METRIC_OPERATION_ERRORS_TOTAL.name()` here.
- registry.register(
- "opendal_operation_errors",
- observe::METRIC_OPERATION_ERRORS_TOTAL.help(),
- operation_errors_total.clone(),
+ register_metric(
+ registry,
+ operation_bytes_rate.clone(),
+ observe::MetricValue::OperationBytesRate(0.0),
+ );
+ register_metric(
+ registry,
+ operation_entries.clone(),
+ observe::MetricValue::OperationEntries(0),
);
- registry.register(
- observe::METRIC_HTTP_REQUEST_DURATION_SECONDS.name(),
- observe::METRIC_HTTP_REQUEST_DURATION_SECONDS.help(),
+ register_metric(
+ registry,
+ operation_entries_rate.clone(),
+ observe::MetricValue::OperationEntriesRate(0.0),
+ );
+ register_metric(
+ registry,
operation_duration_seconds.clone(),
+ observe::MetricValue::OperationDurationSeconds(Duration::default()),
);
- registry.register(
- observe::METRIC_HTTP_REQUEST_BYTES.name(),
- observe::METRIC_HTTP_REQUEST_BYTES.help(),
- operation_bytes.clone(),
+ register_metric(
+ registry,
+ operation_errors_total.clone(),
+ observe::MetricValue::OperationErrorsTotal,
+ );
+ register_metric(
+ registry,
+ operation_executing.clone(),
+ observe::MetricValue::OperationExecuting(0),
+ );
+ register_metric(
+ registry,
+ operation_ttfb_seconds.clone(),
+ observe::MetricValue::OperationTtfbSeconds(Duration::default()),
+ );
+
+ register_metric(
+ registry,
+ http_executing.clone(),
+ observe::MetricValue::HttpExecuting(0),
+ );
+ register_metric(
+ registry,
+ http_request_bytes.clone(),
+ observe::MetricValue::HttpRequestBytes(0),
+ );
+ register_metric(
+ registry,
+ http_request_bytes_rate.clone(),
+ observe::MetricValue::HttpRequestBytesRate(0.0),
+ );
+ register_metric(
+ registry,
+ http_request_duration_seconds.clone(),
+ observe::MetricValue::HttpRequestDurationSeconds(Duration::default()),
+ );
+ register_metric(
+ registry,
+ http_response_bytes.clone(),
+ observe::MetricValue::HttpResponseBytes(0),
+ );
+ register_metric(
+ registry,
+ http_response_bytes_rate.clone(),
+ observe::MetricValue::HttpResponseBytesRate(0.0),
+ );
+ register_metric(
+ registry,
+ http_response_duration_seconds.clone(),
+ observe::MetricValue::HttpResponseDurationSeconds(Duration::default()),
+ );
+ register_metric(
+ registry,
+ http_connection_errors_total.clone(),
+ observe::MetricValue::HttpConnectionErrorsTotal,
+ );
+ register_metric(
+ registry,
+ http_status_errors_total.clone(),
+ observe::MetricValue::HttpStatusErrorsTotal,
);
PrometheusClientLayer {
interceptor: PrometheusClientInterceptor {
- operation_duration_seconds,
operation_bytes,
+ operation_bytes_rate,
+ operation_entries,
+ operation_entries_rate,
+ operation_duration_seconds,
operation_errors_total,
- http_request_duration_seconds,
+ operation_executing,
+ operation_ttfb_seconds,
+
+ http_executing,
http_request_bytes,
- path_label_level: self.path_label_level,
+ http_request_bytes_rate,
+ http_request_duration_seconds,
+ http_response_bytes,
+ http_response_bytes_rate,
+ http_response_duration_seconds,
+ http_connection_errors_total,
+ http_status_errors_total,
},
}
}
@@ -462,114 +377,127 @@ impl MetricConstructor<Histogram> for HistogramConstructor {
#[derive(Clone, Debug)]
pub struct PrometheusClientInterceptor {
- operation_duration_seconds: Family<OperationLabels, Histogram, HistogramConstructor>,
operation_bytes: Family<OperationLabels, Histogram, HistogramConstructor>,
+ operation_bytes_rate: Family<OperationLabels, Histogram, HistogramConstructor>,
+ operation_entries: Family<OperationLabels, Histogram, HistogramConstructor>,
+ operation_entries_rate: Family<OperationLabels, Histogram, HistogramConstructor>,
+ operation_duration_seconds: Family<OperationLabels, Histogram, HistogramConstructor>,
operation_errors_total: Family<OperationLabels, Counter>,
- http_request_duration_seconds: Family<OperationLabels, Histogram, HistogramConstructor>,
+ operation_executing: Family<OperationLabels, Gauge>,
+ operation_ttfb_seconds: Family<OperationLabels, Histogram, HistogramConstructor>,
+
+ http_executing: Family<OperationLabels, Gauge>,
http_request_bytes: Family<OperationLabels, Histogram, HistogramConstructor>,
- path_label_level: usize,
+ http_request_bytes_rate: Family<OperationLabels, Histogram, HistogramConstructor>,
+ http_request_duration_seconds: Family<OperationLabels, Histogram, HistogramConstructor>,
+ http_response_bytes: Family<OperationLabels, Histogram, HistogramConstructor>,
+ http_response_bytes_rate: Family<OperationLabels, Histogram, HistogramConstructor>,
+ http_response_duration_seconds: Family<OperationLabels, Histogram, HistogramConstructor>,
+ http_connection_errors_total: Family<OperationLabels, Counter>,
+ http_status_errors_total: Family<OperationLabels, Counter>,
}
impl observe::MetricsIntercept for PrometheusClientInterceptor {
- fn observe_operation_duration_seconds(
- &self,
- info: Arc<AccessorInfo>,
- path: &str,
- op: Operation,
- duration: Duration,
- ) {
- self.operation_duration_seconds
- .get_or_create(&OperationLabels {
- info,
- operation: op,
- path: observe::path_label_value(path, self.path_label_level).map(Into::into),
- error: None,
- })
- .observe(duration.as_secs_f64())
- }
-
- fn observe_operation_bytes(
- &self,
- info: Arc<AccessorInfo>,
- path: &str,
- op: Operation,
- bytes: usize,
- ) {
- self.operation_bytes
- .get_or_create(&OperationLabels {
- info,
- operation: op,
- path: observe::path_label_value(path, self.path_label_level).map(Into::into),
- error: None,
- })
- .observe(bytes as f64)
- }
-
- fn observe_operation_errors_total(
- &self,
- info: Arc<AccessorInfo>,
- path: &str,
- op: Operation,
- error: ErrorKind,
- ) {
- self.operation_errors_total
- .get_or_create(&OperationLabels {
- info,
- operation: op,
- path: observe::path_label_value(path, self.path_label_level).map(Into::into),
- error: Some(error.into_static()),
- })
- .inc();
- }
-
- fn observe_http_request_duration_seconds(
- &self,
- info: Arc<AccessorInfo>,
- op: Operation,
- duration: Duration,
- ) {
- self.http_request_duration_seconds
- .get_or_create(&OperationLabels {
- info,
- operation: op,
- path: None,
- error: None,
- })
- .observe(duration.as_secs_f64())
- }
+ fn observe(&self, labels: observe::MetricLabels, value: observe::MetricValue) {
+ let labels = OperationLabels(labels);
+ match value {
+ observe::MetricValue::OperationBytes(v) => self
+ .operation_bytes
+ .get_or_create(&labels)
+ .observe(v as f64),
+ observe::MetricValue::OperationBytesRate(v) => {
+ self.operation_bytes_rate.get_or_create(&labels).observe(v)
+ }
+ observe::MetricValue::OperationEntries(v) => self
+ .operation_entries
+ .get_or_create(&labels)
+ .observe(v as f64),
+ observe::MetricValue::OperationEntriesRate(v) => self
+ .operation_entries_rate
+ .get_or_create(&labels)
+ .observe(v),
+ observe::MetricValue::OperationDurationSeconds(v) => self
+ .operation_duration_seconds
+ .get_or_create(&labels)
+ .observe(v.as_secs_f64()),
+ observe::MetricValue::OperationErrorsTotal => {
+ self.operation_errors_total.get_or_create(&labels).inc();
+ }
+ observe::MetricValue::OperationExecuting(v) => {
+ self.operation_executing
+ .get_or_create(&labels)
+ .inc_by(v as i64);
+ }
+ observe::MetricValue::OperationTtfbSeconds(v) => self
+ .operation_ttfb_seconds
+ .get_or_create(&labels)
+ .observe(v.as_secs_f64()),
- fn observe_http_request_bytes(&self, info: Arc<AccessorInfo>, op: Operation, bytes: usize) {
- self.http_request_bytes
- .get_or_create(&OperationLabels {
- info,
- operation: op,
- path: None,
- error: None,
- })
- .observe(bytes as f64)
+ observe::MetricValue::HttpExecuting(v) => {
+ self.http_executing.get_or_create(&labels).inc_by(v as i64);
+ }
+ observe::MetricValue::HttpRequestBytes(v) => self
+ .http_request_bytes
+ .get_or_create(&labels)
+ .observe(v as f64),
+ observe::MetricValue::HttpRequestBytesRate(v) => self
+ .http_request_bytes_rate
+ .get_or_create(&labels)
+ .observe(v),
+ observe::MetricValue::HttpRequestDurationSeconds(v) => self
+ .http_request_duration_seconds
+ .get_or_create(&labels)
+ .observe(v.as_secs_f64()),
+ observe::MetricValue::HttpResponseBytes(v) => self
+ .http_response_bytes
+ .get_or_create(&labels)
+ .observe(v as f64),
+ observe::MetricValue::HttpResponseBytesRate(v) => self
+ .http_response_bytes_rate
+ .get_or_create(&labels)
+ .observe(v),
+ observe::MetricValue::HttpResponseDurationSeconds(v) => self
+ .http_response_duration_seconds
+ .get_or_create(&labels)
+ .observe(v.as_secs_f64()),
+ observe::MetricValue::HttpConnectionErrorsTotal => {
+ self.http_connection_errors_total
+ .get_or_create(&labels)
+ .inc();
+ }
+ observe::MetricValue::HttpStatusErrorsTotal => {
+ self.http_status_errors_total.get_or_create(&labels).inc();
+ }
+ };
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-struct OperationLabels {
- info: Arc<AccessorInfo>,
- operation: Operation,
- path: Option<String>,
- error: Option<&'static str>,
-}
+struct OperationLabels(observe::MetricLabels);
impl EncodeLabelSet for OperationLabels {
fn encode(&self, mut encoder: LabelSetEncoder) -> Result<(), fmt::Error> {
- (observe::LABEL_SCHEME, self.info.scheme().into_static()).encode(encoder.encode_label())?;
- (observe::LABEL_NAMESPACE, self.info.name().as_ref()).encode(encoder.encode_label())?;
- (observe::LABEL_ROOT, self.info.root().as_ref()).encode(encoder.encode_label())?;
- (observe::LABEL_OPERATION, self.operation.into_static()).encode(encoder.encode_label())?;
- if let Some(path) = &self.path {
- (observe::LABEL_PATH, path.as_str()).encode(encoder.encode_label())?;
+ (observe::LABEL_SCHEME, self.0.scheme.into_static()).encode(encoder.encode_label())?;
+ (observe::LABEL_NAMESPACE, self.0.namespace.as_ref()).encode(encoder.encode_label())?;
+ (observe::LABEL_ROOT, self.0.root.as_ref()).encode(encoder.encode_label())?;
+ (observe::LABEL_OPERATION, self.0.operation).encode(encoder.encode_label())?;
+
+ if let Some(error) = &self.0.error {
+ (observe::LABEL_ERROR, error.into_static()).encode(encoder.encode_label())?;
}
- if let Some(error) = self.error {
- (observe::LABEL_ERROR, error).encode(encoder.encode_label())?;
+ if let Some(code) = &self.0.status_code {
+ (observe::LABEL_STATUS_CODE, code.as_str()).encode(encoder.encode_label())?;
}
Ok(())
}
}
+
+fn register_metric(registry: &mut Registry, metric: impl Metric, value: observe::MetricValue) {
+ let ((name, unit), help) = (value.name_with_unit(), value.help());
+
+ if let Some(unit) = unit {
+ registry.register_with_unit(name, help, Unit::Other(unit.to_string()), metric);
+ } else {
+ registry.register(name, help, metric);
+ }
+}