apollo-router 1.61.13

A configurable, high-performance routing runtime for Apollo Federation 🚀
Documentation
use std::borrow::Cow;
use std::sync::Arc;
use std::sync::RwLock;

use opentelemetry::trace::SpanBuilder;
use opentelemetry::trace::Tracer;

use crate::plugins::telemetry::otel::OtelData;
use crate::plugins::telemetry::otel::PreSampledTracer;

#[derive(Clone)]
pub(crate) struct ReloadTracer<S> {
    parent: Arc<RwLock<S>>,
}

impl<S: PreSampledTracer> PreSampledTracer for ReloadTracer<S> {
    fn sampled_context(&self, data: &mut OtelData) -> opentelemetry::Context {
        self.parent
            .read()
            .expect("parent tracer must be available")
            .sampled_context(data)
    }

    fn new_trace_id(&self) -> opentelemetry::trace::TraceId {
        self.parent
            .read()
            .expect("parent tracer must be available")
            .new_trace_id()
    }

    fn new_span_id(&self) -> opentelemetry::trace::SpanId {
        self.parent
            .read()
            .expect("parent tracer must be available")
            .new_span_id()
    }
}

impl<S: Tracer> Tracer for ReloadTracer<S> {
    type Span = S::Span;

    fn start<T>(&self, name: T) -> Self::Span
    where
        T: Into<Cow<'static, str>>,
    {
        self.parent
            .read()
            .expect("parent tracer must be available")
            .start(name)
    }

    fn start_with_context<T>(&self, name: T, parent_cx: &opentelemetry::Context) -> Self::Span
    where
        T: Into<Cow<'static, str>>,
    {
        self.parent
            .read()
            .expect("parent tracer must be available")
            .start_with_context(name, parent_cx)
    }

    fn span_builder<T>(&self, name: T) -> SpanBuilder
    where
        T: Into<Cow<'static, str>>,
    {
        self.parent
            .read()
            .expect("parent tracer must be available")
            .span_builder(name)
    }

    fn build(&self, builder: SpanBuilder) -> Self::Span {
        self.parent
            .read()
            .expect("parent tracer must be available")
            .build(builder)
    }

    fn build_with_context(
        &self,
        builder: SpanBuilder,
        parent_cx: &opentelemetry::Context,
    ) -> Self::Span {
        self.parent
            .read()
            .expect("parent tracer must be available")
            .build_with_context(builder, parent_cx)
    }

    fn in_span<T, F, N>(&self, name: N, f: F) -> T
    where
        F: FnOnce(opentelemetry::Context) -> T,
        N: Into<Cow<'static, str>>,
        Self::Span: Send + Sync + 'static,
    {
        self.parent
            .read()
            .expect("parent tracer must be available")
            .in_span(name, f)
    }
}

impl<S> ReloadTracer<S> {
    pub(crate) fn new(parent: S) -> Self {
        Self {
            parent: Arc::new(RwLock::new(parent)),
        }
    }

    pub(crate) fn reload(&self, new: S) {
        *self
            .parent
            .write()
            .expect("parent tracer must be available") = new;
    }
}