use opentelemetry::global;
use opentelemetry::trace::{TraceContextExt, Tracer};
use opentelemetry::KeyValue;
use opentelemetry_otlp::{Protocol, SpanExporter, WithExportConfig, WithHttpConfig};
use opentelemetry_sdk::trace::SdkTracerProvider;
use otlp_stdout_client::StdoutClient;
fn init_tracer_provider() -> Result<SdkTracerProvider, Box<dyn std::error::Error>> {
let protocol = match std::env::var("OTEL_EXPORTER_OTLP_PROTOCOL")
.unwrap_or_default()
.to_lowercase()
.as_str()
{
"http/protobuf" => Protocol::HttpBinary,
"http/json" | "" => Protocol::HttpJson,
unsupported => {
eprintln!(
"Warning: OTEL_EXPORTER_OTLP_PROTOCOL value '{}' is not supported. Defaulting to HTTP JSON.",
unsupported
);
Protocol::HttpJson
}
};
let exporter = SpanExporter::builder()
.with_http()
.with_protocol(protocol)
.with_http_client(StdoutClient::default())
.build()?;
let tracer_provider = SdkTracerProvider::builder()
.with_simple_exporter(exporter)
.with_resource(opentelemetry_sdk::Resource::builder().build())
.build();
Ok(tracer_provider)
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let tracer_provider = init_tracer_provider()?;
global::set_tracer_provider(tracer_provider.clone());
let tracer = global::tracer("basic-example");
tracer.in_span("hello_world", |cx| {
cx.span().add_event(
"span_started",
vec![KeyValue::new("message", "Hello from inside the span!")],
);
tracer.in_span("nested_operation", |cx| {
std::thread::sleep(std::time::Duration::from_millis(100));
cx.span().add_event(
"operation_progress",
vec![
KeyValue::new("message", "Doing some work in a nested span..."),
KeyValue::new("duration_ms", 100),
],
);
});
});
let _ = tracer_provider.shutdown();
Ok(())
}