Skip to content

Commit

Permalink
Metric should not be counted as errors for metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
bryn committed Sep 1, 2023
1 parent a6e2a2a commit 55d3ae6
Showing 1 changed file with 213 additions and 34 deletions.
247 changes: 213 additions & 34 deletions apollo-router/src/plugins/telemetry/metrics/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ use super::METRIC_PREFIX_HISTOGRAM;
use super::METRIC_PREFIX_MONOTONIC_COUNTER;
use super::METRIC_PREFIX_VALUE;

const I64_MAX: u64 = i64::MAX as u64;

#[derive(Default)]
pub(crate) struct Instruments {
u64_counter: MetricsMap<Counter<u64>>,
Expand Down Expand Up @@ -159,69 +157,249 @@ pub(crate) struct MetricVisitor<'a> {
pub(crate) metric: Option<(&'static str, InstrumentType)>,
pub(crate) custom_attributes: Vec<KeyValue>,
pub(crate) meter: &'a Meter,
attributes_ignored: bool,
}

impl<'a> MetricVisitor<'a> {
fn set_metric(&mut self, name: &'static str, instrument_type: InstrumentType) {
self.metric = Some((name, instrument_type));
if self.attributes_ignored {
tracing::error!(
metric_name = name,
"metric attributes must be declared after the metric value. Some attributes have been ignored"
);
}
}
}

impl<'a> Visit for MetricVisitor<'a> {
fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
// Do not display the log content
if field.name() != "message" {
fn record_f64(&mut self, field: &Field, value: f64) {
if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_MONOTONIC_COUNTER) {
self.set_metric(metric_name, InstrumentType::CounterF64(value));
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_COUNTER) {
self.set_metric(metric_name, InstrumentType::UpDownCounterF64(value));
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_HISTOGRAM) {
self.set_metric(metric_name, InstrumentType::HistogramF64(value));
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_VALUE) {
tracing::error!(
metric_name,
"gauge must be u64. This metric will be ignored"
);
} else if self.metric.is_some() {
self.custom_attributes.push(KeyValue::new(
Key::from_static_str(field.name()),
Value::from(format!("{value:?}")),
Value::from(value),
));
} else {
self.attributes_ignored = true
}
}

fn record_str(&mut self, field: &Field, value: &str) {
self.custom_attributes.push(KeyValue::new(
Key::from_static_str(field.name()),
Value::from(value.to_string()),
));
fn record_i64(&mut self, field: &Field, value: i64) {
if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_MONOTONIC_COUNTER) {
tracing::error!(
metric_name,
"monotonic counter must be u64 or f64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_COUNTER) {
self.set_metric(metric_name, InstrumentType::UpDownCounterI64(value));
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_HISTOGRAM) {
self.set_metric(metric_name, InstrumentType::HistogramI64(value));
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_VALUE) {
tracing::error!(
metric_name,
"gauge must be u64. This metric will be ignored"
);
} else if self.metric.is_some() {
self.custom_attributes.push(KeyValue::new(
Key::from_static_str(field.name()),
Value::from(value),
));
} else {
self.attributes_ignored = true
}
}

fn record_u64(&mut self, field: &Field, value: u64) {
if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_MONOTONIC_COUNTER) {
self.metric = Some((metric_name, InstrumentType::CounterU64(value)));
self.set_metric(metric_name, InstrumentType::CounterU64(value));
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_COUNTER) {
if value <= I64_MAX {
self.metric = Some((metric_name, InstrumentType::UpDownCounterI64(value as i64)));
} else {
eprintln!(
"[tracing-opentelemetry]: Received Counter metric, but \
provided u64: {value} is greater than i64::MAX. Ignoring \
this metric."
);
}
tracing::error!(
metric_name,
"counter must be i64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_HISTOGRAM) {
self.metric = Some((metric_name, InstrumentType::HistogramU64(value)));
self.set_metric(metric_name, InstrumentType::HistogramU64(value));
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_VALUE) {
self.metric = Some((metric_name, InstrumentType::GaugeU64(value)));
self.set_metric(metric_name, InstrumentType::GaugeU64(value));
} else if self.metric.is_some() {
tracing::error!(
name = field.name(),
"metric attribute must be i64, f64, string or bool. This attribute will be ignored"
);
} else {
self.record_debug(field, &value);
self.attributes_ignored = true
}
}

fn record_f64(&mut self, field: &Field, value: f64) {
fn record_i128(&mut self, field: &Field, _value: i128) {
if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_MONOTONIC_COUNTER) {
self.metric = Some((metric_name, InstrumentType::CounterF64(value)));
tracing::error!(
metric_name,
"monotonic counter must be u64 or f64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_COUNTER) {
self.metric = Some((metric_name, InstrumentType::UpDownCounterF64(value)));
tracing::error!(
metric_name,
"counter must be i64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_HISTOGRAM) {
self.metric = Some((metric_name, InstrumentType::HistogramF64(value)));
tracing::error!(
metric_name,
"histogram must be u64, i64 or f64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_VALUE) {
tracing::error!(
metric_name,
"gauge must be u64. This metric will be ignored"
);
} else if self.metric.is_some() {
tracing::error!(
name = field.name(),
"metric attribute must be i64, f64, string or bool. This attribute will be ignored"
);
} else {
self.record_debug(field, &value);
self.attributes_ignored = true
}
}

fn record_i64(&mut self, field: &Field, value: i64) {
fn record_u128(&mut self, field: &Field, _value: u128) {
if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_MONOTONIC_COUNTER) {
self.metric = Some((metric_name, InstrumentType::CounterU64(value as u64)));
tracing::error!(
metric_name,
"monotonic counter must be u64 or f64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_COUNTER) {
self.metric = Some((metric_name, InstrumentType::UpDownCounterI64(value)));
tracing::error!(
metric_name,
"counter must be i64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_HISTOGRAM) {
self.metric = Some((metric_name, InstrumentType::HistogramI64(value)));
tracing::error!(
metric_name,
"histogram must be u64, i64 or f64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_VALUE) {
tracing::error!(
metric_name,
"gauge must be u64. This metric will be ignored"
);
} else if self.metric.is_some() {
tracing::error!(
name = field.name(),
"metric attribute must be i64, f64, string or bool. This attribute will be ignored"
);
} else {
self.attributes_ignored = true
}
}

fn record_bool(&mut self, field: &Field, value: bool) {
if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_MONOTONIC_COUNTER) {
tracing::error!(
metric_name,
"monotonic counter must be u64 or f64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_COUNTER) {
tracing::error!(
metric_name,
"counter must be i64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_HISTOGRAM) {
tracing::error!(
metric_name,
"histogram must be u64, i64 or f64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_VALUE) {
tracing::error!(
metric_name,
"gauge must be u64. This metric will be ignored"
);
} else if self.metric.is_some() {
self.custom_attributes.push(KeyValue::new(
Key::from_static_str(field.name()),
Value::from(value),
));
} else {
self.attributes_ignored = true
}
}

fn record_str(&mut self, field: &Field, value: &str) {
if field.name() == "message" {
return;
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_MONOTONIC_COUNTER)
{
tracing::error!(
metric_name,
"monotonic counter must be u64 or f64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_COUNTER) {
tracing::error!(
metric_name,
"counter must be i64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_HISTOGRAM) {
tracing::error!(
metric_name,
"histogram must be u64, i64 or f64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_VALUE) {
tracing::error!(
metric_name,
"gauge must be u64. This metric will be ignored"
);
} else if self.metric.is_some() {
self.custom_attributes.push(KeyValue::new(
Key::from_static_str(field.name()),
Value::from(value.to_string()),
));
} else {
self.attributes_ignored = true
}
}

fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
if field.name() == "message" {
return;
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_MONOTONIC_COUNTER)
{
tracing::error!(
metric_name,
"monotonic counter must be u64 or f64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_COUNTER) {
tracing::error!(
metric_name,
"counter must be i64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_HISTOGRAM) {
tracing::error!(
metric_name,
"histogram must be u64, i64 or f64. This metric will be ignored"
);
} else if let Some(metric_name) = field.name().strip_prefix(METRIC_PREFIX_VALUE) {
tracing::error!(
metric_name,
"gauge must be u64. This metric will be ignored"
);
} else if self.metric.is_some() {
self.custom_attributes.push(KeyValue::new(
Key::from_static_str(field.name()),
Value::from(format!("{value:?}")),
));
} else {
self.record_debug(field, &value);
self.attributes_ignored = true
}
}
}
Expand Down Expand Up @@ -265,6 +443,7 @@ where
meter: &self.meter,
metric: None,
custom_attributes: Vec::new(),
attributes_ignored: false,
};
event.record(&mut metric_visitor);
metric_visitor.finish();
Expand Down

0 comments on commit 55d3ae6

Please sign in to comment.