-
Notifications
You must be signed in to change notification settings - Fork 721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
opentelemetry: Add extension to link spans #1516
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,5 +1,5 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use crate::subscriber::WithContext; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use opentelemetry::Context; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
use opentelemetry::{trace::TraceContextExt, Context}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// Utility functions to allow tracing [`Span`]s to accept and return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// [OpenTelemetry] [`Context`]s. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -42,6 +42,40 @@ pub trait OpenTelemetrySpanExt { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fn set_parent(&self, cx: Context); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// Associates `self` with a given OpenTelemetry trace, using the provided | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// followed span [`Context`]. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// [`Context`]: opentelemetry::Context | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// # Examples | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// ```rust | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// use opentelemetry::{propagation::TextMapPropagator, trace::TraceContextExt}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// use opentelemetry::sdk::propagation::TraceContextPropagator; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// use tracing_opentelemetry::OpenTelemetrySpanExt; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// use std::collections::HashMap; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// use tracing::Span; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// // Example carrier, could be a framework header map that impls otel's `Extract`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// let mut carrier = HashMap::new(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// // Propagator can be swapped with b3 propagator, jaeger propagator, etc. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// let propagator = TraceContextPropagator::new(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// // Extract otel parent context via the chosen propagator | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// let parent_context = propagator.extract(&carrier); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// // Generate a tracing span as usual | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// let app_root = tracing::span!(tracing::Level::INFO, "app_start"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// // Assign parent trace from external context | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// app_root.add_link(parent_context.clone()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// // Or if the current span has been created elsewhere: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// Span::current().add_link(parent_context); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fn add_link(&self, cx: Context); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// Extracts an OpenTelemetry [`Context`] from `self`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// [`Context`]: opentelemetry::Context | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -86,6 +120,26 @@ impl OpenTelemetrySpanExt for tracing::Span { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fn add_link(&self, cx: Context) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let mut cx = Some(cx); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.with_collector(move |(id, collector)| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if let Some(get_context) = collector.downcast_ref::<WithContext>() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
get_context.with_context(collector, id, move |builder, _tracer| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if let Some(cx) = cx.take() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let follows_context = cx.span().span_context().clone(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let follows_link = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
opentelemetry::trace::Link::new(follows_context, Vec::new()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I notice this will always create a link with no key-value attributes. Do you think it makes sense to include a separate function like We can always add this in a separate PR, of course. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if let Some(ref mut links) = builder.links { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
links.push(follows_link); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
builder.links = Some(vec![follows_link]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
LehMaxence marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think that if we borrowed the
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fn context(&self) -> Context { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let mut cx = None; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.with_collector(|(id, collector)| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, one other thought. I notice that in the examples, the
Context
parameter always has to be cloned...but in theadd_link
method, we borrow the span from the context, and then clone theSpanContext
from the span...so, afaict, we could just borrow theContext
parameter rather than forcing the user to clone it when calling this method. that might be more efficient, as well?but, on the other hand, existing methods on this trait (e.g.
set_parent
) take theContext
by value, so maybe it's preferable to be consistent? IDK.@jtescher what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to be consistent with
set_parent
, as you notice, but that may not be necessary indeed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, i think there's kind of a tradeoff between consistency and ergonomics (and possibly performance?) here...i'd probably go with taking it by reference, but it's @jtescher's call.
alternatively, should this method just take the
SpanContext
? that way, the user can get it from somewhere other than aContext
...i'm not sure if there's a use-case for that, or not?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method could just take
SpanContext
since links don't care about the wholeContext
.However propagators return
Context
so maybe we need bothfn add_link(&self, cx: SpanContext)
andfn add_link(&self, cx: &Context)
.fn add_link(&self, cx: &Context)
would just get theSpanContext
of theContext
and pass it tofn add_link(&self, cx: SpanContext)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the add_link spec suggests a
SpanContext
directly, while the span creation spec explicitly requires a fullContext
to set a parent so the parameter discrepancy seems intentional.