o11y 0.0.0

Observability library for Rust: logging, metrics, tracing, and profiling.
Documentation

o11y - Rust Observability Package

OpenTelemetry instrumentation for Rust applications with unified configuration and flexible deployment options.

Features

  • All-in-one or standalone - Use Telemetry for coordinated setup or initialize components individually
  • Config-based - No environment variables, all configuration via structs
  • Multiple auth methods - BasicAuth, Bearer tokens, API keys, custom headers per component
  • Resource management - Automatic resource building with service identification
  • Validation - Config validation with clear error messages
  • Runtime metrics - Optional Tokio runtime metrics for meters
  • Cargo features - Enable only the observability components you need
  • OTLP native - Uses OpenTelemetry Protocol for all backends (Grafana OTLP endpoints)
  • Cross-platform - Profiler support on Unix platforms

Cargo Features

By default, all features are enabled. You can selectively enable only what you need:

[dependencies]
o11y = { version = "*", default-features = false, features = ["logger", "tracer"] }

Available features:

  • logger - Logging via OTLP
  • tracer - Distributed tracing
  • meter - Metrics collection
  • profiler - Continuous profiling (Unix only)

Installation

[dependencies]
o11y = "0.1.0"
tokio = { version = "1", features = ["full"] }

Quick Start

All-in-One Setup

use o11y::{Config, Telemetry};
use o11y::logger::LoggerConfig;
use o11y::tracer::TracerConfig;
use o11y::meter::MeterConfig;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = Config::new("my-service")
        .with_logger(
            LoggerConfig::new("my-service")
                .enabled(true)
                .with_endpoint("http://localhost:3100/otlp")
        )
        .with_tracer(
            TracerConfig::new("my-service")
                .enabled(true)
                .with_endpoint("http://localhost:4317")
        )
        .with_meter(
            MeterConfig::new("my-service")
                .enabled(true)
                .with_endpoint("http://localhost:9009/otlp")
        );

    let telemetry = Telemetry::setup(&config)?;
    
    // Your application code here
    
    telemetry.shutdown()?;
    Ok(())
}

Standalone Component Setup

use o11y::logger::{self, LoggerConfig};
use o11y::ResourceConfig;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let resource = ResourceConfig::new("my-service")
        .with_version("1.0.0")
        .with_environment("production")
        .build();

    let logger_config = LoggerConfig::new("my-service")
        .enabled(true)
        .with_endpoint("http://localhost:3100/otlp");

    let logger_provider = logger::setup(&logger_config, &resource)?;
    
    // Use logger
    
    logger::shutdown(logger_provider)?;
    Ok(())
}

Configuration

Logger Configuration

use o11y::logger::LoggerConfig;

let logger_cfg = LoggerConfig::new("my-service")
    .enabled(true)
    .with_endpoint("http://localhost:3100/otlp")
    .with_environment("production");

Note: Logger endpoint should include /otlp path for Grafana Loki OTLP endpoint.

Tracer Configuration

use o11y::tracer::TracerConfig;
use std::time::Duration;

let tracer_cfg = TracerConfig::new("my-service")
    .enabled(true)
    .with_endpoint("http://localhost:4317")
    .with_sample_ratio(0.1)  // Sample 10% of traces
    .with_export_timeout(Duration::from_secs(30));

Note: Tracer uses gRPC endpoint (default port 4317 for Grafana Tempo).

Meter Configuration

use o11y::meter::{MeterConfig, RuntimeConfig};
use std::time::Duration;

let meter_cfg = MeterConfig::new("my-service")
    .enabled(true)
    .with_endpoint("http://localhost:9009/otlp")
    .with_export_interval(Duration::from_secs(60))
    .with_runtime(RuntimeConfig::default().enabled(true));

Note: Meter endpoint should include /otlp path for Grafana Mimir OTLP endpoint (default port 9009).

Profiler Configuration

use o11y::profiler::ProfilerConfig;
use std::time::Duration;

#[cfg(unix)]
let profiler_cfg = ProfilerConfig::new("my-service")
    .enabled(true)
    .with_endpoint("http://localhost:4040")
    .with_sample_rate(100)  // Hz
    .with_upload_interval(Duration::from_secs(15));

Resource Configuration

use o11y::ResourceConfig;

let resource = ResourceConfig::new("my-service")
    .with_version("1.0.0")
    .with_environment("production")
    .with_namespace("backend")
    .with_tenant_id("my-tenant");

Global Providers

All enabled components are automatically registered with OpenTelemetry's global registry:

  • Tracer provider → opentelemetry::global::set_tracer_provider()
  • Meter provider → opentelemetry::global::set_meter_provider()

This means you can use the standard OpenTelemetry APIs throughout your application:

use opentelemetry::global;

// Get global tracer
let tracer = global::tracer("my-component");

// Get global meter
let meter = global::meter("my-component");

Authentication

Multiple authentication methods are supported per component:

Basic Auth

use o11y::auth::Credentials;

let creds = Credentials::basic_auth("username", "password");

let logger_cfg = LoggerConfig::new("my-service")
    .enabled(true)
    .with_endpoint("http://localhost:3100/otlp")
    .with_credentials(creds);

Bearer Token

let creds = Credentials::bearer_token("my-token");

API Key

let creds = Credentials::api_key("X-API-Key", "my-api-key");

Custom Headers

let creds = Credentials::custom_header("X-Custom-Auth", "value");

Examples

See the examples directory for complete working examples:

cargo run --example usage

Backends

Designed for Grafana observability stack:

  • Logger → Grafana Loki (port 3100, /otlp path)
  • Tracer → Grafana Tempo (gRPC port 4317)
  • Meter → Grafana Mimir (port 9009, /otlp path)
  • Profiler → Pyroscope (port 4040)

Error Handling

All operations return Result<T, o11y::Error>:

match Telemetry::setup(&config) {
    Ok(telemetry) => { /* success */ }
    Err(o11y::Error::Config(msg)) => { /* config validation error */ }
    Err(o11y::Error::Logger(msg)) => { /* logger setup error */ }
    Err(o11y::Error::Tracer(msg)) => { /* tracer setup error */ }
    Err(o11y::Error::Meter(msg)) => { /* meter setup error */ }
    Err(o11y::Error::Profiler(msg)) => { /* profiler setup error */ }
    Err(e) => { /* other errors */ }
}

Testing

# Unit tests
cargo test --lib

# All tests
cargo test

# With specific features
cargo test --no-default-features --features logger,tracer

License

[License information]