apollo-opentelemetry 0.8.0

OpenTelemetry configuration types for Apollo platform
Documentation
//! Convenience macros for telemetry instrumentation.

mod span;
mod span_event;
pub(crate) mod span_result;
/// Instruments a function with an OpenTelemetry span.
///
/// The span is automatically started when the function begins and ended
/// when it returns. Both sync and async functions are supported.
///
/// # Syntax
///
/// The macro uses the same syntax as the `span!` macro:
///
/// ```text
/// #[traced]                                           // defaults to function name
/// #[traced("span-name")]                              // custom span name
/// #[traced("span-name", kind: SpanKind::Server)]      // with span kind
/// #[traced("span-name", "key" = "literal")]           // with literal attribute
/// #[traced("span-name", "key" = CONST_VALUE)]         // with expression attribute
/// #[traced(scope, "span-name")]                       // explicit scope
/// #[traced(scope, "span-name", kind: SpanKind::X, "key" = value)]
/// ```
///
/// # Attributes
///
/// Attribute values can be literals, constants, or expressions that reference
/// parameters:
///
/// ```
/// use apollo_opentelemetry::traced;
///
/// const VERSION: &str = "1.0";
///
/// struct Request { path: String }
/// impl Request {
///     fn path(&self) -> &str { &self.path }
/// }
///
/// #[traced("request", "api.version" = VERSION, "url.path" = request.path())]
/// fn handle(request: &Request) {
///     let _ = request;
/// }
/// ```
///
/// `Option<T>` values are supported - if the value is `None`, the attribute
/// is omitted:
///
/// ```
/// use apollo_opentelemetry::traced;
///
/// #[traced("query", "user.id" = user_id)]
/// fn query(user_id: Option<i64>) {
///     let _ = user_id;
/// }
/// ```
///
/// # Parameter Attributes
///
/// Parameters can be annotated with `#[attr]` to include them as span attributes:
///
/// - `#[attr]` - Uses parameter name as attribute key
/// - `#[attr("custom.key")]` - Uses custom key for the attribute
///
/// Note: `#[attr]` captures the parameter value directly. For computed values
/// or expressions, use manual attributes in the macro arguments instead.
///
/// ```
/// use apollo_opentelemetry::traced;
///
/// #[traced]
/// fn process(#[attr] user_id: u64, #[attr("request.method")] method: &str) {
///     let _ = (user_id, method);
/// }
/// ```
///
/// # Examples
///
/// Basic usage - span name defaults to function name:
///
/// ```
/// use apollo_opentelemetry::traced;
///
/// #[traced]
/// fn process_data() { }
/// ```
///
/// Custom span name:
///
/// ```
/// use apollo_opentelemetry::traced;
///
/// #[traced("custom-span")]
/// fn handler() { }
/// ```
///
/// With span kind:
///
/// ```
/// use apollo_opentelemetry::traced;
/// use opentelemetry::trace::SpanKind;
///
/// #[traced("handle-request", kind: SpanKind::Server)]
/// async fn handle_request() { }
/// ```
///
/// With attributes:
///
/// ```
/// use apollo_opentelemetry::traced;
///
/// #[traced("db-query", "db.system" = "postgresql")]
/// fn query_database() { }
/// ```
///
/// With explicit instrumentation scope:
///
/// ```
/// use apollo_opentelemetry::{default_instrumentation_scope, traced};
///
/// #[traced(default_instrumentation_scope!(), "process")]
/// fn process_item() { }
/// ```
///
/// Full example combining scope, span name, kind, and attributes:
///
/// ```
/// use apollo_opentelemetry::{default_instrumentation_scope, traced};
/// use opentelemetry::trace::SpanKind;
///
/// #[traced(default_instrumentation_scope!(), "http.request", kind: SpanKind::Client, "http.method" = "GET")]
/// async fn make_request(#[attr("http.url")] url: &str) -> i32 {
///     let _ = url;
///     200
/// }
/// ```
///
/// # Automatic Span Status
///
/// Functions returning `Result` automatically set the span status:
///
/// - `Ok(_)` → span status set to `Ok`
/// - `Err(e)` → span status set to `Error` with the error message
/// - Non-`Result` return types → span status unchanged
///
/// ```
/// use apollo_opentelemetry::traced;
///
/// # fn do_work() -> Result<(), String> { Ok(()) }
/// #[traced("process")]
/// fn process() -> Result<(), String> {
///     do_work()?;
///     Ok(())
/// }
/// ```
///
/// ```
/// use apollo_opentelemetry::traced;
///
/// # async fn fetch_data() -> Result<String, String> { Ok("data".into()) }
/// #[traced("fetch")]
/// async fn fetch() -> Result<String, String> {
///     let data = fetch_data().await?;
///     Ok(data)
/// }
/// ```
pub use apollo_opentelemetry_macros::traced;

/// Returns an [`InstrumentationScope`] for the calling crate.
///
/// The scope includes the crate name and version from `Cargo.toml`, ensuring
/// telemetry is attributed to your crate.
///
/// [`InstrumentationScope`]: opentelemetry::InstrumentationScope
#[macro_export]
macro_rules! default_instrumentation_scope {
    () => {{
        static SCOPE: std::sync::LazyLock<$crate::__private::opentelemetry::InstrumentationScope> =
            std::sync::LazyLock::new(|| {
                $crate::__private::opentelemetry::InstrumentationScope::builder(env!(
                    "CARGO_PKG_NAME"
                ))
                .with_version(env!("CARGO_PKG_VERSION"))
                .build()
            });
        &*SCOPE
    }};
}