llm-optimizer-processor 0.1.1

Data processing and transformation pipeline
Documentation
# OpenTelemetry Telemetry Module

Comprehensive OpenTelemetry tracing and metrics for the LLM Auto-Optimizer Stream Processor.

## Features

- **Distributed Tracing**: Full support for distributed tracing with OTLP exporter
- **OTLP Metrics Export**: Export metrics to OTLP collectors with delta or cumulative temporality
- **Context Propagation**: W3C Trace Context and Baggage propagation across service boundaries
- **Resource Attributes**: Automatic detection of service metadata following semantic conventions
- **Multiple Exporters**: Support for gRPC and HTTP OTLP protocols
- **Sampling Strategies**: Configurable sampling (always on/off, trace ID ratio, parent-based)
- **Async Support**: Full async/await compatibility with Tokio runtime

## Quick Start

### Initialize Telemetry

```rust
use processor::telemetry::{TelemetryConfig, init_telemetry};

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).await?;

// Use telemetry...

// Shutdown when done
providers.shutdown().await?;
```

### Create Spans

```rust
use processor::telemetry::SpanBuilder;
use opentelemetry::trace::SpanKind;

let span = SpanBuilder::new("process_event")
    .with_kind(SpanKind::Internal)
    .with_attribute("event.type", "metric")
    .with_attribute("event.id", "12345")
    .start();

// Use span...
```

### Record Metrics

```rust
use processor::telemetry::{MetricsRecorder, metric_names, metric_attributes};
use opentelemetry::KeyValue;

let recorder = MetricsRecorder::new()
    .with_attribute("service", "processor");

recorder.record_counter(
    "processor",
    metric_names::EVENTS_PROCESSED,
    1,
    vec![KeyValue::new(metric_attributes::EVENT_TYPE, "metric")],
);
```

### Context Propagation

```rust
use processor::telemetry::{inject_into_headers, extract_from_headers};
use opentelemetry::Context;
use std::collections::HashMap;

// Inject context into outgoing request
let mut headers = HashMap::new();
inject_into_headers(&Context::current(), &mut headers);

// Extract context from incoming request
let context = extract_from_headers(&headers);
```

## Module Structure

- **mod.rs**: Main module with re-exports and combined configuration
- **tracing.rs**: Trace provider initialization and span helpers
- **context.rs**: W3C Trace Context and Baggage propagation
- **metrics.rs**: OTLP metrics export configuration
- **resource.rs**: Resource attributes and automatic detection
- **examples.rs**: Usage examples and patterns

## Configuration

### Trace Configuration

```rust
use processor::telemetry::{TraceConfig, OtlpProtocol, SamplingStrategy};

let config = TraceConfig {
    enabled: true,
    service_name: "my-processor".to_string(),
    service_version: "1.0.0".to_string(),
    otlp_endpoint: "http://localhost:4317".to_string(),
    otlp_protocol: OtlpProtocol::Grpc,
    sampling: SamplingStrategy::TraceIdRatio { ratio: 0.5 },
    batch_config: Default::default(),
    headers: Default::default(),
    environment: Some("production".to_string()),
};
```

### Metrics Configuration

```rust
use processor::telemetry::{MetricsConfig, Temporality};

let config = MetricsConfig {
    enabled: true,
    service_name: "my-processor".to_string(),
    service_version: "1.0.0".to_string(),
    otlp_endpoint: "http://localhost:4317".to_string(),
    temporality: Temporality::Cumulative,
    export_config: Default::default(),
    headers: Default::default(),
    environment: Some("production".to_string()),
};
```

## Sampling Strategies

### Always On (100% sampling)

```rust
use processor::telemetry::SamplingStrategy;

let sampling = SamplingStrategy::AlwaysOn;
```

### Trace ID Ratio (sample a percentage)

```rust
let sampling = SamplingStrategy::TraceIdRatio { ratio: 0.1 }; // 10%
```

### Parent-Based (follow parent's decision)

```rust
let sampling = SamplingStrategy::ParentBased {
    root: Box::new(SamplingStrategy::TraceIdRatio { ratio: 0.5 }),
};
```

## Semantic Conventions

The module follows OpenTelemetry semantic conventions for:

### Resource Attributes

- `service.name`: Service name
- `service.version`: Service version
- `service.instance.id`: Unique instance identifier
- `deployment.environment`: Deployment environment
- `service.component`: Component type (e.g., "stream-processor")

### Span Attributes

- `event.type`: Type of event being processed
- `window.type`: Type of window operation
- `aggregation.type`: Type of aggregation
- `state.backend`: State backend type
- `operation.type`: Operation being performed

### Metric Names

- `processor.events.processed`: Count of processed events
- `processor.events.dropped`: Count of dropped events
- `processor.processing.duration`: Processing duration histogram
- `processor.window.triggers`: Window trigger count
- `processor.aggregation.duration`: Aggregation duration
- `processor.state.operation.duration`: State operation duration
- `processor.deduplication.count`: Deduplication count
- `processor.watermark.lag`: Watermark lag gauge

## Integration with Tracing Crate

```rust
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::Registry;
use processor::telemetry::otel_global;

let tracer = otel_global::tracer("processor");
let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);

let subscriber = Registry::default().with(telemetry);
tracing::subscriber::set_global_default(subscriber)?;

// Now use tracing macros
tracing::info!("Processing event");
tracing::error!("Error occurred");
```

## Testing

### Unit Tests

```bash
cargo test --lib telemetry
```

### Integration Tests (requires OTLP collector)

```bash
# Start OTLP collector
docker run -p 4317:4317 -p 4318:4318 otel/opentelemetry-collector

# Run tests
OTLP_ENDPOINT=http://localhost:4317 cargo test --test telemetry_integration_tests -- --ignored
```

## Examples

See `examples.rs` for comprehensive usage examples including:

- Basic initialization
- Creating nested spans
- Async context propagation
- Cross-service context injection/extraction
- Recording metrics
- Adding span events
- Error handling
- Baggage usage
- Integration with tracing crate

## Best Practices

1. **Initialize Once**: Initialize telemetry providers once at application startup
2. **Use Sampling**: In high-throughput scenarios, use sampling to reduce overhead
3. **Propagate Context**: Always propagate context across async boundaries
4. **Add Meaningful Attributes**: Include relevant attributes to make traces searchable
5. **Record Errors**: Use `record_exception` to capture errors in spans
6. **Batch Configuration**: Tune batch settings for your throughput requirements
7. **Shutdown Gracefully**: Always shutdown providers to flush pending data

## Performance Considerations

- **Sampling**: Use trace ID ratio sampling to reduce overhead in production
- **Batch Size**: Increase batch size for high-throughput scenarios
- **Export Interval**: Adjust export interval based on latency requirements
- **Async Export**: Spans and metrics are exported asynchronously

## Troubleshooting

### Traces Not Appearing

- Verify OTLP endpoint is correct and reachable
- Check sampling strategy (ensure not AlwaysOff)
- Verify batch export is completing (check timeouts)
- Check OTLP collector logs

### High Overhead

- Reduce sampling ratio
- Increase batch size and export interval
- Disable telemetry for low-priority operations

### Context Not Propagating

- Ensure context is attached before creating child spans
- Verify headers are correctly injected/extracted
- Check W3C Trace Context propagator is set

## License

Apache-2.0