Add (optional) OpenTelemetry + Xray integration (#95) (#96)

This introduces all the necessary code to be able to send traces to
AWS Xray via `tracing-opentelemetry`. It can be optionally enabled
using the `xray` feature defined on this crate.

Also update the README.md with instructions on how to enable and use
this.
This commit is contained in:
Bryan Garza
2022-05-18 09:13:19 -07:00
committed by GitHub
parent 4b4ecf0310
commit 6cd697afe9
4 changed files with 106 additions and 6 deletions

View File

@@ -12,11 +12,27 @@ use structopt::StructOpt;
use tokio::net::TcpListener;
use tokio::signal;
#[cfg(feature = "otel")]
// To be able to set the XrayPropagator
use opentelemetry::global;
#[cfg(feature = "otel")]
// To configure certain options such as sampling rate
use opentelemetry::sdk::trace as sdktrace;
#[cfg(feature = "otel")]
// For passing along the same XrayId across services
use opentelemetry_aws::trace::XrayPropagator;
#[cfg(feature = "otel")]
// To be able to pass along the XrayId across services
#[cfg(feature = "otel")]
// The `Ext` traits are to allow the Registry to accept the
// OpenTelemetry-specific types (such as `OpenTelemetryLayer`)
use tracing_subscriber::{
fmt, layer::SubscriberExt, util::SubscriberInitExt, util::TryInitError, EnvFilter,
};
#[tokio::main]
pub async fn main() -> mini_redis::Result<()> {
// enable logging
// see https://docs.rs/tracing for more info
tracing_subscriber::fmt::try_init()?;
set_up_logging()?;
let cli = Cli::from_args();
let port = cli.port.as_deref().unwrap_or(DEFAULT_PORT);
@@ -35,3 +51,46 @@ struct Cli {
#[structopt(name = "port", long = "--port")]
port: Option<String>,
}
#[cfg(not(feature = "otel"))]
fn set_up_logging() -> mini_redis::Result<()> {
// See https://docs.rs/tracing for more info
tracing_subscriber::fmt::try_init()
}
#[cfg(feature = "otel")]
fn set_up_logging() -> Result<(), TryInitError> {
// Set the global propagator to X-Ray propagator
// Note: If you need to pass the x-amzn-trace-id across services in the same trace,
// you will need this line. However, this requires additional code not pictured here.
// For a full example using hyper, see:
// https://github.com/open-telemetry/opentelemetry-rust/blob/main/examples/aws-xray/src/server.rs#L14-L26
global::set_text_map_propagator(XrayPropagator::default());
let tracer = opentelemetry_otlp::new_pipeline()
.tracing()
.with_exporter(opentelemetry_otlp::new_exporter().tonic())
.with_trace_config(
sdktrace::config()
.with_sampler(sdktrace::Sampler::AlwaysOn)
// Needed in order to convert the trace IDs into an Xray-compatible format
.with_id_generator(sdktrace::XrayIdGenerator::default()),
)
.install_simple()
.expect("Unable to initialize OtlpPipeline");
// Create a tracing layer with the configured tracer
let opentelemetry = tracing_opentelemetry::layer().with_tracer(tracer);
// Parse an `EnvFilter` configuration from the `RUST_LOG`
// environment variable.
let filter = EnvFilter::from_default_env();
// Use the tracing subscriber `Registry`, or any other subscriber
// that impls `LookupSpan`
tracing_subscriber::registry()
.with(opentelemetry)
.with(filter)
.with(fmt::Layer::default())
.try_init()
}