diff --git a/tracing-core/src/span.rs b/tracing-core/src/span.rs index 1cb228d38d..7deb7c12df 100644 --- a/tracing-core/src/span.rs +++ b/tracing-core/src/span.rs @@ -195,6 +195,12 @@ impl<'a> Attributes<'a> { pub fn is_empty(&self) -> bool { self.values.is_empty() } + + /// Returns the number of fields in this `Attributes`. + #[inline] + pub fn len(&self) -> usize { + self.values.field_set().len() + } } // ===== impl Record ===== diff --git a/tracing-opentelemetry/src/subscriber.rs b/tracing-opentelemetry/src/subscriber.rs index cb2b7aa4ce..3ae4b720ec 100644 --- a/tracing-opentelemetry/src/subscriber.rs +++ b/tracing-opentelemetry/src/subscriber.rs @@ -171,17 +171,20 @@ impl<'a> field::Visit for SpanEventVisitor<'a> { struct SpanAttributeVisitor<'a>(&'a mut otel::SpanBuilder); +impl<'a> SpanAttributeVisitor<'a> { + fn record(&mut self, attribute: KeyValue) { + debug_assert!(self.0.attributes.is_some()); + self.0.attributes.as_mut().map(|v| v.push(attribute)); + } +} + impl<'a> field::Visit for SpanAttributeVisitor<'a> { /// Set attributes on the underlying OpenTelemetry [`Span`] from `bool` values. /// /// [`Span`]: opentelemetry::trace::Span fn record_bool(&mut self, field: &field::Field, value: bool) { let attribute = KeyValue::new(field.name(), value); - if let Some(attributes) = &mut self.0.attributes { - attributes.push(attribute); - } else { - self.0.attributes = Some(vec![attribute]); - } + self.record(attribute); } /// Set attributes on the underlying OpenTelemetry [`Span`] from `i64` values. @@ -189,11 +192,7 @@ impl<'a> field::Visit for SpanAttributeVisitor<'a> { /// [`Span`]: opentelemetry::trace::Span fn record_i64(&mut self, field: &field::Field, value: i64) { let attribute = KeyValue::new(field.name(), value); - if let Some(attributes) = &mut self.0.attributes { - attributes.push(attribute); - } else { - self.0.attributes = Some(vec![attribute]); - } + self.record(attribute); } /// Set attributes on the underlying OpenTelemetry [`Span`] from `&str` values. @@ -206,11 +205,7 @@ impl<'a> field::Visit for SpanAttributeVisitor<'a> { self.0.span_kind = str_to_span_kind(value); } else { let attribute = KeyValue::new(field.name(), value.to_string()); - if let Some(attributes) = &mut self.0.attributes { - attributes.push(attribute); - } else { - self.0.attributes = Some(vec![attribute]); - } + self.record(attribute); } } @@ -225,11 +220,7 @@ impl<'a> field::Visit for SpanAttributeVisitor<'a> { self.0.span_kind = str_to_span_kind(&format!("{:?}", value)); } else { let attribute = Key::new(field.name()).string(format!("{:?}", value)); - if let Some(attributes) = &mut self.0.attributes { - attributes.push(attribute); - } else { - self.0.attributes = Some(vec![attribute]); - } + self.record(attribute); } } } @@ -418,6 +409,7 @@ where builder.trace_id = Some(self.tracer.new_trace_id()); } + builder.attributes = Some(Vec::with_capacity(attrs.len())); attrs.record(&mut SpanAttributeVisitor(&mut builder)); extensions.insert(builder); }