Skip to content

Commit 7b77d33

Browse files
authored
Add set_attribute function (#34)
* Adds a function `set_attribute` to `OpenTelemetrySpanExt` to allow setting attributes directly on the OpenTelemetry `SpanBuilder`. This allows users to set more than the tracing maximum of 32 fields. There was a workaround I came up with without using the function involving wrapping the `Registry` in an Arc and accessing `OtelData` directly, but that led to [this bug in tracing-subscriber](tokio-rs/tracing#2668).
1 parent f5f898b commit 7b77d33

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

src/span_ext.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::layer::WithContext;
2-
use opentelemetry::{trace::SpanContext, Context, KeyValue};
2+
use opentelemetry::{trace::SpanContext, Context, Key, KeyValue, Value};
33

44
/// Utility functions to allow tracing [`Span`]s to accept and return
55
/// [OpenTelemetry] [`Context`]s.
@@ -114,6 +114,25 @@ pub trait OpenTelemetrySpanExt {
114114
/// make_request(Span::current().context())
115115
/// ```
116116
fn context(&self) -> Context;
117+
118+
/// Sets an OpenTelemetry attribute directly for this span, bypassing `tracing`.
119+
/// If fields set here conflict with `tracing` fields, the `tracing` fields will supersede fields set with `set_attribute`.
120+
/// This allows for more than 32 fields.
121+
///
122+
/// # Examples
123+
///
124+
/// ```rust
125+
/// use opentelemetry::Context;
126+
/// use tracing_opentelemetry::OpenTelemetrySpanExt;
127+
/// use tracing::Span;
128+
///
129+
/// // Generate a tracing span as usual
130+
/// let app_root = tracing::span!(tracing::Level::INFO, "app_start");
131+
///
132+
/// // Set the `http.request.header.x_forwarded_for` attribute to `example`.
133+
/// app_root.set_attribute("http.request.header.x_forwarded_for", "example");
134+
/// ```
135+
fn set_attribute(&self, key: impl Into<Key>, value: impl Into<Value>);
117136
}
118137

119138
impl OpenTelemetrySpanExt for tracing::Span {
@@ -168,4 +187,24 @@ impl OpenTelemetrySpanExt for tracing::Span {
168187

169188
cx.unwrap_or_default()
170189
}
190+
191+
fn set_attribute(&self, key: impl Into<Key>, value: impl Into<Value>) {
192+
self.with_subscriber(move |(id, subscriber)| {
193+
if let Some(get_context) = subscriber.downcast_ref::<WithContext>() {
194+
let mut key = Some(key.into());
195+
let mut value = Some(value.into());
196+
get_context.with_context(subscriber, id, move |builder, _| {
197+
if builder.builder.attributes.is_none() {
198+
builder.builder.attributes = Some(Default::default());
199+
}
200+
builder
201+
.builder
202+
.attributes
203+
.as_mut()
204+
.unwrap()
205+
.insert(key.take().unwrap(), value.take().unwrap());
206+
})
207+
}
208+
});
209+
}
171210
}

0 commit comments

Comments
 (0)