apollo-opentelemetry 0.8.0

OpenTelemetry configuration types for Apollo platform
Documentation
#![allow(dead_code)]
//! OpenTelemetry crate for Apollo platform.
//!
//! This crate provides a standard way to configure and use OpenTelemetry.
//!
//! # Getting Started
//!
//! Create telemetry from configuration:
//!
//! ```no_run
//! use apollo_configuration::parse_yaml;
//! use apollo_opentelemetry::{OpenTelemetryConfig, Telemetry};
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let yaml = r#"
//!   tracer_provider:
//!     processors:
//!       - batch:
//!           exporter:
//!             otlp_http:
//!               endpoint: http://localhost:4318
//! "#;
//! let config: OpenTelemetryConfig = parse_yaml(yaml, &Default::default())?;
//! let telemetry = Telemetry::new(config)?;
//! # Ok(())
//! # }
//! ```
//!
//! Or use the builder for more control:
//!
//! ```no_run
//! use apollo_configuration::parse_yaml;
//! use apollo_opentelemetry::{OpenTelemetryConfig, Telemetry};
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let yaml = r#"
//!   tracer_provider:
//!     processors:
//!       - batch:
//!           exporter:
//!             otlp_http:
//!               endpoint: http://localhost:4318
//! "#;
//! let config: OpenTelemetryConfig = parse_yaml(yaml, &Default::default())?;
//! let telemetry = Telemetry::builder(config)
//!     .with_global_tracer_provider()
//!     .with_global_meter_provider()
//!     .build()?;
//! # Ok(())
//! # }
//! ```
//!
//! # Feature Flags
//!
//! - `otlp` - Enable OTLP exporters (HTTP and gRPC)
//! - `honeycomb` - Enable [Honeycomb](https://honeycomb.io) exporter
//! - `new-relic` - Enable [New Relic](https://newrelic.com) exporter
//! - `grafana-cloud` - Enable [Grafana Cloud](https://grafana.com/products/cloud/) exporter
//! - `datadog-otlp` - Enable [Datadog OTLP intake](https://docs.datadoghq.com/opentelemetry/) exporter

// Re-export crate as `apollo_opentelemetry` for proc macro generated code.
// This allows `::apollo_opentelemetry::` paths to work both within this crate
// and from external crates that depend on it.
extern crate self as apollo_opentelemetry;

mod config;
mod error;
mod exporters;
mod processors;
mod providers;
mod telemetry;
mod to_value;
#[cfg(feature = "tower")]
pub mod tower;

pub mod metrics;

pub use config::OpenTelemetryConfig;
pub use error::{InitError, RateLimitProcessorConfigError};
pub use telemetry::{Telemetry, TelemetryBuilder};
pub use to_value::ToValue;
mod macros;
pub use macros::traced;

/// Creates a new span using OpenTelemetry.
///
/// This macro provides a concise syntax for creating spans with optional
/// attributes, span kind, parent context, and body (closure or async block).
///
/// # Syntax
///
/// ```text
/// span!(name [, scope: expr] [, parent: cx] [, kind: K] [, attrs...] [, body])
/// ```
///
/// Where:
/// - `name` - Span name (string literal or expression)
/// - `scope: expr` - Optional instrumentation scope. If omitted, uses calling crate's scope.
/// - `parent: cx` - Optional parent context. If omitted, uses `Context::current()`.
/// - `kind: K` - Optional span kind (e.g., `kind: SpanKind::Server`)
/// - `attrs...` - Optional attributes as `"key" = value` pairs
/// - `body` - Optional body: `|| { }`, `move || { }`, `async { }`, or `async move { }`
///
/// Without a body, returns the span for manual lifetime management. With a body,
/// the span is active for the duration of the closure/async block.
///
/// # Examples
///
/// ```
/// use apollo_opentelemetry::span;
/// use opentelemetry::trace::SpanKind;
///
/// // Simple span
/// let _span = span!("my-operation");
///
/// // With closure
/// span!("process", || {
///     // work happens here
/// });
///
/// // With kind and attributes
/// span!("db-query", kind: SpanKind::Client, "db.system" = "postgresql", || {
///     // execute query
/// });
///
/// // Async
/// # async fn example() {
/// span!("async-operation", async {
///     // async work
/// }).await;
/// # }
/// ```
///
/// ## Spawned tasks
///
/// The async block form returns a `Future`, making it composable with
/// `tokio::spawn()`, `select!`, `join!`, etc. The span context is captured
/// when the span is created, so spawned tasks inherit the parent automatically:
///
/// ```
/// use apollo_opentelemetry::span;
///
/// # async fn do_background_work() {}
/// # async fn example() {
/// span!("parent", async {
///     tokio::spawn(span!("child", async {
///         do_background_work().await;
///     })).await.unwrap();
/// }).await;
/// # }
/// ```
///
/// ## Dynamic span names
///
/// Span names can be expressions — variables, `format!`, function calls, etc.:
///
/// ```
/// use apollo_opentelemetry::span;
///
/// let name = String::from("dynamic-span");
/// let _span = span!(name);
///
/// let id = 42u32;
/// span!(format!("request-{id}"), || { /* work */ });
/// ```
///
/// ## Optional attributes
///
/// Attribute values of `Option<T>` are silently skipped when `None`:
///
/// ```
/// use apollo_opentelemetry::span;
///
/// let user_id: Option<i64> = Some(42);
/// let _span = span!("request", "user.id" = user_id);
/// ```
///
/// ## Automatic span status from Result
///
/// Closure and async block forms automatically set the span status based on
/// the return value:
///
/// - `Ok(_)` → span status set to `Ok`
/// - `Err(e)` → span status set to `Error` with the error's display message
/// - Any other type → span status unchanged
///
/// ```
/// use apollo_opentelemetry::span;
///
/// # fn do_work() -> Result<(), String> { Ok(()) }
/// fn process() -> Result<(), String> {
///     span!("process", || {
///         do_work()?;
///         Ok(())
///     })
/// }
/// ```
///
/// ## Custom Instrumentation Scope
///
/// Use `scope:` to override the instrumentation scope (library name and version
/// reported in telemetry). If omitted, the calling crate's scope is used.
///
/// ```
/// use apollo_opentelemetry::span;
/// use opentelemetry::InstrumentationScope;
///
/// # fn my_scope() -> InstrumentationScope { InstrumentationScope::builder("example").build() }
/// let _span = span!("my-operation", scope: my_scope());
/// ```
///
/// # Explicit Parent Context
///
/// Use `parent:` to create a span with a specific parent context:
///
/// ```
/// use apollo_opentelemetry::span;
/// use opentelemetry::Context;
/// use opentelemetry::trace::TraceContextExt;
///
/// # fn example(parent_cx: &Context) {
/// span!("child", parent: parent_cx, || {
///     // This span's parent comes from parent_cx
/// });
/// # }
/// ```
pub use apollo_opentelemetry_macros::span;

/// Private module for macro implementation details.
/// Not part of the public API - may change without notice.
#[doc(hidden)]
pub mod __private {
    pub use opentelemetry;

    pub use crate::macros::span_result::{RecordSpanResult, SpanResultRef};
}