Skip to main content

TelemetryBuilder

Struct TelemetryBuilder 

Source
pub struct TelemetryBuilder { /* private fields */ }
Expand description

Builder for configuring telemetry options incrementally.

Created via Telemetry::builder or Telemetry::from_env. Call .init() to consume the builder and start telemetry.

§Example

use std::time::Duration;

let _handles = otel_bootstrap::Telemetry::builder("my-service")
    .with_version("1.2.3")
    .with_environment("staging")
    .with_metrics(true)
    .with_shutdown_timeout(Duration::from_secs(10))
    .init()
    .unwrap();

Implementations§

Source§

impl TelemetryBuilder

Source

pub fn with_log_filter(self, directive: impl Into<String>) -> Self

Set the tracing filter without mutating process-global environment.

The directive is parsed during init. Invalid directives fail initialization before exporters or the global subscriber are built.

Source

pub fn with_log_format(self, format: LogFormat) -> Self

Set stdout log encoding without mutating process-global environment.

Source

pub fn with_version(self, version: &str) -> Self

Set the service version (maps to service.version resource attribute).

Source

pub fn with_environment(self, environment: &str) -> Self

Set the deployment environment (maps to deployment.environment.name).

Source

pub fn with_mtls(self, material: MtlsMaterial) -> Self

Enable mTLS on the gRPC OTLP exporter (requires the grpc-mtls feature).

The material is read once at init time; the resulting tonic Channel is built once and reused for the lifetime of the process.

Forces the protocol to ExportProtocol::Grpc regardless of OTEL_EXPORTER_OTLP_PROTOCOL or any prior with_protocol(...) call. Pairs with a collector configured with client_ca_file.

§Rotation

In-process auto-rotation is not yet implemented — when the underlying SVID rotates (typically every 1h), the existing tonic Channel keeps presenting the old cert and exports start failing. Two-part mitigation until a proper rotation watcher lands:

  1. Issue long-lived client certs (≥365 days) so manual rotation is infrequent.
  2. Rely on natural pod restarts (deploys, reschedules) to pick up fresh material — every restart re-reads the SVID at this call.

Rotation as a first-class feature is tracked as an immediate follow-up (see CHANGELOG).

Source

pub fn with_sampler(self, sampler: TraceSampler) -> Self

Set an explicit trace sampler. If not set, falls back to OTEL_TRACES_SAMPLER env var, then always-on.

Source

pub fn with_metrics(self, enabled: bool) -> Self

Enable or disable metrics export (default: true).

Source

pub fn with_runtime_metrics(self, enabled: bool) -> Self

Enable or disable the built-in process/runtime gauges (default: true).

Covers process uptime and resident memory plus Tokio worker count, live task count, global queue depth and scheduler delay — see runtime_metrics for what each answers.

On by default because these are the instruments that distinguish “the runtime never polled us” from “the thing we called was slow”, and a service that has to opt in generally has not, precisely when it matters. They are registered on the MeterProvider this builder installs, so they cost nothing when with_metrics(false) is set — no provider is created and this is never reached.

Turn off for a process where the extra series are unwanted, e.g. a short-lived CLI whose runtime state carries no operational meaning.

Source

pub fn with_protocol(self, protocol: ExportProtocol) -> Self

Set the export protocol explicitly. If not set, falls back to OTEL_EXPORTER_OTLP_PROTOCOL, then the compiled-in default (grpc when the grpc feature is enabled, http/protobuf otherwise).

Source

pub fn with_max_export_batch_size(self, size: usize) -> Self

Set the maximum number of spans exported in a single batch (default: 512).

Overrides OTEL_BSP_MAX_EXPORT_BATCH_SIZE when set programmatically. The env var is still read as a fallback when this method is not called.

Source

pub fn with_metric_export_interval(self, interval: Duration) -> Self

Set the interval between metric exports (default: 60 s).

Returns an error at build time if interval is zero. Overrides OTEL_METRIC_EXPORT_INTERVAL when set programmatically.

Source

pub fn with_logs(self, enabled: bool) -> Self

Enable or disable log export via the OTLP log bridge (default: false).

When enabled, tracing events are forwarded to an OTLP LogExporter in addition to the existing stdout fmt layer. This allows structured logs to be correlated with traces in backends like Grafana Loki or Datadog.

Source

pub fn with_propagated_span_fields( self, fields: &'static [&'static str], ) -> Self

Override the set of span field names propagated into OTLP log records.

The default set is PROPAGATED_SPAN_FIELDS. Callers that add extra tracing fields (e.g. "request.id", "enduser.id") can extend it:

const MY_FIELDS: &[&str] = &["request.id", "enduser.id", "tenant.id"];
let _handles = otel_bootstrap::Telemetry::builder("my-service")
    .with_logs(true)
    .with_propagated_span_fields(MY_FIELDS)
    .init();
Source

pub fn with_export_timeout(self, timeout: Duration) -> Self

Set the OTLP export timeout explicitly. If not set, falls back to OTEL_EXPORTER_OTLP_TIMEOUT (in milliseconds), then the SDK default of 10 000 ms.

Source

pub fn with_shutdown_timeout(self, timeout: Duration) -> Self

Set the maximum time to wait for provider shutdown when the TelemetryHandles is dropped (default: 5 s).

If the timeout expires a warning is logged and the drop completes without panicking. The background shutdown thread is abandoned and the providers may not have flushed all pending data.

Source

pub fn with_profiling(self, endpoint: &str) -> Self

Enable continuous profiling via pyroscope (requires the profiling-bridge-pyroscope-rs feature).

The bridge pushes profiles over plain HTTP/loopback to a local SPIFFE-terminating sidecar (or an already-mTLS’d endpoint reachable without client-side TLS material). pyroscope-rs hardcodes its own HTTP client internally with no hook for custom TLS/identity, so in-process mTLS is not possible; the sidecar carries the workload identity upstream.

The endpoint must target loopback only (127.0.0.1, ::1, localhost, or a unix socket) per ADR platform/0203 AC1 — enforced at init time.

§Example
let _handles = otel_bootstrap::Telemetry::builder("my-service")
    .with_profiling("http://localhost:4040")
    .init()?;
Source

pub fn with_meter_provider_setup<F>(self, setup: F) -> Self

Add a custom tracing_subscriber::Layer to the subscriber stack.

Multiple layers can be added by chaining calls. Each layer is composed with the built-in EnvFilter, fmt, and OpenTelemetry layers.

Insertion order in the subscriber stack (inner → outer, i.e. first-added to last-added):

registry → custom layers → EnvFilter → fmt → OTel

Because EnvFilter is outer, it can suppress events before they reach the fmt and OTel layers; custom layers receive events independently according to their own enabled() implementation.

§Example
let _handles = otel_bootstrap::Telemetry::builder("my-service")
    .with_layer(tracing_subscriber::fmt::layer().with_target(false))
    .init()?;

Customise the MeterProviderBuilder before it is built.

Runs after the built-in OTLP PeriodicReader is attached (when with_metrics is enabled) and before .build() is called. The closure is the escape hatch for everything the explicit builder methods do not cover — most importantly, installing additional MetricReaders like opentelemetry-prometheus alongside the OTLP push, so the same instruments fan out to multiple transports without double-counting.

May be called multiple times; closures run in registration order. Has no effect when with_metrics(false) is also set on the builder — when metrics are disabled, no MeterProvider is created at all.

MetricReader is intentionally not nameable from outside opentelemetry_sdk, so the closure form is the only way to attach readers without leaking unstable trait names through this crate’s public API.

§Example
// With `opentelemetry-prometheus` in scope:
let registry = prometheus::Registry::new();
let exporter = opentelemetry_prometheus::exporter()
    .with_registry(registry.clone())
    .build()?;
let _handles = otel_bootstrap::Telemetry::builder("my-service")
    .with_meter_provider_setup(move |b| b.with_reader(exporter))
    .init()?;
// ...mount `registry` at GET /metrics in your HTTP layer.
Source

pub fn with_layer<L>(self, layer: L) -> Self
where L: Layer<Registry> + Send + Sync + 'static,

Source

pub fn init(self) -> Result<TelemetryHandles, Box<dyn Error>>

Consume the builder and initialise OpenTelemetry.

Installs a global tracer provider, meter provider (if enabled), and a tracing subscriber. Returns an error if any provider fails to build (e.g. unknown sampler name, zero metric interval).

§Example
let handles = otel_bootstrap::Telemetry::builder("my-service")
    .with_metrics(false)
    .init()
    .expect("telemetry init failed");
handles.shutdown().ok();

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more