use crate::client::Channel;
use std::sync::{
Arc,
atomic::{AtomicUsize, Ordering},
};
macro_rules! metrics {
(
$pub_container:ty {
$field:ident: $internal_container:ident {
$(
$(#[$meta:meta])*
$metric:ident: $ty:ident -> $pub_ty:ident,
)*
}
}
) => {
#[derive(Default)]
pub(crate) struct $internal_container {
$(
$(#[$meta])*
pub(crate) $metric: $ty,
)*
}
impl emit::metric::Source for $internal_container {
fn sample_metrics<S: emit::metric::Sampler>(&self, sampler: S) {
let $internal_container { $($metric),* } = self;
$(
sampler.metric(
emit::metric::Metric::new(
emit::pkg!(),
emit::Empty,
emit::props! {
metric_name: stringify!($metric),
metric_agg: <$ty>::AGG,
metric_value: $metric.sample(),
},
),
);
)*
}
}
impl $pub_container {
$(
$(#[$meta])*
pub fn $metric(&self) -> $pub_ty {
self.$field.$metric.sample()
}
)*
}
};
}
#[derive(Default)]
pub(crate) struct Counter(AtomicUsize);
impl Counter {
const AGG: &'static str = emit::well_known::METRIC_AGG_COUNT;
pub fn increment(&self) {
self.increment_by(1);
}
pub fn increment_by(&self, by: usize) {
self.0.fetch_add(by, Ordering::Relaxed);
}
pub fn sample(&self) -> usize {
self.0.load(Ordering::Relaxed)
}
}
metrics!(
OtlpMetrics {
metrics: InternalMetrics {
event_discarded: Counter -> usize,
event_encoding_failed: Counter -> usize,
transport_conn_established: Counter -> usize,
transport_conn_failed: Counter -> usize,
transport_conn_tls_handshake: Counter -> usize,
transport_conn_tls_failed: Counter -> usize,
transport_request_sent: Counter -> usize,
transport_request_failed: Counter -> usize,
transport_request_compress_gzip: Counter -> usize,
http_batch_sent: Counter -> usize,
http_batch_failed: Counter -> usize,
grpc_batch_sent: Counter -> usize,
grpc_batch_failed: Counter -> usize,
configuration_failed: Counter -> usize,
}
}
);
pub struct OtlpMetrics {
pub(crate) logs_channel_metrics: Option<emit_batcher::ChannelMetrics<Channel>>,
pub(crate) traces_channel_metrics: Option<emit_batcher::ChannelMetrics<Channel>>,
pub(crate) metrics_channel_metrics: Option<emit_batcher::ChannelMetrics<Channel>>,
pub(crate) metrics: Arc<InternalMetrics>,
}
impl emit::metric::Source for OtlpMetrics {
fn sample_metrics<S: emit::metric::sampler::Sampler>(&self, sampler: S) {
if let Some(ref channel_metrics) = self.logs_channel_metrics {
channel_metrics.sample_metrics(emit::metric::sampler::from_fn(|metric| {
sampler.metric(
metric
.by_ref()
.with_name(&format!("otlp_logs_{}", metric.name().unwrap()))
.with_mdl(emit::pkg!().append(emit::path!("logs_channel"))),
);
}));
}
if let Some(ref channel_metrics) = self.traces_channel_metrics {
channel_metrics.sample_metrics(emit::metric::sampler::from_fn(|metric| {
sampler.metric(
metric
.by_ref()
.with_name(&format!("otlp_traces_{}", metric.name().unwrap()))
.with_mdl(emit::pkg!().append(emit::path!("traces_channel"))),
);
}));
}
if let Some(ref channel_metrics) = self.metrics_channel_metrics {
channel_metrics.sample_metrics(emit::metric::sampler::from_fn(|metric| {
sampler.metric(
metric
.by_ref()
.with_name(&format!("otlp_metrics_{}", metric.name().unwrap()))
.with_mdl(emit::pkg!().append(emit::path!("metrics_channel"))),
);
}));
}
self.metrics.sample_metrics(sampler);
}
}