mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +08:00
build(deps): bump opentelemetry crates to 0.27 (#6774)
This commit is contained in:
@ -3,20 +3,6 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use ::config::ConfigError;
|
||||
use opentelemetry::{
|
||||
global, runtime,
|
||||
sdk::{
|
||||
export::metrics::aggregation::cumulative_temporality_selector,
|
||||
metrics::{controllers::BasicController, selectors::simple},
|
||||
propagation::TraceContextPropagator,
|
||||
trace,
|
||||
trace::BatchConfig,
|
||||
Resource,
|
||||
},
|
||||
trace::{TraceContextExt, TraceState},
|
||||
KeyValue,
|
||||
};
|
||||
use opentelemetry_otlp::{TonicExporterBuilder, WithExportConfig};
|
||||
use serde_json::ser::{CompactFormatter, PrettyFormatter};
|
||||
use tracing_appender::non_blocking::WorkerGuard;
|
||||
use tracing_subscriber::{fmt, prelude::*, util::SubscriberInitExt, EnvFilter, Layer};
|
||||
@ -27,7 +13,6 @@ use crate::{config, FormattingLayer, StorageSubscription};
|
||||
#[derive(Debug)]
|
||||
pub struct TelemetryGuard {
|
||||
_log_guards: Vec<WorkerGuard>,
|
||||
_metrics_controller: Option<BasicController>,
|
||||
}
|
||||
|
||||
/// Setup logging sub-system specifying the logging configuration, service (binary) name, and a
|
||||
@ -47,10 +32,9 @@ pub fn setup(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let _metrics_controller = if config.telemetry.metrics_enabled {
|
||||
|
||||
if config.telemetry.metrics_enabled {
|
||||
setup_metrics_pipeline(&config.telemetry)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Setup file logging
|
||||
@ -132,21 +116,23 @@ pub fn setup(
|
||||
// dropped
|
||||
Ok(TelemetryGuard {
|
||||
_log_guards: guards,
|
||||
_metrics_controller,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_opentelemetry_exporter(config: &config::LogTelemetry) -> TonicExporterBuilder {
|
||||
let mut exporter_builder = opentelemetry_otlp::new_exporter().tonic();
|
||||
fn get_opentelemetry_exporter_config(
|
||||
config: &config::LogTelemetry,
|
||||
) -> opentelemetry_otlp::ExportConfig {
|
||||
let mut exporter_config = opentelemetry_otlp::ExportConfig {
|
||||
protocol: opentelemetry_otlp::Protocol::Grpc,
|
||||
endpoint: config.otel_exporter_otlp_endpoint.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
if let Some(ref endpoint) = config.otel_exporter_otlp_endpoint {
|
||||
exporter_builder = exporter_builder.with_endpoint(endpoint);
|
||||
}
|
||||
if let Some(timeout) = config.otel_exporter_otlp_timeout {
|
||||
exporter_builder = exporter_builder.with_timeout(Duration::from_millis(timeout));
|
||||
exporter_config.timeout = Duration::from_millis(timeout);
|
||||
}
|
||||
|
||||
exporter_builder
|
||||
exporter_config
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -192,39 +178,41 @@ impl TraceAssertion {
|
||||
|
||||
/// Conditional Sampler for providing control on url based tracing
|
||||
#[derive(Clone, Debug)]
|
||||
struct ConditionalSampler<T: trace::ShouldSample + Clone + 'static>(TraceAssertion, T);
|
||||
struct ConditionalSampler<T: opentelemetry_sdk::trace::ShouldSample + Clone + 'static>(
|
||||
TraceAssertion,
|
||||
T,
|
||||
);
|
||||
|
||||
impl<T: trace::ShouldSample + Clone + 'static> trace::ShouldSample for ConditionalSampler<T> {
|
||||
impl<T: opentelemetry_sdk::trace::ShouldSample + Clone + 'static>
|
||||
opentelemetry_sdk::trace::ShouldSample for ConditionalSampler<T>
|
||||
{
|
||||
fn should_sample(
|
||||
&self,
|
||||
parent_context: Option<&opentelemetry::Context>,
|
||||
trace_id: opentelemetry::trace::TraceId,
|
||||
name: &str,
|
||||
span_kind: &opentelemetry::trace::SpanKind,
|
||||
attributes: &opentelemetry::trace::OrderMap<opentelemetry::Key, opentelemetry::Value>,
|
||||
attributes: &[opentelemetry::KeyValue],
|
||||
links: &[opentelemetry::trace::Link],
|
||||
instrumentation_library: &opentelemetry::InstrumentationLibrary,
|
||||
) -> opentelemetry::trace::SamplingResult {
|
||||
use opentelemetry::trace::TraceContextExt;
|
||||
|
||||
match attributes
|
||||
.get(&opentelemetry::Key::new("http.route"))
|
||||
.iter()
|
||||
.find(|&kv| kv.key == opentelemetry::Key::new("http.route"))
|
||||
.map_or(self.0.default, |inner| {
|
||||
self.0.should_trace_url(&inner.as_str())
|
||||
self.0.should_trace_url(&inner.value.as_str())
|
||||
}) {
|
||||
true => self.1.should_sample(
|
||||
parent_context,
|
||||
trace_id,
|
||||
name,
|
||||
span_kind,
|
||||
attributes,
|
||||
links,
|
||||
instrumentation_library,
|
||||
),
|
||||
true => {
|
||||
self.1
|
||||
.should_sample(parent_context, trace_id, name, span_kind, attributes, links)
|
||||
}
|
||||
false => opentelemetry::trace::SamplingResult {
|
||||
decision: opentelemetry::trace::SamplingDecision::Drop,
|
||||
attributes: Vec::new(),
|
||||
trace_state: match parent_context {
|
||||
Some(ctx) => ctx.span().span_context().trace_state().clone(),
|
||||
None => TraceState::default(),
|
||||
None => opentelemetry::trace::TraceState::default(),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -234,95 +222,117 @@ impl<T: trace::ShouldSample + Clone + 'static> trace::ShouldSample for Condition
|
||||
fn setup_tracing_pipeline(
|
||||
config: &config::LogTelemetry,
|
||||
service_name: &str,
|
||||
) -> Option<tracing_opentelemetry::OpenTelemetryLayer<tracing_subscriber::Registry, trace::Tracer>>
|
||||
{
|
||||
global::set_text_map_propagator(TraceContextPropagator::new());
|
||||
) -> Option<
|
||||
tracing_opentelemetry::OpenTelemetryLayer<
|
||||
tracing_subscriber::Registry,
|
||||
opentelemetry_sdk::trace::Tracer,
|
||||
>,
|
||||
> {
|
||||
use opentelemetry::trace::TracerProvider;
|
||||
use opentelemetry_otlp::WithExportConfig;
|
||||
use opentelemetry_sdk::trace;
|
||||
|
||||
let mut trace_config = trace::config()
|
||||
opentelemetry::global::set_text_map_propagator(
|
||||
opentelemetry_sdk::propagation::TraceContextPropagator::new(),
|
||||
);
|
||||
|
||||
// Set the export interval to 1 second
|
||||
let batch_config = trace::BatchConfigBuilder::default()
|
||||
.with_scheduled_delay(Duration::from_millis(1000))
|
||||
.build();
|
||||
|
||||
let exporter_result = opentelemetry_otlp::SpanExporter::builder()
|
||||
.with_tonic()
|
||||
.with_export_config(get_opentelemetry_exporter_config(config))
|
||||
.build();
|
||||
|
||||
let exporter = if config.ignore_errors {
|
||||
#[allow(clippy::print_stderr)] // The logger hasn't been initialized yet
|
||||
exporter_result
|
||||
.inspect_err(|error| eprintln!("Failed to build traces exporter: {error:?}"))
|
||||
.ok()?
|
||||
} else {
|
||||
// Safety: This is conditional, there is an option to avoid this behavior at runtime.
|
||||
#[allow(clippy::expect_used)]
|
||||
exporter_result.expect("Failed to build traces exporter")
|
||||
};
|
||||
|
||||
let mut provider_builder = trace::TracerProvider::builder()
|
||||
.with_span_processor(
|
||||
trace::BatchSpanProcessor::builder(
|
||||
exporter,
|
||||
// The runtime would have to be updated if a different web framework is used
|
||||
opentelemetry_sdk::runtime::TokioCurrentThread,
|
||||
)
|
||||
.with_batch_config(batch_config)
|
||||
.build(),
|
||||
)
|
||||
.with_sampler(trace::Sampler::ParentBased(Box::new(ConditionalSampler(
|
||||
TraceAssertion {
|
||||
clauses: config
|
||||
.route_to_trace
|
||||
.clone()
|
||||
.map(|inner| inner.into_iter().map(Into::into).collect()),
|
||||
.map(|inner| inner.into_iter().map(TraceUrlAssert::from).collect()),
|
||||
default: false,
|
||||
},
|
||||
trace::Sampler::TraceIdRatioBased(config.sampling_rate.unwrap_or(1.0)),
|
||||
))))
|
||||
.with_resource(Resource::new(vec![KeyValue::new(
|
||||
"service.name",
|
||||
service_name.to_owned(),
|
||||
)]));
|
||||
.with_resource(opentelemetry_sdk::Resource::new(vec![
|
||||
opentelemetry::KeyValue::new("service.name", service_name.to_owned()),
|
||||
]));
|
||||
|
||||
if config.use_xray_generator {
|
||||
trace_config = trace_config.with_id_generator(trace::XrayIdGenerator::default());
|
||||
provider_builder = provider_builder
|
||||
.with_id_generator(opentelemetry_aws::trace::XrayIdGenerator::default());
|
||||
}
|
||||
|
||||
// Change the default export interval from 5 seconds to 1 second
|
||||
let batch_config = BatchConfig::default().with_scheduled_delay(Duration::from_millis(1000));
|
||||
|
||||
let traces_layer_result = opentelemetry_otlp::new_pipeline()
|
||||
.tracing()
|
||||
.with_exporter(get_opentelemetry_exporter(config))
|
||||
.with_batch_config(batch_config)
|
||||
.with_trace_config(trace_config)
|
||||
.install_batch(runtime::TokioCurrentThread)
|
||||
.map(|tracer| tracing_opentelemetry::layer().with_tracer(tracer));
|
||||
|
||||
#[allow(clippy::print_stderr)] // The logger hasn't been initialized yet
|
||||
if config.ignore_errors {
|
||||
traces_layer_result
|
||||
.map_err(|error| {
|
||||
eprintln!("Failed to create an `opentelemetry_otlp` tracer: {error:?}")
|
||||
})
|
||||
.ok()
|
||||
} else {
|
||||
// Safety: This is conditional, there is an option to avoid this behavior at runtime.
|
||||
#[allow(clippy::expect_used)]
|
||||
Some(traces_layer_result.expect("Failed to create an `opentelemetry_otlp` tracer"))
|
||||
}
|
||||
Some(
|
||||
tracing_opentelemetry::layer()
|
||||
.with_tracer(provider_builder.build().tracer(service_name.to_owned())),
|
||||
)
|
||||
}
|
||||
|
||||
fn setup_metrics_pipeline(config: &config::LogTelemetry) -> Option<BasicController> {
|
||||
let histogram_buckets = {
|
||||
let mut init = 0.01;
|
||||
let mut buckets: [f64; 15] = [0.0; 15];
|
||||
fn setup_metrics_pipeline(config: &config::LogTelemetry) {
|
||||
use opentelemetry_otlp::WithExportConfig;
|
||||
|
||||
for bucket in &mut buckets {
|
||||
init *= 2.0;
|
||||
*bucket = init;
|
||||
}
|
||||
buckets
|
||||
};
|
||||
|
||||
let metrics_controller_result = opentelemetry_otlp::new_pipeline()
|
||||
.metrics(
|
||||
simple::histogram(histogram_buckets),
|
||||
cumulative_temporality_selector(),
|
||||
// This would have to be updated if a different web framework is used
|
||||
runtime::TokioCurrentThread,
|
||||
)
|
||||
.with_exporter(get_opentelemetry_exporter(config))
|
||||
.with_period(Duration::from_secs(3))
|
||||
.with_timeout(Duration::from_secs(10))
|
||||
.with_resource(Resource::new(vec![KeyValue::new(
|
||||
"pod",
|
||||
std::env::var("POD_NAME").map_or(
|
||||
"hyperswitch-server-default".into(),
|
||||
Into::<opentelemetry::Value>::into,
|
||||
),
|
||||
)]))
|
||||
let exporter_result = opentelemetry_otlp::MetricExporter::builder()
|
||||
.with_tonic()
|
||||
.with_temporality(opentelemetry_sdk::metrics::Temporality::Cumulative)
|
||||
.with_export_config(get_opentelemetry_exporter_config(config))
|
||||
.build();
|
||||
|
||||
#[allow(clippy::print_stderr)] // The logger hasn't been initialized yet
|
||||
if config.ignore_errors {
|
||||
metrics_controller_result
|
||||
.map_err(|error| eprintln!("Failed to setup metrics pipeline: {error:?}"))
|
||||
.ok()
|
||||
let exporter = if config.ignore_errors {
|
||||
#[allow(clippy::print_stderr)] // The logger hasn't been initialized yet
|
||||
exporter_result
|
||||
.inspect_err(|error| eprintln!("Failed to build metrics exporter: {error:?}"))
|
||||
.ok();
|
||||
return;
|
||||
} else {
|
||||
// Safety: This is conditional, there is an option to avoid this behavior at runtime.
|
||||
#[allow(clippy::expect_used)]
|
||||
Some(metrics_controller_result.expect("Failed to setup metrics pipeline"))
|
||||
}
|
||||
exporter_result.expect("Failed to build metrics exporter")
|
||||
};
|
||||
|
||||
let reader = opentelemetry_sdk::metrics::PeriodicReader::builder(
|
||||
exporter,
|
||||
// The runtime would have to be updated if a different web framework is used
|
||||
opentelemetry_sdk::runtime::TokioCurrentThread,
|
||||
)
|
||||
.with_interval(Duration::from_secs(3))
|
||||
.with_timeout(Duration::from_secs(10))
|
||||
.build();
|
||||
|
||||
let provider = opentelemetry_sdk::metrics::SdkMeterProvider::builder()
|
||||
.with_reader(reader)
|
||||
.with_resource(opentelemetry_sdk::Resource::new([
|
||||
opentelemetry::KeyValue::new(
|
||||
"pod",
|
||||
std::env::var("POD_NAME").unwrap_or(String::from("hyperswitch-server-default")),
|
||||
),
|
||||
]))
|
||||
.build();
|
||||
|
||||
opentelemetry::global::set_meter_provider(provider);
|
||||
}
|
||||
|
||||
fn get_envfilter(
|
||||
|
||||
@ -1,16 +1,5 @@
|
||||
//! Utilities to easily create opentelemetry contexts, meters and metrics.
|
||||
|
||||
/// Create a metrics [`Context`][Context] with the specified name.
|
||||
///
|
||||
/// [Context]: opentelemetry::Context
|
||||
#[macro_export]
|
||||
macro_rules! metrics_context {
|
||||
($name:ident) => {
|
||||
pub(crate) static $name: once_cell::sync::Lazy<$crate::opentelemetry::Context> =
|
||||
once_cell::sync::Lazy::new($crate::opentelemetry::Context::current);
|
||||
};
|
||||
}
|
||||
|
||||
/// Create a global [`Meter`][Meter] with the specified name and an optional description.
|
||||
///
|
||||
/// [Meter]: opentelemetry::metrics::Meter
|
||||
@ -20,14 +9,14 @@ macro_rules! global_meter {
|
||||
static $name: once_cell::sync::Lazy<$crate::opentelemetry::metrics::Meter> =
|
||||
once_cell::sync::Lazy::new(|| $crate::opentelemetry::global::meter(stringify!($name)));
|
||||
};
|
||||
($name:ident, $description:literal) => {
|
||||
static $name: once_cell::sync::Lazy<$crate::opentelemetry::metrics::Meter> =
|
||||
once_cell::sync::Lazy::new(|| $crate::opentelemetry::global::meter($description));
|
||||
($meter:ident, $name:literal) => {
|
||||
static $meter: once_cell::sync::Lazy<$crate::opentelemetry::metrics::Meter> =
|
||||
once_cell::sync::Lazy::new(|| $crate::opentelemetry::global::meter(stringify!($name)));
|
||||
};
|
||||
}
|
||||
|
||||
/// Create a [`Counter`][Counter] metric with the specified name and an optional description,
|
||||
/// associated with the specified meter. Note that the meter must be to a valid [`Meter`][Meter].
|
||||
/// associated with the specified meter. Note that the meter must be a valid [`Meter`][Meter].
|
||||
///
|
||||
/// [Counter]: opentelemetry::metrics::Counter
|
||||
/// [Meter]: opentelemetry::metrics::Meter
|
||||
@ -36,36 +25,54 @@ macro_rules! counter_metric {
|
||||
($name:ident, $meter:ident) => {
|
||||
pub(crate) static $name: once_cell::sync::Lazy<
|
||||
$crate::opentelemetry::metrics::Counter<u64>,
|
||||
> = once_cell::sync::Lazy::new(|| $meter.u64_counter(stringify!($name)).init());
|
||||
> = once_cell::sync::Lazy::new(|| $meter.u64_counter(stringify!($name)).build());
|
||||
};
|
||||
($name:ident, $meter:ident, description:literal) => {
|
||||
#[doc = $description]
|
||||
pub(crate) static $name: once_cell::sync::Lazy<
|
||||
$crate::opentelemetry::metrics::Counter<u64>,
|
||||
> = once_cell::sync::Lazy::new(|| $meter.u64_counter($description).init());
|
||||
> = once_cell::sync::Lazy::new(|| {
|
||||
$meter
|
||||
.u64_counter(stringify!($name))
|
||||
.with_description($description)
|
||||
.build()
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/// Create a [`Histogram`][Histogram] metric with the specified name and an optional description,
|
||||
/// associated with the specified meter. Note that the meter must be to a valid [`Meter`][Meter].
|
||||
/// Create a [`Histogram`][Histogram] f64 metric with the specified name and an optional description,
|
||||
/// associated with the specified meter. Note that the meter must be a valid [`Meter`][Meter].
|
||||
///
|
||||
/// [Histogram]: opentelemetry::metrics::Histogram
|
||||
/// [Meter]: opentelemetry::metrics::Meter
|
||||
#[macro_export]
|
||||
macro_rules! histogram_metric {
|
||||
macro_rules! histogram_metric_f64 {
|
||||
($name:ident, $meter:ident) => {
|
||||
pub(crate) static $name: once_cell::sync::Lazy<
|
||||
$crate::opentelemetry::metrics::Histogram<f64>,
|
||||
> = once_cell::sync::Lazy::new(|| $meter.f64_histogram(stringify!($name)).init());
|
||||
> = once_cell::sync::Lazy::new(|| {
|
||||
$meter
|
||||
.f64_histogram(stringify!($name))
|
||||
.with_boundaries($crate::metrics::f64_histogram_buckets())
|
||||
.build()
|
||||
});
|
||||
};
|
||||
($name:ident, $meter:ident, $description:literal) => {
|
||||
#[doc = $description]
|
||||
pub(crate) static $name: once_cell::sync::Lazy<
|
||||
$crate::opentelemetry::metrics::Histogram<f64>,
|
||||
> = once_cell::sync::Lazy::new(|| $meter.f64_histogram($description).init());
|
||||
> = once_cell::sync::Lazy::new(|| {
|
||||
$meter
|
||||
.f64_histogram(stringify!($name))
|
||||
.with_description($description)
|
||||
.with_boundaries($crate::metrics::f64_histogram_buckets())
|
||||
.build()
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/// Create a [`Histogram`][Histogram] u64 metric with the specified name and an optional description,
|
||||
/// associated with the specified meter. Note that the meter must be to a valid [`Meter`][Meter].
|
||||
/// associated with the specified meter. Note that the meter must be a valid [`Meter`][Meter].
|
||||
///
|
||||
/// [Histogram]: opentelemetry::metrics::Histogram
|
||||
/// [Meter]: opentelemetry::metrics::Meter
|
||||
@ -74,64 +81,72 @@ macro_rules! histogram_metric_u64 {
|
||||
($name:ident, $meter:ident) => {
|
||||
pub(crate) static $name: once_cell::sync::Lazy<
|
||||
$crate::opentelemetry::metrics::Histogram<u64>,
|
||||
> = once_cell::sync::Lazy::new(|| $meter.u64_histogram(stringify!($name)).init());
|
||||
> = once_cell::sync::Lazy::new(|| {
|
||||
$meter
|
||||
.u64_histogram(stringify!($name))
|
||||
.with_boundaries($crate::metrics::f64_histogram_buckets())
|
||||
.build()
|
||||
});
|
||||
};
|
||||
($name:ident, $meter:ident, $description:literal) => {
|
||||
#[doc = $description]
|
||||
pub(crate) static $name: once_cell::sync::Lazy<
|
||||
$crate::opentelemetry::metrics::Histogram<u64>,
|
||||
> = once_cell::sync::Lazy::new(|| $meter.u64_histogram($description).init());
|
||||
> = once_cell::sync::Lazy::new(|| {
|
||||
$meter
|
||||
.u64_histogram(stringify!($name))
|
||||
.with_description($description)
|
||||
.with_boundaries($crate::metrics::f64_histogram_buckets())
|
||||
.build()
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/// Create a [`Histogram`][Histogram] i64 metric with the specified name and an optional description,
|
||||
/// associated with the specified meter. Note that the meter must be to a valid [`Meter`][Meter].
|
||||
/// Create a [`Gauge`][Gauge] metric with the specified name and an optional description,
|
||||
/// associated with the specified meter. Note that the meter must be a valid [`Meter`][Meter].
|
||||
///
|
||||
/// [Histogram]: opentelemetry::metrics::Histogram
|
||||
/// [Meter]: opentelemetry::metrics::Meter
|
||||
#[macro_export]
|
||||
macro_rules! histogram_metric_i64 {
|
||||
($name:ident, $meter:ident) => {
|
||||
pub(crate) static $name: once_cell::sync::Lazy<
|
||||
$crate::opentelemetry::metrics::Histogram<i64>,
|
||||
> = once_cell::sync::Lazy::new(|| $meter.i64_histogram(stringify!($name)).init());
|
||||
};
|
||||
($name:ident, $meter:ident, $description:literal) => {
|
||||
pub(crate) static $name: once_cell::sync::Lazy<
|
||||
$crate::opentelemetry::metrics::Histogram<i64>,
|
||||
> = once_cell::sync::Lazy::new(|| $meter.i64_histogram($description).init());
|
||||
};
|
||||
}
|
||||
|
||||
/// Create a [`ObservableGauge`][ObservableGauge] metric with the specified name and an optional description,
|
||||
/// associated with the specified meter. Note that the meter must be to a valid [`Meter`][Meter].
|
||||
///
|
||||
/// [ObservableGauge]: opentelemetry::metrics::ObservableGauge
|
||||
/// [Gauge]: opentelemetry::metrics::Gauge
|
||||
/// [Meter]: opentelemetry::metrics::Meter
|
||||
#[macro_export]
|
||||
macro_rules! gauge_metric {
|
||||
($name:ident, $meter:ident) => {
|
||||
pub(crate) static $name: once_cell::sync::Lazy<
|
||||
$crate::opentelemetry::metrics::ObservableGauge<u64>,
|
||||
> = once_cell::sync::Lazy::new(|| $meter.u64_observable_gauge(stringify!($name)).init());
|
||||
pub(crate) static $name: once_cell::sync::Lazy<$crate::opentelemetry::metrics::Gauge<u64>> =
|
||||
once_cell::sync::Lazy::new(|| $meter.u64_gauge(stringify!($name)).build());
|
||||
};
|
||||
($name:ident, $meter:ident, description:literal) => {
|
||||
pub(crate) static $name: once_cell::sync::Lazy<
|
||||
$crate::opentelemetry::metrics::ObservableGauge<u64>,
|
||||
> = once_cell::sync::Lazy::new(|| $meter.u64_observable_gauge($description).init());
|
||||
#[doc = $description]
|
||||
pub(crate) static $name: once_cell::sync::Lazy<$crate::opentelemetry::metrics::Gauge<u64>> =
|
||||
once_cell::sync::Lazy::new(|| {
|
||||
$meter
|
||||
.u64_gauge(stringify!($name))
|
||||
.with_description($description)
|
||||
.build()
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
pub use helpers::add_attributes;
|
||||
/// Create attributes to associate with a metric from key-value pairs.
|
||||
#[macro_export]
|
||||
macro_rules! metric_attributes {
|
||||
($(($key:expr, $value:expr $(,)?)),+ $(,)?) => {
|
||||
&[$($crate::opentelemetry::KeyValue::new($key, $value)),+]
|
||||
};
|
||||
}
|
||||
|
||||
pub use helpers::f64_histogram_buckets;
|
||||
|
||||
mod helpers {
|
||||
pub fn add_attributes<T, U>(attributes: U) -> Vec<opentelemetry::KeyValue>
|
||||
where
|
||||
T: Into<opentelemetry::Value>,
|
||||
U: IntoIterator<Item = (&'static str, T)>,
|
||||
{
|
||||
attributes
|
||||
.into_iter()
|
||||
.map(|(key, value)| opentelemetry::KeyValue::new(key, value))
|
||||
.collect::<Vec<_>>()
|
||||
/// Returns the buckets to be used for a f64 histogram
|
||||
#[inline(always)]
|
||||
pub fn f64_histogram_buckets() -> Vec<f64> {
|
||||
let mut init = 0.01;
|
||||
let mut buckets: [f64; 15] = [0.0; 15];
|
||||
|
||||
for bucket in &mut buckets {
|
||||
init *= 2.0;
|
||||
*bucket = init;
|
||||
}
|
||||
|
||||
Vec::from(buckets)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user