mirror of
https://github.com/tokio-rs/tracing.git
synced 2025-10-01 06:50:49 +00:00
opentelemetry: improve performance by pre-determining attribute length (#1327)
The `SpanBuilder` uses `Vec` to store span's fields. However, the current solution can be slightly improved by preparing the capacity of `Vec` in advance, this can reduce a few memory reallocations. Since the max number of tracing's span fields is 32, we can replace `Vec` with `SmallVec` to further improve performance. Maybe, we should add a new feature (such as `smallvec`?) to the `opentelemetry` crate. Well, this should be discussed in the `opentelemetry` repo. Co-authored-by: Eliza Weisman <eliza@buoyant.io>
This commit is contained in:
parent
ab6207621d
commit
29291af1fd
@ -177,29 +177,28 @@ impl<'a> field::Visit for SpanEventVisitor<'a> {
|
|||||||
|
|
||||||
struct SpanAttributeVisitor<'a>(&'a mut otel::SpanBuilder);
|
struct SpanAttributeVisitor<'a>(&'a mut otel::SpanBuilder);
|
||||||
|
|
||||||
|
impl<'a> SpanAttributeVisitor<'a> {
|
||||||
|
fn record(&mut self, attribute: KeyValue) {
|
||||||
|
debug_assert!(self.0.attributes.is_some());
|
||||||
|
if let Some(v) = self.0.attributes.as_mut() {
|
||||||
|
v.push(attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> field::Visit for SpanAttributeVisitor<'a> {
|
impl<'a> field::Visit for SpanAttributeVisitor<'a> {
|
||||||
/// Set attributes on the underlying OpenTelemetry [`Span`] from `bool` values.
|
/// Set attributes on the underlying OpenTelemetry [`Span`] from `bool` values.
|
||||||
///
|
///
|
||||||
/// [`Span`]: opentelemetry::trace::Span
|
/// [`Span`]: opentelemetry::trace::Span
|
||||||
fn record_bool(&mut self, field: &field::Field, value: bool) {
|
fn record_bool(&mut self, field: &field::Field, value: bool) {
|
||||||
let attribute = KeyValue::new(field.name(), value);
|
self.record(KeyValue::new(field.name(), value));
|
||||||
if let Some(attributes) = &mut self.0.attributes {
|
|
||||||
attributes.push(attribute);
|
|
||||||
} else {
|
|
||||||
self.0.attributes = Some(vec![attribute]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set attributes on the underlying OpenTelemetry [`Span`] from `i64` values.
|
/// Set attributes on the underlying OpenTelemetry [`Span`] from `i64` values.
|
||||||
///
|
///
|
||||||
/// [`Span`]: opentelemetry::trace::Span
|
/// [`Span`]: opentelemetry::trace::Span
|
||||||
fn record_i64(&mut self, field: &field::Field, value: i64) {
|
fn record_i64(&mut self, field: &field::Field, value: i64) {
|
||||||
let attribute = KeyValue::new(field.name(), value);
|
self.record(KeyValue::new(field.name(), value));
|
||||||
if let Some(attributes) = &mut self.0.attributes {
|
|
||||||
attributes.push(attribute);
|
|
||||||
} else {
|
|
||||||
self.0.attributes = Some(vec![attribute]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set attributes on the underlying OpenTelemetry [`Span`] from `&str` values.
|
/// Set attributes on the underlying OpenTelemetry [`Span`] from `&str` values.
|
||||||
@ -211,14 +210,7 @@ impl<'a> field::Visit for SpanAttributeVisitor<'a> {
|
|||||||
SPAN_KIND_FIELD => self.0.span_kind = str_to_span_kind(value),
|
SPAN_KIND_FIELD => self.0.span_kind = str_to_span_kind(value),
|
||||||
SPAN_STATUS_CODE_FIELD => self.0.status_code = str_to_status_code(value),
|
SPAN_STATUS_CODE_FIELD => self.0.status_code = str_to_status_code(value),
|
||||||
SPAN_STATUS_MESSAGE_FIELD => self.0.status_message = Some(value.to_owned().into()),
|
SPAN_STATUS_MESSAGE_FIELD => self.0.status_message = Some(value.to_owned().into()),
|
||||||
_ => {
|
_ => self.record(KeyValue::new(field.name(), value.to_string())),
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,14 +228,7 @@ impl<'a> field::Visit for SpanAttributeVisitor<'a> {
|
|||||||
SPAN_STATUS_MESSAGE_FIELD => {
|
SPAN_STATUS_MESSAGE_FIELD => {
|
||||||
self.0.status_message = Some(format!("{:?}", value).into())
|
self.0.status_message = Some(format!("{:?}", value).into())
|
||||||
}
|
}
|
||||||
_ => {
|
_ => self.record(Key::new(field.name()).string(format!("{:?}", value))),
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -421,7 +406,9 @@ where
|
|||||||
builder.trace_id = Some(self.tracer.new_trace_id());
|
builder.trace_id = Some(self.tracer.new_trace_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
let builder_attrs = builder.attributes.get_or_insert(Vec::new());
|
let builder_attrs = builder
|
||||||
|
.attributes
|
||||||
|
.get_or_insert(Vec::with_capacity(attrs.fields().len() + 3));
|
||||||
|
|
||||||
let meta = attrs.metadata();
|
let meta = attrs.metadata();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user