Skip to content

Commit

Permalink
add aws xray id generator (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
sreeo authored Feb 20, 2024
1 parent c40c650 commit c4673aa
Show file tree
Hide file tree
Showing 7 changed files with 490 additions and 393 deletions.
1 change: 1 addition & 0 deletions opentelemetry-aws/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

- reduce `tokio` feature requirements #750
- Update to opentelemetry v0.18.0
- Move Xray IdGenerator from `opentelemetry-rust` to `opentelemetry-aws` [#33](https://github.com/open-telemetry/opentelemetry-rust-contrib/pull/33)

### Fixed

Expand Down
3 changes: 2 additions & 1 deletion opentelemetry-aws/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ rustdoc-args = ["--cfg", "docsrs"]

[features]
default = ["trace"]
trace = ["opentelemetry/trace"]
trace = ["opentelemetry/trace", "opentelemetry_sdk"]

[dependencies]
once_cell = "1.12"
opentelemetry = { version = "0.21" }
opentelemetry_sdk = { version = "0.21", optional = true }

[dev-dependencies]
opentelemetry_sdk = { version = "0.21", features = ["trace", "testing"] }
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-aws/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ to AWS's telemetry platform.

## Supported component

Currently, this crate only supports `XRay` propagator. Contributions are welcome.
Currently, this crate only supports `XRay` propagator and `Xray` ID Generator. Contributions are welcome.

[`OpenTelemetry`]: https://crates.io/crates/opentelemetry
392 changes: 1 addition & 391 deletions opentelemetry-aws/src/lib.rs

Large diffs are not rendered by default.

95 changes: 95 additions & 0 deletions opentelemetry-aws/src/trace/id_generator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use opentelemetry::trace::{SpanId, TraceId};
use opentelemetry_sdk::trace::{IdGenerator, RandomIdGenerator};
use std::time::{Duration, UNIX_EPOCH};

/// Generates AWS X-Ray compliant Trace and Span ids.
///
/// 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::trace::{TraceId};
/// use opentelemetry_sdk::trace::{self, IdGenerator, TracerProvider};
/// use opentelemetry_aws::trace::XrayIdGenerator;
/// let _provider: TracerProvider = TracerProvider::builder()
/// .with_config(trace::config().with_id_generator(XrayIdGenerator::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
#[derive(Debug, Default)]
pub struct XrayIdGenerator {
sdk_default_generator: RandomIdGenerator,
}

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());

default_trace_id.truncate(24);

let epoch_time_seconds: u64 = opentelemetry::time::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())
.unwrap_or(TraceId::INVALID)
}

/// 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 = opentelemetry::time::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 = opentelemetry::time::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();

let trace_as_hex = trace_id.to_string();
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);
}
}
8 changes: 8 additions & 0 deletions opentelemetry-aws/src/trace/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pub mod id_generator;
pub mod xray_propagator;

#[cfg(feature = "trace")]
pub use xray_propagator::XrayPropagator;

#[cfg(feature = "trace")]
pub use id_generator::XrayIdGenerator;
Loading

0 comments on commit c4673aa

Please sign in to comment.