diff --git a/traces/Cargo.toml b/traces/Cargo.toml index 33c7a7e..0046443 100644 --- a/traces/Cargo.toml +++ b/traces/Cargo.toml @@ -10,4 +10,4 @@ opentelemetry-otlp = { version = "0.11.0", features = ["tonic", "tls", "tls-root tracing = { version = "0.1.37" } serde = { version = "1.0.152", features = ["derive"] } tonic = { version = "0.8.1", features = ["tls"] } -tokio = { version = "1.24.2", features = ["default"] } \ No newline at end of file +tokio = { version = "1.25.0", features = ["default"] } \ No newline at end of file diff --git a/traces/src/amqp.rs b/traces/src/amqp.rs deleted file mode 100644 index 65b1383..0000000 --- a/traces/src/amqp.rs +++ /dev/null @@ -1,93 +0,0 @@ -use opentelemetry::{ - global, - global::{BoxedSpan, BoxedTracer}, - trace::{ - Span, SpanContext, SpanId, SpanKind, TraceContextExt, TraceFlags, TraceId, TraceState, - Tracer, - }, - Context, -}; -use std::borrow::Cow; - -const TRACE_VERSION: u8 = 0; - -pub struct Traceparent { - pub trace_id: TraceId, - pub span_id: SpanId, - pub trace_flags: TraceFlags, -} - -///traceparent is compos from {trace-version}-{trace-id}-{parent-id}-{trace-flags} -impl Traceparent { - pub fn from_string(traceparent: &str) -> Traceparent { - if traceparent.is_empty() { - return Traceparent::new_empty(); - } - - let splitted: Vec<&str> = traceparent.split("-").collect(); - - if splitted.len() <= 3 { - return Traceparent::new_empty(); - } - - let trace_id = TraceId::from_hex(&splitted[1].to_string()).unwrap(); - let span_id = SpanId::from_hex(&splitted[2].to_string()).unwrap(); - let trace_flags = TraceFlags::new(splitted[3].as_bytes()[0]); - - Traceparent { - trace_id, - span_id, - trace_flags, - } - } - - pub fn string_from_ctx(ctx: &Context) -> String { - let trace_id = ctx.get::().unwrap(); - let parent_id = ctx.get::().unwrap(); - let trace_flags = ctx.get::().unwrap(); - - format!( - "{:02x}-{:032x}-{:016x}-{:02x}", - TRACE_VERSION, trace_id, parent_id, trace_flags - ) - } - - fn new_empty() -> Traceparent { - let tracer = global::tracer("empty"); - - let span = tracer - .span_builder("empty") - .with_kind(SpanKind::Consumer) - .start(&tracer); - - let span_ctx = span.span_context(); - - Traceparent { - trace_id: span_ctx.clone().trace_id(), - span_id: span_ctx.clone().span_id(), - trace_flags: span_ctx.clone().trace_flags(), - } - } -} - -pub fn get_span(tracer: &BoxedTracer, traceparent: &str, span_name: &str) -> (Context, BoxedSpan) { - let traceparent = Traceparent::from_string(traceparent); - - let ctx = Context::new().with_remote_span_context(SpanContext::new( - traceparent.trace_id, - traceparent.span_id, - traceparent.trace_flags, - true, - TraceState::default(), - )); - - let span = tracer - .span_builder(Cow::from(span_name.to_owned())) - .with_kind(SpanKind::Consumer) - .start_with_context(tracer, &ctx); - - let ctx = ctx.with_value(traceparent.trace_id); - let ctx = ctx.with_value(traceparent.span_id); - - (ctx.with_value(traceparent.trace_flags), span) -} diff --git a/traces/src/grpc.rs b/traces/src/grpc.rs new file mode 100644 index 0000000..47bd26c --- /dev/null +++ b/traces/src/grpc.rs @@ -0,0 +1,53 @@ +use opentelemetry::{ + global::{self, BoxedSpan, BoxedTracer}, + propagation::{Extractor, Injector}, + trace::Tracer, + Context, +}; + +pub struct ExMetadataMap<'a>(&'a tonic::metadata::MetadataMap); + +impl<'a> Extractor for ExMetadataMap<'a> { + /// Get a value for a key from the MetadataMap. If the value can't be converted to &str, returns None + fn get(&self, key: &str) -> Option<&str> { + self.0.get(key).and_then(|metadata| metadata.to_str().ok()) + } + + /// Collect all the keys from the MetadataMap. + fn keys(&self) -> Vec<&str> { + self.0 + .keys() + .map(|key| match key { + tonic::metadata::KeyRef::Ascii(v) => v.as_str(), + tonic::metadata::KeyRef::Binary(v) => v.as_str(), + }) + .collect::>() + } +} + +pub struct InjMetadataMap<'a>(&'a mut tonic::metadata::MetadataMap); + +impl<'a> Injector for InjMetadataMap<'a> { + /// Set a key and value in the MetadataMap. Does nothing if the key or value are not valid inputs + fn set(&mut self, key: &str, value: String) { + if let Ok(key) = tonic::metadata::MetadataKey::from_bytes(key.as_bytes()) { + if let Ok(val) = tonic::metadata::MetadataValue::try_from(&value) { + self.0.insert(key, val); + } + } + } +} + +pub fn span(meta: &tonic::metadata::MetadataMap, tracer: &BoxedTracer) -> (Context, BoxedSpan) { + let ctx = global::get_text_map_propagator(|prop| prop.extract(&ExMetadataMap(meta))); + + let span = tracer.start_with_context("Processing reply", &ctx); + + (ctx, span) +} + +pub fn inject(ctx: &Context, meta: &mut tonic::metadata::MetadataMap) { + global::get_text_map_propagator(|propagator| { + propagator.inject_context(&ctx, &mut InjMetadataMap(meta)) + }); +} diff --git a/traces/src/lib.rs b/traces/src/lib.rs index aef5994..1d480bb 100644 --- a/traces/src/lib.rs +++ b/traces/src/lib.rs @@ -1,6 +1,4 @@ -///deprecated -pub mod amqp; - +pub mod grpc; pub mod jaeger; pub mod otlp;