use mecha10::prelude::*;
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize)]
struct ImageMessage {
width: u32,
height: u32,
timestamp: u64,
}
impl Message for ImageMessage {}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct DetectionResult {
object_count: u32,
confidence: f32,
}
impl Message for DetectionResult {}
pub fn basic_propagation_example() -> Result<()> {
info!("Example 1: Basic trace context propagation");
let trace_ctx = TraceContext::new();
info!("\nCreated trace context:");
info!(" Trace ID: {}", trace_ctx.trace_id);
info!(" Span ID: {}", trace_ctx.span_id);
info!(" Sampled: {}", trace_ctx.sampled);
let child_ctx = trace_ctx.child();
info!("\nChild context:");
info!(" Trace ID: {} (same as parent)", child_ctx.trace_id);
info!(" Span ID: {} (new)", child_ctx.span_id);
info!(" Parent Span ID: {:?}", child_ctx.parent_span_id);
Ok(())
}
pub fn w3c_format_example() -> Result<()> {
info!("Example 2: W3C Trace Context format");
let ctx = TraceContext::new();
let traceparent = ctx.to_w3c_traceparent();
info!("\nW3C traceparent: {}", traceparent);
info!(" Format: version-trace_id-span_id-flags");
let parsed = TraceContext::from_w3c_traceparent(&traceparent).unwrap();
info!("\nParsed context:");
info!(" Trace ID: {}", parsed.trace_id);
info!(" Span ID: {}", parsed.span_id);
info!(" Sampled: {}", parsed.sampled);
Ok(())
}
pub fn baggage_example() -> Result<()> {
info!("Example 3: Baggage for metadata propagation");
let ctx = TraceContext::new()
.with_baggage("user_id", "user123")
.with_baggage("request_id", "req_abc")
.with_baggage("environment", "production");
info!("\nBaggage items:");
for (key, value) in &ctx.baggage {
info!(" {}: {}", key, value);
}
info!("\nBaggage propagates with trace context,");
info!("allowing metadata to flow through the system.");
Ok(())
}
pub fn traced_message_example() -> Result<()> {
info!("Example 4: TracedMessage envelope");
let image = ImageMessage {
width: 640,
height: 480,
timestamp: now_micros(),
};
let traced = TracedMessage::new(image.clone(), "camera_node");
info!("\nTracedMessage structure:");
info!(" Payload: {:?}", traced.payload);
info!(" Trace ID: {}", traced.trace_context.trace_id);
info!(" Source: {}", traced.source_node);
info!(" Timestamp: {}", traced.timestamp_us);
let span = traced.create_span("process_image");
let _guard = span.enter();
info!("\nSpan created from message");
info!(" All logs within this scope include trace context");
Ok(())
}
pub async fn publish_traced_example() -> Result<()> {
info!("Example 5: Publishing with trace context");
info!("\nNormal publish:");
info!(" ctx.publish(\"/topic\", &message).await");
info!(" → No trace context");
info!("\nTraced publish:");
info!(" ctx.publish_traced(\"/topic\", &message).await");
info!(" → Automatic trace context injection");
info!(" → Creates child span for this publish");
info!("\nPublish with explicit context:");
info!(" ctx.publish_with_context(\"/topic\", &message, trace_ctx).await");
info!(" → Use existing trace context");
info!(" → Continue existing trace");
Ok(())
}
pub async fn subscribe_traced_example() -> Result<()> {
info!("Example 6: Subscribing with trace context");
info!("\nNormal subscribe:");
info!(" let mut rx = ctx.subscribe(\"/topic\").await?;");
info!(" while let Some(msg) = rx.recv().await {{ }}");
info!(" → Message only");
info!("\nTraced subscribe:");
info!(" let mut rx = ctx.subscribe_traced(\"/topic\").await?;");
info!(" while let Some(traced_msg) = rx.recv().await {{");
info!(" let trace_ctx = traced_msg.trace_context;");
info!(" let span = traced_msg.create_span(\"process\");");
info!(" span.in_scope(|| {{");
info!(" // Process within traced span");
info!(" }});");
info!(" }}");
info!(" → Message + trace context");
info!(" → Automatic span continuation");
Ok(())
}
pub fn end_to_end_scenario() -> Result<()> {
info!("Example 7: End-to-end tracing scenario");
info!("\nImage processing pipeline:");
info!(" Camera → Detection → Tracking → Planning");
let root_ctx = TraceContext::new()
.with_baggage("pipeline", "vision")
.with_baggage("frame_id", "1234");
info!("\nStep 1: Camera captures image");
info!(" Trace ID: {}", root_ctx.trace_id);
info!(" Span: camera_capture");
let detection_ctx = root_ctx.child();
info!("\nStep 2: Detection processes image");
info!(" Trace ID: {} (same)", detection_ctx.trace_id);
info!(" Span: object_detection");
info!(" Parent: {}", root_ctx.span_id);
let tracking_ctx = detection_ctx.child();
info!("\nStep 3: Tracking updates state");
info!(" Trace ID: {} (same)", tracking_ctx.trace_id);
info!(" Span: object_tracking");
info!(" Parent: {}", detection_ctx.span_id);
let planning_ctx = tracking_ctx.child();
info!("\nStep 4: Planning makes decision");
info!(" Trace ID: {} (same)", planning_ctx.trace_id);
info!(" Span: path_planning");
info!(" Parent: {}", tracking_ctx.span_id);
info!("\nAll spans share the same trace ID,");
info!("enabling visualization of the complete flow!");
Ok(())
}
pub fn sampling_example() -> Result<()> {
info!("Example 8: Sampling configuration");
info!("\nFull sampling (100%):");
let config = TracingConfig::default()
.with_service_name("robot-vision")
.with_sampling_rate(1.0);
info!(" Every request is traced");
info!(" Sampling rate: {}", config.sampling_rate);
info!("\nPartial sampling (10%):");
let config = TracingConfig::default()
.with_service_name("robot-vision")
.with_sampling_rate(0.1);
info!(" 1 in 10 requests traced");
info!(" Reduces overhead in production");
info!(" Sampling rate: {}", config.sampling_rate);
info!("\nNo sampling (0%):");
let config = TracingConfig::default()
.with_service_name("robot-vision")
.with_sampling_rate(0.0);
info!(" Tracing disabled");
info!(" Sampling rate: {}", config.sampling_rate);
Ok(())
}
pub fn exporter_configuration() -> Result<()> {
info!("Example 9: Exporter configuration");
info!("\nJaeger exporter:");
let config = TracingConfig::default()
.with_service_name("my-robot")
.with_jaeger("http://localhost:14268/api/traces");
info!(" Service: {}", config.service_name);
info!(" Endpoint: {:?}", config.jaeger_endpoint);
info!("\nZipkin exporter:");
let config = TracingConfig::default()
.with_service_name("my-robot")
.with_zipkin("http://localhost:9411/api/v2/spans");
info!(" Service: {}", config.service_name);
info!(" Endpoint: {:?}", config.zipkin_endpoint);
info!("\nBoth exporters:");
let config = TracingConfig::default()
.with_service_name("my-robot")
.with_jaeger("http://jaeger:14268/api/traces")
.with_zipkin("http://zipkin:9411/api/v2/spans");
info!(" Traces sent to both Jaeger and Zipkin");
Ok(())
}
pub fn real_world_pattern() -> Result<()> {
info!("Example 10: Real-world usage pattern");
info!("\nTypical node implementation:");
info!("```rust");
info!("async fn run(&mut self, ctx: &Context) -> Result<()> {{");
info!(" // Subscribe with tracing");
info!(" let mut images = ctx.subscribe_traced(\"/camera/rgb\").await?;");
info!("");
info!(" while let Some(traced_msg) = images.recv().await {{");
info!(" // Extract trace context");
info!(" let trace_ctx = traced_msg.trace_context;");
info!(" let image = traced_msg.payload;");
info!("");
info!(" // Create span for processing");
info!(" let span = traced_msg.create_span(\"detect_objects\");");
info!(" let _guard = span.enter();");
info!("");
info!(" // Process (all logs include trace context)");
info!(" let detections = detect_objects(&image);");
info!("");
info!(" // Publish with continued trace");
info!(" ctx.publish_with_context(");
info!(" \"/perception/detections\",");
info!(" &detections,");
info!(" trace_ctx,");
info!(" ).await?;");
info!(" }}");
info!("}}");
info!("```");
Ok(())
}
pub fn trace_visualization() -> Result<()> {
info!("Example 11: Trace visualization");
info!("\nIn Jaeger UI, you can see:");
info!(" • Request timeline");
info!(" • Service dependencies");
info!(" • Span durations");
info!(" • Error locations");
info!(" • Baggage metadata");
info!("\nExample trace:");
info!("┌─────────────────────────────────────────────────────┐");
info!("│ Trace: a1b2c3d4e5f6 Duration: 145ms │");
info!("├─────────────────────────────────────────────────────┤");
info!("│ camera_node → camera_capture 5ms │");
info!("│ vision_node → object_detection 80ms │");
info!("│ tracking_node → update_tracks 35ms │");
info!("│ planner_node → plan_path 25ms │");
info!("└─────────────────────────────────────────────────────┘");
Ok(())
}
pub fn performance_impact() -> Result<()> {
info!("Example 12: Performance impact");
info!("\nTracing overhead:");
info!(" Trace context creation: ~1-2 µs");
info!(" Context serialization: ~5-10 µs");
info!(" Span creation: ~2-3 µs");
info!(" Export (async, batched): ~100-500 µs");
info!("\nMitigation strategies:");
info!(" • Use sampling (e.g., 10%)");
info!(" • Batch export spans");
info!(" • Async export to avoid blocking");
info!(" • Disable in tight loops");
info!("\nRecommendations:");
info!(" Development: 100% sampling");
info!(" Staging: 50% sampling");
info!(" Production: 5-10% sampling");
Ok(())
}
fn main() -> Result<()> {
tracing_subscriber::fmt().with_max_level(tracing::Level::INFO).init();
println!("Distributed Tracing with Context Propagation");
println!("============================================\n");
println!("End-to-end request tracing across distributed nodes.");
println!();
let runtime = tokio::runtime::Runtime::new().unwrap();
runtime.block_on(async {
basic_propagation_example()?;
println!();
w3c_format_example()?;
println!();
baggage_example()?;
println!();
traced_message_example()?;
println!();
publish_traced_example().await?;
println!();
subscribe_traced_example().await?;
println!();
end_to_end_scenario()?;
println!();
sampling_example()?;
println!();
exporter_configuration()?;
println!();
real_world_pattern()?;
println!();
trace_visualization()?;
println!();
performance_impact()?;
println!();
Ok::<(), Mecha10Error>(())
})?;
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!("All examples completed!");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
println!("Key Features:");
println!(" ✓ Automatic trace context propagation");
println!(" ✓ W3C Trace Context standard");
println!(" ✓ Parent-child span relationships");
println!(" ✓ Baggage for metadata");
println!(" ✓ Configurable sampling");
println!(" ✓ Multiple exporters (Jaeger, Zipkin)");
println!();
println!("Benefits:");
println!(" • Debug distributed systems");
println!(" • Identify performance bottlenecks");
println!(" • Understand service dependencies");
println!(" • Track requests end-to-end");
println!(" • Correlate logs across nodes");
Ok(())
}