Skip to content

impl(o11y-tracing): add opentelemetry dependencies and HeaderInjector#4980

Merged
westarle merged 7 commits intogoogleapis:mainfrom
westarle:trace-propagation-deps
Mar 12, 2026
Merged

impl(o11y-tracing): add opentelemetry dependencies and HeaderInjector#4980
westarle merged 7 commits intogoogleapis:mainfrom
westarle:trace-propagation-deps

Conversation

@westarle
Copy link
Contributor

No description provided.

@westarle westarle force-pushed the trace-propagation-deps branch from 5649b5d to df4f4cd Compare March 10, 2026 20:46
@codecov
Copy link

codecov bot commented Mar 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.81%. Comparing base (40581e2) to head (d9e8e84).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4980   +/-   ##
=======================================
  Coverage   92.80%   92.81%           
=======================================
  Files         224      225    +1     
  Lines        8656     8665    +9     
=======================================
+ Hits         8033     8042    +9     
  Misses        623      623           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@westarle westarle force-pushed the trace-propagation-deps branch 4 times, most recently from 230a7cc to 060718e Compare March 11, 2026 15:06
@westarle westarle force-pushed the trace-propagation-deps branch 3 times, most recently from ecf1086 to 378d2dd Compare March 12, 2026 18:29
@westarle westarle force-pushed the trace-propagation-deps branch from 378d2dd to 4153ca6 Compare March 12, 2026 19:12
@westarle westarle marked this pull request as ready for review March 12, 2026 19:37
@westarle westarle requested a review from a team as a code owner March 12, 2026 19:37
@westarle westarle requested a review from haphungw March 12, 2026 19:38

impl<'a> opentelemetry::propagation::Injector for HeaderInjector<'a> {
fn set(&mut self, key: &str, value: String) {
if let Ok(name) = http::header::HeaderName::from_bytes(key.as_bytes()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to the module as use http::header::HeaderName.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


impl<'a> opentelemetry::propagation::Injector for HeaderInjector<'a> {
fn set(&mut self, key: &str, value: String) {
if let Ok(name) = http::header::HeaderName::from_bytes(key.as_bytes()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, done!

// If the tracing span doesn't have a valid trace ID (e.g., the user isn't
// using the tracing_opentelemetry subscriber bridge), fall back to the global
// OTel context (for pure opentelemetry_sdk users).
use opentelemetry::trace::TraceContextExt;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move to the module

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// OTel context (for pure opentelemetry_sdk users).
use opentelemetry::trace::TraceContextExt;
if !context.span().span_context().is_valid() {
context = opentelemetry::Context::current();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a use declaration at the module level.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +53 to +54
let propagator = opentelemetry_sdk::propagation::TraceContextPropagator::new();
use opentelemetry::propagation::TextMapPropagator;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After several refactors I convinced myself that use declarations work better in practice that fully qualified names. And the Google Style Guide recommends them too (if that convinces you).

Comment on lines +133 to +140
// 4. Verify the traceparent header was successfully injected
assert!(
headers.contains_key("traceparent"),
"Headers: {:?}",
headers
);
let traceparent = headers.get("traceparent").unwrap().to_str().unwrap();
assert!(traceparent.starts_with("00-"));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see below, these assertions can be simplified with matches!()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +110 to +120
#[test]
fn test_inject_context_success() {
// 1. Setup tracing with OpenTelemetry layer
let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder().build();
use opentelemetry::trace::TracerProvider as _;
let tracer = tracer_provider.tracer("test");

use tracing_subscriber::layer::SubscriberExt;
let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);
let subscriber = tracing_subscriber::registry().with(telemetry);
let dispatcher = tracing::Dispatch::new(subscriber);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can save yourself explanations with a helper function:

Suggested change
#[test]
fn test_inject_context_success() {
// 1. Setup tracing with OpenTelemetry layer
let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder().build();
use opentelemetry::trace::TracerProvider as _;
let tracer = tracer_provider.tracer("test");
use tracing_subscriber::layer::SubscriberExt;
let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);
let subscriber = tracing_subscriber::registry().with(telemetry);
let dispatcher = tracing::Dispatch::new(subscriber);
fn set_up_otel_and_tracing() -> Dispatch {
let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder().build();
use opentelemetry::trace::TracerProvider as _;
let tracer = tracer_provider.tracer("test");
use tracing_subscriber::layer::SubscriberExt;
let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);
let subscriber = tracing_subscriber::registry().with(telemetry);
tracing::Dispatch::new(subscriber)
}
#[test]
fn inject_context_success() {
let dispatch = set_up_otel_and_tracing();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, this is much better.

use opentelemetry::propagation::Injector;

#[test]
fn test_injector_valid_headers() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test_ prefix is not idiomatic in Rust.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


impl<'a> opentelemetry::propagation::Injector for HeaderInjector<'a> {
fn set(&mut self, key: &str, value: String) {
if let Ok(name) = http::header::HeaderName::from_bytes(key.as_bytes()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can write:

Suggested change
if let Ok(name) = http::header::HeaderName::from_bytes(key.as_bytes()) {
if let (Ok(key), Ok(value)) = (HeaderName::from_str(key), HeaderValue::from_str(&value)) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, looks much better this way!

// Invalid characters in header key
injector.set("invalid key\n", "value".to_string());

assert!(headers.is_empty());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert!(headers.is_empty());
assert!(headers.is_empty(), "{headers:?}");

In general, assert!(expr); is typically too little context to debug things.

@westarle westarle enabled auto-merge (squash) March 12, 2026 22:03
@westarle westarle merged commit 4e48dac into googleapis:main Mar 12, 2026
35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants