Skip to content

Commit

Permalink
opentelemetry: allocate fewer strings for recording events (#1917)
Browse files Browse the repository at this point in the history
## Motivation

Currently, the `tracing-opentelemetry` subscriber will allocate several
strings for opentelemetry key-value fields in its `on_event`
implementation. Some of these allocations are not necessary, since
`opentelemetry::Value::String` can take a `Cow`, allowing `&'static str`s
to be used without allocating a new `String`.

Since this happens for _every_ event that's recorded to opentelemetry,
this probably has a meaningful performance impact.

## Solution

This branch makes two primary changes:

+ Change the `on_event` method to subscriber to use `&'static str`s for
  event targets when possible, similarly to how we did this for source
  locations in #1911. This way, when events were not recorded via the
  `tracing-log` adapter, we will use the `&'static` tracing metadata
  string for their targets, rather than allocating a new `String`. New
  `String`s are only allocated when an event came from the `log` crate
  and its target is not valid for the `'static` lifetime.

* Use `Level::as_str` for the `Level` key-value field, instead of
  `Level::to_string`. `to_string` calls `fmt::Display` and returns a
  `String`, while `as_str` returns an `&'static str`. This way, levels
  will never allocate a `String`.
  • Loading branch information
hawkw committed Feb 9, 2022
1 parent 2db3750 commit 4e65750
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions tracing-opentelemetry/src/subscriber.rs
Expand Up @@ -554,13 +554,23 @@ where
let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
#[cfg(not(feature = "tracing-log"))]
let meta = event.metadata();

let target = Key::new("target");

#[cfg(feature = "tracing-log")]
let target = if normalized_meta.is_some() {
target.string(meta.target().to_owned())
} else {
target.string(event.metadata().target())
};

#[cfg(not(feature = "tracing-log"))]
let target = target.string(meta.target());

let mut otel_event = otel::Event::new(
String::new(),
SystemTime::now(),
vec![
Key::new("level").string(meta.level().to_string()),
Key::new("target").string(meta.target().to_string()),
],
vec![Key::new("level").string(meta.level().as_str()), target],
0,
);
event.record(&mut SpanEventVisitor(&mut otel_event));
Expand Down

0 comments on commit 4e65750

Please sign in to comment.