#![allow(dead_code)]
use crate::telemetry::{
context_with_span, extract_from_headers, init_telemetry, inject_into_headers, metric_attributes,
metric_names, MetricsRecorder, SamplingStrategy, SpanBuilder, TelemetryConfig,
};
use opentelemetry::trace::{Span, SpanKind, Tracer};
use opentelemetry::{global, Context, KeyValue};
use std::collections::HashMap;
pub async fn example_init_default_telemetry() -> Result<(), Box<dyn std::error::Error>> {
let config = TelemetryConfig::new("my-processor")
.with_otlp_endpoint("http://localhost:4317")
.with_service_version("1.0.0")
.with_environment("production");
let providers = init_telemetry(config)?;
providers.shutdown().await?;
Ok(())
}
pub fn example_create_span() {
let span = SpanBuilder::new("process_event")
.with_kind(SpanKind::Internal)
.with_attribute("event.type", "metric")
.with_attribute("event.id", "12345")
.start();
drop(span);
}
pub fn example_nested_spans() {
let tracer = global::tracer("processor");
let parent_span = tracer
.span_builder("parent_operation")
.with_kind(SpanKind::Server)
.start(&tracer);
let parent_context = context_with_span(parent_span);
let _guard = parent_context.attach();
let child_span = tracer
.span_builder("child_operation")
.with_kind(SpanKind::Internal)
.start(&tracer);
drop(child_span);
drop(_guard);
}
pub async fn example_async_context_propagation() {
use crate::telemetry::propagate_context;
let tracer = global::tracer("processor");
let span = tracer
.span_builder("async_operation")
.with_kind(SpanKind::Internal)
.start(&tracer);
let context = context_with_span(span);
let _guard = context.attach();
let handle = tokio::spawn(propagate_context(async {
process_async_work().await;
}));
handle.await.ok();
}
async fn process_async_work() {
}
pub fn example_context_injection_extraction() {
let tracer = global::tracer("processor");
let span_a = tracer
.span_builder("outgoing_request")
.with_kind(SpanKind::Client)
.start(&tracer);
let context_a = context_with_span(span_a);
let mut headers = HashMap::new();
inject_into_headers(&context_a, &mut headers);
let incoming_headers = headers; let context_b = extract_from_headers(&incoming_headers);
let _guard = context_b.attach();
let span_b = tracer
.span_builder("incoming_request")
.with_kind(SpanKind::Server)
.start(&tracer);
drop(span_b);
}
pub fn example_record_metrics() {
let recorder = MetricsRecorder::new()
.with_attribute("service", "processor")
.with_attribute("environment", "production");
recorder.record_counter(
"processor",
metric_names::EVENTS_PROCESSED,
1,
vec![KeyValue::new(metric_attributes::EVENT_TYPE, "metric")],
);
recorder.record_histogram(
"processor",
metric_names::PROCESSING_DURATION,
123.45,
vec![KeyValue::new(metric_attributes::OPERATION_TYPE, "aggregation")],
);
recorder.record_gauge(
"processor",
metric_names::WATERMARK_LAG,
1000,
vec![KeyValue::new(metric_attributes::PARTITION_ID, "0")],
);
}
pub fn example_span_events() {
let tracer = global::tracer("processor");
let mut span = tracer
.span_builder("complex_operation")
.with_kind(SpanKind::Internal)
.start(&tracer);
span.add_event("Starting validation".to_string(), vec![]);
span.add_event(
"Validation complete".to_string(),
vec![KeyValue::new("validation.result", "success")],
);
span.add_event("Starting processing".to_string(), vec![]);
span.add_event("Processing complete".to_string(), vec![]);
drop(span);
}
pub fn example_span_with_error() {
use crate::telemetry::record_exception;
let tracer = global::tracer("processor");
let mut span = tracer
.span_builder("operation_with_error")
.with_kind(SpanKind::Internal)
.start(&tracer);
let result: Result<(), std::io::Error> =
Err(std::io::Error::new(std::io::ErrorKind::Other, "Something went wrong"));
if let Err(e) = result {
record_exception(&mut span, &e);
}
drop(span);
}
pub fn example_sampling_strategies() -> Result<(), Box<dyn std::error::Error>> {
use crate::telemetry::{init_tracer_provider, TraceConfig};
let config = TraceConfig {
sampling: SamplingStrategy::AlwaysOn,
..Default::default()
};
let _provider = init_tracer_provider(config)?;
let config = TraceConfig {
sampling: SamplingStrategy::TraceIdRatio { ratio: 0.1 },
..Default::default()
};
let _provider = init_tracer_provider(config)?;
let config = TraceConfig {
sampling: SamplingStrategy::ParentBased {
root: Box::new(SamplingStrategy::TraceIdRatio { ratio: 0.5 }),
},
..Default::default()
};
let _provider = init_tracer_provider(config)?;
Ok(())
}
pub fn example_baggage() {
use crate::telemetry::{get_baggage, with_baggage, BaggageItem};
let context = Context::current();
let items = vec![
BaggageItem::new("user-id", "12345"),
BaggageItem::new("tenant-id", "acme-corp"),
BaggageItem::new("request-id", "abc-123"),
];
let context = with_baggage(&context, items);
let _guard = context.attach();
if let Some(user_id) = get_baggage(&context, "user-id") {
println!("User ID: {}", user_id);
}
if let Some(tenant_id) = get_baggage(&context, "tenant-id") {
println!("Tenant ID: {}", tenant_id);
}
}
pub fn example_tracing_integration() -> Result<(), Box<dyn std::error::Error>> {
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::Registry;
let tracer = global::tracer("processor");
let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);
let subscriber = Registry::default().with(telemetry);
tracing::subscriber::set_global_default(subscriber)?;
tracing::info!("This will be exported to OpenTelemetry");
tracing::error!("Errors are captured too");
Ok(())
}
pub async fn example_instrumented_function() {
tracing::info_span!("process_batch", batch_size = 100).in_scope(|| {
});
}
pub async fn example_complete_workflow() -> Result<(), Box<dyn std::error::Error>> {
let config = TelemetryConfig::new("stream-processor")
.with_otlp_endpoint("http://localhost:4317")
.with_service_version("1.0.0")
.with_environment("production");
let providers = init_telemetry(config)?;
let tracer = global::tracer("processor");
let recorder = MetricsRecorder::new().with_attribute("service", "processor");
for i in 0..10 {
let mut span = tracer
.span_builder(format!("process_event_{}", i))
.with_kind(SpanKind::Internal)
.with_attributes(vec![
KeyValue::new("event.id", i.to_string()),
KeyValue::new("event.type", "metric"),
])
.start(&tracer);
let context = context_with_span(span.clone());
let _guard = context.attach();
span.add_event("Processing started".to_string(), vec![]);
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
recorder.record_counter(
"processor",
metric_names::EVENTS_PROCESSED,
1,
vec![KeyValue::new(metric_attributes::EVENT_TYPE, "metric")],
);
span.add_event("Processing completed".to_string(), vec![]);
drop(_guard);
drop(span);
}
providers.shutdown().await?;
Ok(())
}