Skip to content

Commit

Permalink
optimize regex and string allocation
Browse files Browse the repository at this point in the history
  • Loading branch information
Elias Ram committed May 27, 2024
1 parent 493d0ff commit c08c0b4
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 134 deletions.
24 changes: 13 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions sentry-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,14 @@ UNSTABLE_cadence = ["dep:cadence", "UNSTABLE_metrics"]
[dependencies]
cadence = { version = "0.29.0", optional = true }
crc32fast = "1.4.0"
itertools = "0.10.5"
itertools = "0.13.0"
log = { version = "0.4.8", optional = true, features = ["std"] }
once_cell = "1"
rand = { version = "0.8.1", optional = true }
regex = "1.7.3"
sentry-types = { version = "0.32.3", path = "../sentry-types" }
serde = { version = "1.0.104", features = ["derive"] }
serde_json = { version = "1.0.46" }
unicode-segmentation = "1.11.0"
uuid = { version = "1.0.0", features = ["v4", "serde"], optional = true }

[dev-dependencies]
Expand Down
19 changes: 12 additions & 7 deletions sentry-core/src/metrics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,13 +535,13 @@ impl Metric {
let data = format!(
"{}@{}:{}|{}|#{}|T{}",
NormalizedName::from(self.name.as_ref()),
NormalizedUnit::from(self.unit),
NormalizedUnit::from(self.unit.to_string().as_ref()),
self.value,
self.value.ty(),
NormalizedTags::from(self.tags),
NormalizedTags::from(&self.tags),
timestamp
);
Envelope::from_item(EnvelopeItem::Statsd(data.into_bytes()))
EnvelopeItem::Statsd(data.into_bytes()).into()
}
}

Expand Down Expand Up @@ -597,9 +597,9 @@ impl MetricBuilder {
K: Into<MetricStr>,
V: Into<MetricStr>,
{
tags.into_iter().for_each(|(k, v)| {
for (k, v) in tags {
self.metric.tags.insert(k.into(), v.into());
});
}
self
}

Expand Down Expand Up @@ -836,7 +836,12 @@ impl Worker {
for (timestamp, buckets) in buckets {
for (key, value) in buckets {
write!(&mut out, "{}", NormalizedName::from(key.name.as_ref()))?;
write!(&mut out, "@{}", NormalizedUnit::from(key.unit))?;
match key.unit {
MetricUnit::Custom(u) => {
write!(&mut out, "@{}", NormalizedUnit::from(u.as_ref()))?
}
_ => write!(&mut out, "@{}", key.unit)?,
}
match value {
BucketValue::Counter(c) => {
write!(&mut out, ":{}", c)?;
Expand All @@ -862,7 +867,7 @@ impl Worker {

write!(&mut out, "|{}", key.ty.as_str())?;
let normalized_tags =
NormalizedTags::from(key.tags).with_default_tags(&self.default_tags);
NormalizedTags::from(&key.tags).with_default_tags(&self.default_tags);
write!(&mut out, "|#{}", normalized_tags)?;
writeln!(&mut out, "|T{}", timestamp)?;
}
Expand Down
21 changes: 21 additions & 0 deletions sentry-core/src/metrics/normalization/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
pub mod normalized_name;
pub mod normalized_tags;
pub mod normalized_unit;

pub fn truncate(s: &str, max_chars: usize) -> &str {
match s.char_indices().nth(max_chars) {
None => s,
Some((i, _)) => &s[..i],
}
}

#[cfg(test)]
mod test {

#[test]
fn test_truncate_ascii_chars() {
assert_eq!("abc", super::truncate("abcde", 3));
}

#[test]
fn test_truncate_unicode_chars() {
assert_eq!("😀😀😀", super::truncate("😀😀😀😀😀", 3));
}
}
21 changes: 16 additions & 5 deletions sentry-core/src/metrics/normalization/normalized_name.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
use std::{borrow::Cow, sync::OnceLock};

use regex::Regex;
use std::borrow::Cow;

pub struct NormalizedName<'a> {
name: Cow<'a, str>,
}

impl<'a> From<&'a str> for NormalizedName<'a> {
fn from(name: &'a str) -> Self {
static METRIC_NAME_RE: OnceLock<Regex> = OnceLock::new();
Self {
name: Regex::new(r"[^a-zA-Z0-9_\-.]")
.expect("Regex should compile")
.replace_all(name, "_"),
name: METRIC_NAME_RE
.get_or_init(|| Regex::new(r"[^a-zA-Z0-9_\-.]").expect("Regex should compile"))
.replace_all(super::truncate(name, 150), "_"),
}
}
}

impl std::fmt::Display for NormalizedName<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.name)
}
}
Expand All @@ -33,4 +35,13 @@ mod test {

assert_eq!(expected, actual);
}

#[test]
fn test_length_restriction() {
let expected = "a".repeat(150);

let actual = NormalizedName::from("a".repeat(155).as_ref()).to_string();

assert_eq!(expected, actual);
}
}
Loading

0 comments on commit c08c0b4

Please sign in to comment.