apollo-opentelemetry 0.8.0

OpenTelemetry configuration types for Apollo platform
Documentation
//! Span processor configuration.
//!
//! See the [OpenTelemetry Tracing SDK specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/)
//! for details on processor behavior and defaults.

use apollo_configuration::configuration;

use crate::config::processor::validate_rate_limited_processor;
use crate::config::{BatchProcessorConfig, RateLimitedProcessorConfig, SpanExporter};

/// Span processor configuration.
#[configuration]
pub(crate) enum SpanProcessor {
    /// Batch processor that collects spans and exports them in batches.
    Batch(BatchSpanProcessorConfig),
    /// Simple processor that exports each span immediately.
    Simple(SimpleSpanProcessorConfig),
    /// Rate-limited processor that applies rate limiting before batch processing.
    RateLimited(RateLimitedSpanProcessorConfig),
}

/// Batch span processor configuration.
///
/// Batches spans and exports them periodically or when the batch reaches
/// a size threshold. See the [SDK specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#batching-processor)
/// for details.
#[configuration]
pub(crate) struct BatchSpanProcessorConfig {
    #[config(required)]
    pub(crate) exporter: SpanExporter,

    /// Maximum time to wait before exporting a batch (in milliseconds).
    ///
    /// Default: 5000ms per [SDK specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#batching-processor).
    #[config(default = 5000)]
    pub(crate) schedule_delay: u64,

    /// Maximum time to wait for export to complete (in milliseconds).
    ///
    /// Default: 30000ms per [SDK specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#batching-processor).
    #[config(default = 30000)]
    pub(crate) export_timeout: u64,

    /// Maximum number of spans per batch.
    ///
    /// Default: 512 per [SDK specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#batching-processor).
    #[config(default = 512)]
    pub(crate) max_export_batch_size: u32,

    /// Maximum queue size for pending spans.
    ///
    /// Default: 2048 per [SDK specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#batching-processor).
    #[config(default = 2048)]
    pub(crate) max_queue_size: u32,
}

/// Simple span processor configuration.
///
/// Exports each span immediately as it ends.
#[configuration]
pub(crate) struct SimpleSpanProcessorConfig {
    #[config(required)]
    pub(crate) exporter: SpanExporter,
}

/// Rate-limited span processor configuration.
///
/// Protects against unexpected telemetry costs by enforcing a maximum spans-per-second
/// limit. Spans exceeding the limit are dropped before entering the batch queue,
/// preventing runaway telemetry from infinite loops, retry storms, or load spikes.
///
/// # Observability
///
/// **UNSTABLE:** Metrics follow the [OTel SDK semantic conventions] which are currently
/// in development status. Metric names and attributes may change in future releases.
///
/// **Processor metric:** `otel.sdk.processor.span.processed`
///
/// | Attribute            | Description                                           |
/// |----------------------|-------------------------------------------------------|
/// | `otel.component.type`| `rate_limited_span_processor`                         |
/// | `otel.component.name`| `rate_limited_span_processor/{instance_id}`           |
/// | `error.type`         | `rate_limited` (only present when spans are dropped)  |
///
/// **Exporter metric:** `otel.sdk.exporter.span.exported`
///
/// | Attribute            | Description                                           |
/// |----------------------|-------------------------------------------------------|
/// | `otel.component.type`| `{exporter}_exporter` (e.g., `otlp_http_exporter`)    |
/// | `otel.component.name`| `{exporter}_exporter/{instance_id}`                   |
/// | `server.address`     | Destination host (e.g., `localhost`)                  |
/// | `server.port`        | Destination port (e.g., `4318`)                       |
/// | `error.type`         | `export_failed` (only present on failure)             |
///
/// The processor and exporter share the same `{instance_id}` so you can correlate
/// rate-limited drops with export failures for the same pipeline.
///
/// Use these metrics to:
/// - Alert when processor drops exceed a threshold (rate limit too low)
/// - Monitor exporter failures and retries
/// - Calculate drop rates by comparing records with/without `error.type`
///
/// [OTel SDK semantic conventions]: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/otel/sdk-metrics.md
///
/// # Configuration
///
/// Batch parameters use SDK defaults. If `max_rate` exceeds the batch processor's
/// throughput (`max_export_batch_size / schedule_delay`), validation will fail with
/// suggestions for how to adjust the configuration.
#[configuration(validate = validate_rate_limited_processor)]
pub(crate) struct RateLimitedSpanProcessorConfig {
    #[config(required)]
    pub(crate) exporter: SpanExporter,

    /// Maximum spans per second.
    ///
    /// Default: 100 per second.
    #[config(default = 100)]
    pub(crate) max_rate: u32,

    /// Maximum time to wait before exporting a batch (in milliseconds).
    ///
    /// Default: 5000ms per [SDK specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#batching-processor).
    #[config(default = 5000)]
    pub(crate) schedule_delay: u64,

    /// Maximum time to wait for export to complete (in milliseconds).
    ///
    /// Default: 30000ms per [SDK specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#batching-processor).
    #[config(default = 30000)]
    pub(crate) export_timeout: u64,

    /// Maximum number of spans per batch.
    ///
    /// Default: 512 per [SDK specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#batching-processor).
    #[config(default = 512)]
    pub(crate) max_export_batch_size: u32,

    /// Maximum queue size for pending spans.
    ///
    /// Default: 2048 per [SDK specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#batching-processor).
    #[config(default = 2048)]
    pub(crate) max_queue_size: u32,
}

impl BatchProcessorConfig for BatchSpanProcessorConfig {
    fn schedule_delay(&self) -> u64 {
        self.schedule_delay
    }

    fn export_timeout(&self) -> u64 {
        self.export_timeout
    }

    fn max_export_batch_size(&self) -> u32 {
        self.max_export_batch_size
    }

    fn max_queue_size(&self) -> u32 {
        self.max_queue_size
    }
}

impl BatchProcessorConfig for RateLimitedSpanProcessorConfig {
    fn schedule_delay(&self) -> u64 {
        self.schedule_delay
    }

    fn export_timeout(&self) -> u64 {
        self.export_timeout
    }

    fn max_export_batch_size(&self) -> u32 {
        self.max_export_batch_size
    }

    fn max_queue_size(&self) -> u32 {
        self.max_queue_size
    }
}

impl RateLimitedProcessorConfig for RateLimitedSpanProcessorConfig {
    fn max_rate(&self) -> u32 {
        self.max_rate
    }
}

/// Span limits configuration.
///
/// See the [span limits specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#span-limits)
/// and [attribute limits specification](https://opentelemetry.io/docs/specs/otel/common/#attribute-limits)
/// for details.
#[configuration]
pub(crate) struct SpanLimitsConfig {
    /// Maximum number of attributes per span.
    ///
    /// Default: 128 per [attribute limits specification](https://opentelemetry.io/docs/specs/otel/common/#attribute-limits).
    #[config(default = 128)]
    pub(crate) attribute_count_limit: u32,

    /// Maximum length of string attribute values. No limit by default.
    ///
    /// Per the [attribute limits specification](https://opentelemetry.io/docs/specs/otel/common/#attribute-limits),
    /// there is no default length limit.
    pub(crate) attribute_value_length_limit: Option<u32>,

    /// Maximum number of events per span.
    ///
    /// Default: 128 per [span limits specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#span-limits).
    #[config(default = 128)]
    pub(crate) event_count_limit: u32,

    /// Maximum number of links per span.
    ///
    /// Default: 128 per [span limits specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#span-limits).
    #[config(default = 128)]
    pub(crate) link_count_limit: u32,

    /// Maximum number of attributes per event.
    ///
    /// Default: 128 per [span limits specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#span-limits).
    #[config(default = 128)]
    pub(crate) event_attribute_count_limit: u32,

    /// Maximum number of attributes per link.
    ///
    /// Default: 128 per [span limits specification](https://opentelemetry.io/docs/specs/otel/trace/sdk/#span-limits).
    #[config(default = 128)]
    pub(crate) link_attribute_count_limit: u32,
}