1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
//! # AWS X-Ray ID Generator //! //! Generates OpenTelemetry formatted `TraceId`'s and `SpanId`'s. The `TraceId`'s are generated so //! they can be backed out into X-Ray format by the [AWS X-Ray Exporter][xray-exporter] in the //! [OpenTelemetry Collector][otel-collector]. //! //! ## Trace ID Format //! //! A `trace_id` consists of three numbers separated by hyphens. For example, `1-58406520-a006649127e371903a2de979`. //! This includes: //! //! * The version number, that is, 1. //! * The time of the original request, in Unix epoch time, in 8 hexadecimal digits. //! * For example, 10:00AM December 1st, 2016 PST in epoch time is 1480615200 seconds, or 58406520 in hexadecimal digits. //! * A 96-bit identifier for the trace, globally unique, in 24 hexadecimal digits. //! //! See the [AWS X-Ray Documentation][xray-trace-id] for more details. //! //! ## Example //! //! ``` //! use opentelemetry::api::trace::NoopSpanExporter; //! use opentelemetry::sdk::trace::{Config, TracerProvider, XrayIdGenerator}; //! //! let _provider: TracerProvider = TracerProvider::builder() //! .with_simple_exporter(NoopSpanExporter::new()) //! .with_config(Config { //! id_generator: Box::new(XrayIdGenerator::default()), //! ..Default::default() //! }) //! .build(); //! ``` //! //! [otel-collector]: https://github.com/open-telemetry/opentelemetry-collector-contrib#opentelemetry-collector-contrib //! [xray-exporter]: https://godoc.org/github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsxrayexporter //! [xray-trace-id]: https://docs.aws.amazon.com/xray/latest/devguide/xray-api-sendingdata.html#xray-api-traceids use crate::api::trace::{IdGenerator, SpanId, TraceId}; use crate::sdk; use std::time::{Duration, SystemTime, UNIX_EPOCH}; /// Generates AWS X-Ray compliant Trace and Span ids. #[derive(Debug, Default)] pub struct XrayIdGenerator { sdk_default_generator: sdk::trace::IdGenerator, } impl IdGenerator for XrayIdGenerator { /// Generates a new `TraceId` that can be converted to an X-Ray Trace ID fn new_trace_id(&self) -> TraceId { let mut default_trace_id: String = format!( "{:024x}", self.sdk_default_generator.new_trace_id().to_u128() ); default_trace_id.truncate(24); let epoch_time_seconds: u64 = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap_or_else(|_| Duration::from_secs(0)) .as_secs(); TraceId::from_hex(format!("{:08x}{}", epoch_time_seconds, default_trace_id).as_str()) } /// Generates a new `SpanId` that can be converted to an X-Ray Segment ID fn new_span_id(&self) -> SpanId { self.sdk_default_generator.new_span_id() } } #[cfg(test)] mod tests { use super::*; use std::thread::sleep; #[test] fn test_trace_id_generation() { let before: u64 = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_secs(); sleep(Duration::from_secs(1)); let generator: XrayIdGenerator = XrayIdGenerator::default(); let trace_id: TraceId = generator.new_trace_id(); sleep(Duration::from_secs(1)); let after: u64 = SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_secs(); let trace_as_hex: String = format!("{:032x}", trace_id.to_u128()); let (timestamp, _xray_id) = trace_as_hex.split_at(8_usize); let trace_time: u64 = u64::from_str_radix(timestamp, 16).unwrap(); assert!(before <= trace_time); assert!(after >= trace_time); } }