From 21eb741b658f858884527ca9d3d4a83f2c0973db Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 9 Feb 2022 11:17:26 -0800 Subject: [PATCH] opentelemetry: allocate fewer strings for recording events (#1917) ## 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`. --- tracing-opentelemetry/src/layer.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tracing-opentelemetry/src/layer.rs b/tracing-opentelemetry/src/layer.rs index 00678bf1a6..20e1053714 100644 --- a/tracing-opentelemetry/src/layer.rs +++ b/tracing-opentelemetry/src/layer.rs @@ -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));