Skip to content

Commit

Permalink
fix: Move statsd parsing to metrics module
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-auer committed Dec 11, 2023
1 parent c164983 commit cdd36e4
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 36 deletions.
37 changes: 1 addition & 36 deletions sentry-core/src/cadence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ where
S: MetricSink,
{
fn emit(&self, string: &str) -> std::io::Result<usize> {
if let Some(metric) = parse_metric(string) {
if let Ok(metric) = Metric::parse_statsd(string) {
self.client.add_metric(metric);
}

Expand All @@ -50,41 +50,6 @@ where
}
}

fn parse_metric(string: &str) -> Option<Metric> {
let mut components = string.split('|');

let (mri_str, value_str) = components.next()?.split_once(':')?;
let (name, unit) = match mri_str.split_once('@') {
Some((name, unit_str)) => (name, unit_str.parse().ok()?),
None => (mri_str, MetricUnit::None),
};

let ty = components.next().and_then(|s| s.parse().ok())?;
let value = match ty {
MetricType::Counter => MetricValue::Counter(value_str.parse().ok()?),
MetricType::Distribution => MetricValue::Distribution(value_str.parse().ok()?),
MetricType::Set => MetricValue::Set(value_str.parse().ok()?),
MetricType::Gauge => MetricValue::Gauge(value_str.parse().ok()?),
};

let mut builder = Metric::build(name.to_owned(), value).with_unit(unit);

for component in components {
if let Some('#') = component.chars().next() {
for pair in component.get(1..)?.split(',') {
let mut key_value = pair.splitn(2, ':');

let key = key_value.next()?.to_owned();
let value = key_value.next().unwrap_or_default().to_owned();

builder = builder.with_tag(key, value);
}
}
}

Some(builder.finish())
}

#[cfg(test)]
mod tests {
use cadence::{Counted, Distributed};
Expand Down
50 changes: 50 additions & 0 deletions sentry-core/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,10 @@ impl Metric {
MetricBuilder { metric }
}

pub fn parse_statsd(string: &str) -> Result<Self, ParseMetricError> {
parse_metric_opt(string).ok_or(ParseMetricError(()))
}

pub fn incr(name: impl Into<MetricStr>) -> MetricBuilder {
Self::build(name, MetricValue::Counter(1.0))
}
Expand Down Expand Up @@ -353,6 +357,52 @@ impl MetricBuilder {
}
}

#[derive(Debug)]
pub struct ParseMetricError(());

impl std::error::Error for ParseMetricError {}

impl fmt::Display for ParseMetricError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("invalid metric string")
}
}

fn parse_metric_opt(string: &str) -> Option<Metric> {
let mut components = string.split('|');

let (mri_str, value_str) = components.next()?.split_once(':')?;
let (name, unit) = match mri_str.split_once('@') {
Some((name, unit_str)) => (name, unit_str.parse().ok()?),
None => (mri_str, MetricUnit::None),
};

let ty = components.next().and_then(|s| s.parse().ok())?;
let value = match ty {
MetricType::Counter => MetricValue::Counter(value_str.parse().ok()?),
MetricType::Distribution => MetricValue::Distribution(value_str.parse().ok()?),
MetricType::Set => MetricValue::Set(value_str.parse().ok()?),
MetricType::Gauge => MetricValue::Gauge(value_str.parse().ok()?),
};

let mut builder = Metric::build(name.to_owned(), value).with_unit(unit);

for component in components {
if let Some('#') = component.chars().next() {
for pair in component.get(1..)?.split(',') {
let mut key_value = pair.splitn(2, ':');

let key = key_value.next()?.to_owned();
let value = key_value.next().unwrap_or_default().to_owned();

builder = builder.with_tag(key, value);
}
}
}

Some(builder.finish())
}

pub struct MetricAggregator {
inner: Arc<Mutex<AggregatorInner>>,
handle: Option<JoinHandle<()>>,
Expand Down

0 comments on commit cdd36e4

Please sign in to comment.