From ab828d5b84928c352a89fdb1d0c4946bdfefe9de Mon Sep 17 00:00:00 2001 From: mlehurau Date: Wed, 28 Jul 2021 17:05:39 -0400 Subject: [PATCH 1/3] opentelemetry: Add extension to link spans Discussed in #1121, the purpose of adding the `add_link` extension is to allow adding a link to a propagated span and/or a closed span. --- tracing-opentelemetry/src/span_ext.rs | 56 ++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/tracing-opentelemetry/src/span_ext.rs b/tracing-opentelemetry/src/span_ext.rs index 5b8ac7a02c..00d7bc14b6 100644 --- a/tracing-opentelemetry/src/span_ext.rs +++ b/tracing-opentelemetry/src/span_ext.rs @@ -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::() { + 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()); + if let Some(ref mut links) = builder.links { + links.push(follows_link); + } else { + builder.links = Some(vec![follows_link]); + } + } + }); + } + }); + } + fn context(&self) -> Context { let mut cx = None; self.with_collector(|(id, collector)| { From e8d3cce35e5fa5f8156023ccdb106f7c34cd2fa5 Mon Sep 17 00:00:00 2001 From: Max Lehuraux <72396955+LehMaxence@users.noreply.github.com> Date: Wed, 18 Aug 2021 15:43:32 -0400 Subject: [PATCH 2/3] Improve syntax Co-authored-by: Eliza Weisman --- tracing-opentelemetry/src/span_ext.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tracing-opentelemetry/src/span_ext.rs b/tracing-opentelemetry/src/span_ext.rs index 00d7bc14b6..6049b97ce4 100644 --- a/tracing-opentelemetry/src/span_ext.rs +++ b/tracing-opentelemetry/src/span_ext.rs @@ -129,10 +129,10 @@ impl OpenTelemetrySpanExt for tracing::Span { let follows_context = cx.span().span_context().clone(); let follows_link = opentelemetry::trace::Link::new(follows_context, Vec::new()); - if let Some(ref mut links) = builder.links { - links.push(follows_link); - } else { - builder.links = Some(vec![follows_link]); + builder + .links + .get_or_insert_with(|| Vec::with_capacity(1)) + .push(follows_link); } } }); From aafb661a06ee15e8c37498e252ef5e79dd2f423a Mon Sep 17 00:00:00 2001 From: mlehurau Date: Fri, 20 Aug 2021 11:01:35 -0400 Subject: [PATCH 3/3] Rework `add_link` Implement OpenTelemetry API specification for links --- tracing-opentelemetry/src/span_ext.rs | 67 ++++++++++++++++----------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/tracing-opentelemetry/src/span_ext.rs b/tracing-opentelemetry/src/span_ext.rs index 6049b97ce4..77448b0408 100644 --- a/tracing-opentelemetry/src/span_ext.rs +++ b/tracing-opentelemetry/src/span_ext.rs @@ -1,5 +1,5 @@ use crate::subscriber::WithContext; -use opentelemetry::{trace::TraceContextExt, Context}; +use opentelemetry::{trace::SpanContext, Context, KeyValue}; /// Utility functions to allow tracing [`Span`]s to accept and return /// [OpenTelemetry] [`Context`]s. @@ -43,9 +43,9 @@ pub trait OpenTelemetrySpanExt { fn set_parent(&self, cx: Context); /// Associates `self` with a given OpenTelemetry trace, using the provided - /// followed span [`Context`]. + /// followed span [`SpanContext`]. /// - /// [`Context`]: opentelemetry::Context + /// [`SpanContext`]: opentelemetry::trace::SpanContext /// /// # Examples /// @@ -62,19 +62,29 @@ pub trait OpenTelemetrySpanExt { /// // 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); + /// // Extract otel context of linked span via the chosen propagator + /// let linked_span_otel_context = propagator.extract(&carrier); + /// + /// // Extract the linked span context from the otel context + /// let linked_span_context = linked_span_otel_context.span().span_context().clone(); /// /// // 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()); + /// // Assign linked trace from external context + /// app_root.add_link(linked_span_context); /// /// // Or if the current span has been created elsewhere: - /// Span::current().add_link(parent_context); + /// let linked_span_context = linked_span_otel_context.span().span_context().clone(); + /// Span::current().add_link(linked_span_context); /// ``` - fn add_link(&self, cx: Context); + fn add_link(&self, cx: SpanContext); + + /// Associates `self` with a given OpenTelemetry trace, using the provided + /// followed span [`SpanContext`] and attributes. + /// + /// [`SpanContext`]: opentelemetry::trace::SpanContext + fn add_link_with_attributes(&self, cx: SpanContext, attributes: Vec); /// Extracts an OpenTelemetry [`Context`] from `self`. /// @@ -120,24 +130,29 @@ 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::() { - 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()); - builder - .links - .get_or_insert_with(|| Vec::with_capacity(1)) - .push(follows_link); + fn add_link(&self, cx: SpanContext) { + self.add_link_with_attributes(cx, Vec::new()) + } + + fn add_link_with_attributes(&self, cx: SpanContext, attributes: Vec) { + if cx.is_valid() { + let mut cx = Some(cx); + let mut att = Some(attributes); + self.with_collector(move |(id, collector)| { + if let Some(get_context) = collector.downcast_ref::() { + get_context.with_context(collector, id, move |builder, _tracer| { + if let Some(cx) = cx.take() { + let attr = att.take().unwrap_or_default(); + let follows_link = opentelemetry::trace::Link::new(cx, attr); + builder + .links + .get_or_insert_with(|| Vec::with_capacity(1)) + .push(follows_link); } - } - }); - } - }); + }); + } + }); + } } fn context(&self) -> Context {