Skip to content

Commit c08c0b4

Browse files
author
Elias Ram
committed
optimize regex and string allocation
1 parent 493d0ff commit c08c0b4

File tree

8 files changed

+160
-134
lines changed

8 files changed

+160
-134
lines changed

Cargo.lock

Lines changed: 13 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sentry-core/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,14 @@ UNSTABLE_cadence = ["dep:cadence", "UNSTABLE_metrics"]
3232
[dependencies]
3333
cadence = { version = "0.29.0", optional = true }
3434
crc32fast = "1.4.0"
35-
itertools = "0.10.5"
35+
itertools = "0.13.0"
3636
log = { version = "0.4.8", optional = true, features = ["std"] }
3737
once_cell = "1"
3838
rand = { version = "0.8.1", optional = true }
3939
regex = "1.7.3"
4040
sentry-types = { version = "0.32.3", path = "../sentry-types" }
4141
serde = { version = "1.0.104", features = ["derive"] }
4242
serde_json = { version = "1.0.46" }
43-
unicode-segmentation = "1.11.0"
4443
uuid = { version = "1.0.0", features = ["v4", "serde"], optional = true }
4544

4645
[dev-dependencies]

sentry-core/src/metrics/mod.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -535,13 +535,13 @@ impl Metric {
535535
let data = format!(
536536
"{}@{}:{}|{}|#{}|T{}",
537537
NormalizedName::from(self.name.as_ref()),
538-
NormalizedUnit::from(self.unit),
538+
NormalizedUnit::from(self.unit.to_string().as_ref()),
539539
self.value,
540540
self.value.ty(),
541-
NormalizedTags::from(self.tags),
541+
NormalizedTags::from(&self.tags),
542542
timestamp
543543
);
544-
Envelope::from_item(EnvelopeItem::Statsd(data.into_bytes()))
544+
EnvelopeItem::Statsd(data.into_bytes()).into()
545545
}
546546
}
547547

@@ -597,9 +597,9 @@ impl MetricBuilder {
597597
K: Into<MetricStr>,
598598
V: Into<MetricStr>,
599599
{
600-
tags.into_iter().for_each(|(k, v)| {
600+
for (k, v) in tags {
601601
self.metric.tags.insert(k.into(), v.into());
602-
});
602+
}
603603
self
604604
}
605605

@@ -836,7 +836,12 @@ impl Worker {
836836
for (timestamp, buckets) in buckets {
837837
for (key, value) in buckets {
838838
write!(&mut out, "{}", NormalizedName::from(key.name.as_ref()))?;
839-
write!(&mut out, "@{}", NormalizedUnit::from(key.unit))?;
839+
match key.unit {
840+
MetricUnit::Custom(u) => {
841+
write!(&mut out, "@{}", NormalizedUnit::from(u.as_ref()))?
842+
}
843+
_ => write!(&mut out, "@{}", key.unit)?,
844+
}
840845
match value {
841846
BucketValue::Counter(c) => {
842847
write!(&mut out, ":{}", c)?;
@@ -862,7 +867,7 @@ impl Worker {
862867

863868
write!(&mut out, "|{}", key.ty.as_str())?;
864869
let normalized_tags =
865-
NormalizedTags::from(key.tags).with_default_tags(&self.default_tags);
870+
NormalizedTags::from(&key.tags).with_default_tags(&self.default_tags);
866871
write!(&mut out, "|#{}", normalized_tags)?;
867872
writeln!(&mut out, "|T{}", timestamp)?;
868873
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
11
pub mod normalized_name;
22
pub mod normalized_tags;
33
pub mod normalized_unit;
4+
5+
pub fn truncate(s: &str, max_chars: usize) -> &str {
6+
match s.char_indices().nth(max_chars) {
7+
None => s,
8+
Some((i, _)) => &s[..i],
9+
}
10+
}
11+
12+
#[cfg(test)]
13+
mod test {
14+
15+
#[test]
16+
fn test_truncate_ascii_chars() {
17+
assert_eq!("abc", super::truncate("abcde", 3));
18+
}
19+
20+
#[test]
21+
fn test_truncate_unicode_chars() {
22+
assert_eq!("😀😀😀", super::truncate("😀😀😀😀😀", 3));
23+
}
24+
}

sentry-core/src/metrics/normalization/normalized_name.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1+
use std::{borrow::Cow, sync::OnceLock};
2+
13
use regex::Regex;
2-
use std::borrow::Cow;
34

45
pub struct NormalizedName<'a> {
56
name: Cow<'a, str>,
67
}
78

89
impl<'a> From<&'a str> for NormalizedName<'a> {
910
fn from(name: &'a str) -> Self {
11+
static METRIC_NAME_RE: OnceLock<Regex> = OnceLock::new();
1012
Self {
11-
name: Regex::new(r"[^a-zA-Z0-9_\-.]")
12-
.expect("Regex should compile")
13-
.replace_all(name, "_"),
13+
name: METRIC_NAME_RE
14+
.get_or_init(|| Regex::new(r"[^a-zA-Z0-9_\-.]").expect("Regex should compile"))
15+
.replace_all(super::truncate(name, 150), "_"),
1416
}
1517
}
1618
}
1719

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

3436
assert_eq!(expected, actual);
3537
}
38+
39+
#[test]
40+
fn test_length_restriction() {
41+
let expected = "a".repeat(150);
42+
43+
let actual = NormalizedName::from("a".repeat(155).as_ref()).to_string();
44+
45+
assert_eq!(expected, actual);
46+
}
3647
}

0 commit comments

Comments
 (0)