evlib 0.8.6

Event Camera Data Processing Library
Documentation
# Structured Logging with Tracing

evlib uses the [`tracing`](https://docs.rs/tracing/latest/tracing/) crate for structured, configurable logging. This provides better control over log verbosity, structured output, and integration with external logging systems.

## Quick Start

### Basic Setup

```rust
use evlib::tracing_config;

// Initialize with sensible defaults
tracing_config::init();

// Now load events - logging will be structured and configurable
let events = evlib::ev_formats::load_events_with_config("tests/data/eTram/h5/val_2/val_night_011_td.h5", &config)?;
```

### Environment Variable Control

Control logging via the `RUST_LOG` environment variable:

```bash
# Default: INFO level for evlib, WARN for everything else
cargo run

# Enable debug logging for evlib
RUST_LOG=evlib=debug cargo run

# Only show warnings and errors
RUST_LOG=evlib=warn cargo run

# Very detailed tracing for specific module
RUST_LOG=evlib::ev_formats::prophesee_ecf_codec=trace cargo run

# Multiple module control
RUST_LOG="evlib::ev_formats=debug,evlib::ev_processing=info" cargo run
```

## Log Levels

evlib uses the following log levels:

### `ERROR` - Critical Failures
- Model loading failures
- File parsing errors
- System-level problems
- Fallback mechanism failures

Example output:
```
2024-01-15T10:30:45.123456Z ERROR evlib::ev_formats::mod: Python fallback failed error="File not found"
```

### `WARN` - Warnings and Fallbacks
- Fallback behaviors activated
- Unsupported file formats
- Missing optional dependencies
- Performance degradation warnings

Example output:
```
2024-01-15T10:30:45.123456Z  WARN evlib::ev_formats::prophesee_ecf_codec: Unknown delta_bits value in ECF decoder delta_bits=7
```

### `INFO` - Status and Progress
- File loading progress
- Model downloading status
- Successful operations
- Stream status updates

Example output:
```
2024-01-15T10:30:45.123456Z  INFO evlib::ev_formats::mod: Native Rust ECF decoder loaded events events=1048576
```

### `DEBUG` - Development Information
- Detailed ECF decoding steps
- WebSocket connection details
- Model verification results
- Internal state information

Example output:
```
2024-01-15T10:30:45.123456Z DEBUG evlib::ev_formats::prophesee_ecf_codec: ECF base timestamp base_timestamp=1627849200000000
```

### `TRACE` - Very Detailed Debug
- Low-level operations
- Performance timing
- Memory allocation details

*Note: Currently no TRACE level logs in evlib, reserved for future use.*

## Configuration Options

### Default Configuration

```rust
use evlib::tracing_config;

// Standard configuration - good for most use cases
tracing_config::init();
```

### Debug Configuration

```rust
use evlib::tracing_config;

// Enables debug logging with file/line information
tracing_config::init_debug();
```

### Custom Configuration

```rust
use evlib::tracing_config;

// Fine-grained control over specific modules
tracing_config::init_with_filter("evlib::ev_formats=trace,evlib=info");
```

### Production Configuration

```rust
use evlib::tracing_config::examples;

// JSON output suitable for log aggregation
examples::init_production();
```

### Development Configuration

```rust
use evlib::tracing_config::examples;

// Pretty-printed output with colors and extra context
examples::init_development();
```

## Integration Examples

### With `env_logger` style

```rust
use tracing_subscriber::{EnvFilter, fmt};

// Similar to env_logger but with structured output
fmt()
    .with_env_filter(EnvFilter::from_default_env())
    .init();
```

### With `syslog`

```rust
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

tracing_subscriber::registry()
    .with(tracing_syslog::layer())
    .with(EnvFilter::from_default_env())
    .init();
```

### With File Output

```rust
use tracing_subscriber::{fmt, EnvFilter};
use std::fs::File;

let file = File::create("evlib.log")?;
fmt()
    .with_writer(file)
    .with_env_filter(EnvFilter::from_default_env())
    .init();
```

### With JSON for Kubernetes/Docker

```rust
use tracing_subscriber::{fmt, EnvFilter};

fmt()
    .json()
    .with_env_filter(EnvFilter::from_default_env())
    .init();
```

## Testing Integration

```rust
#[cfg(test)]
mod tests {
    use evlib::tracing_config;

    #[test]
    fn test_event_loading() {
        // Initialize tracing for tests
        tracing_config::init_test();

        // Test code here - logs will be captured in test output
        let events = evlib::ev_formats::load_events_from_text("tests/data/test.txt")?;
    }
}
```

## Python Integration

When using evlib from Python, you can still control Rust logging:

```python
import os
import evlib

# Set logging level before importing/using evlib
os.environ['RUST_LOG'] = 'evlib=debug'

# Initialize tracing from Python (if exposed)
# Note: This requires exposing tracing_config functions to Python
# evlib.tracing_config.init()

# Load events - Rust logs will be controlled by RUST_LOG
events = evlib.load_events('tests/data/eTram/h5/val_2/val_night_011_td.h5')
print(f"Loaded events with shape: {events.collect().shape}")
```

## Performance Considerations

### Runtime Overhead
- `trace!` and `debug!` macros compile to no-ops when disabled
- `info!`, `warn!`, `error!` have minimal overhead when disabled
- Structured logging is more efficient than string formatting
- Filtering happens at compile time when possible

### Memory Usage
- Structured logs use less memory than formatted strings
- Span context tracking has minimal overhead
- Field values are lazily formatted only when logged

## Common Patterns

### Module-Specific Debugging

```bash
# Debug only ECF decoding
RUST_LOG=evlib::ev_formats::prophesee_ecf_codec=debug cargo run

# Debug all format readers
RUST_LOG=evlib::ev_formats=debug cargo run

# Debug model loading
RUST_LOG=evlib::ev_processing::model_zoo=debug cargo run
```

### Production Logging

```bash
# Minimal logging for production
RUST_LOG=evlib=warn cargo run

# Structured JSON for log aggregation
RUST_LOG=evlib=info cargo run > logs.json
```

### Development Debugging

```bash
# Comprehensive debugging
RUST_LOG=evlib=debug cargo run

# Very detailed tracing
RUST_LOG=evlib=trace cargo run
```

## Migration from println!/eprintln!

Old code using print statements:
```rust
eprintln!("Loading {} events from file", events.len());
println!("ECF decoder failed: {}", error);
```

New structured logging:
```rust
use tracing::{info, error};

info!(events = events.len(), "Loading events from file");
error!(error = %error, "ECF decoder failed");
```

## Benefits

1. **Configurable Verbosity**: Control logging at runtime without recompilation
2. **Structured Output**: Key-value pairs for better parsing and filtering
3. **Performance**: Debug logs compile to no-ops when disabled
4. **Integration**: Works with existing Rust logging ecosystem
5. **Consistency**: Uniform logging patterns across the entire library
6. **Observability**: Better debugging and monitoring capabilities

## Troubleshooting

### No Logs Appearing

1. Check that tracing is initialized: `tracing_config::init()`
2. Verify `RUST_LOG` environment variable: `RUST_LOG=evlib=debug`
3. Ensure log level is appropriate for desired messages

### Too Many Logs

1. Increase filter level: `RUST_LOG=evlib=warn`
2. Use module-specific filtering: `RUST_LOG=evlib::ev_formats=info`
3. Switch to production configuration for cleaner output

### JSON Parsing Issues

1. Use `fmt().json()` for consistent JSON output
2. Ensure no mixed output formats in configuration
3. Consider using dedicated JSON logging libraries for complex parsing

For more information, see the [tracing documentation](https://docs.rs/tracing/latest/tracing/) and [tracing-subscriber documentation](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/).