1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! OpenTelemetry tracing export (feature `opentelemetry`).
//!
//! `amalgam`'s core already emits [`tracing`] spans and events (for example
//! `amalgam.get_or_set`). This module wires those spans to an OTLP collector
//! such as [Jaeger] or the [OpenTelemetry Collector] so you can see them on a
//! distributed-tracing backend, with no changes to your cache code.
//!
//! Call [`init_otlp`] once at startup and keep the returned [`OtelGuard`] alive
//! for the lifetime of the process; dropping it flushes any buffered spans and
//! shuts the exporter down cleanly.
//!
//! ```no_run
//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
//! // Keep the guard alive for as long as you want spans exported.
//! let _otel = amalgam::otel::init_otlp("my-service", "http://127.0.0.1:4317")?;
//!
//! let cache: amalgam::Cache<String> = amalgam::Cache::builder().build();
//! let _ = cache
//! .get_or_set("k", |ctx| async move { Ok(ctx.value("v".to_owned())) })
//! .await?;
//! // `_otel` is dropped here, flushing spans to the collector.
//! # Ok(())
//! # }
//! ```
//!
//! [Jaeger]: https://www.jaegertracing.io/
//! [OpenTelemetry Collector]: https://opentelemetry.io/docs/collector/
use TracerProvider as _;
use WithExportConfig as _;
use Resource;
use SdkTracerProvider;
use SubscriberExt as _;
use SubscriberInitExt as _;
use ;
/// Default [`EnvFilter`] directives used when `RUST_LOG` is unset: everything at
/// `info`, but `amalgam`'s own spans/events down to `debug`.
const DEFAULT_FILTER: &str = "info,amalgam=debug";
/// Flushes and shuts down the OpenTelemetry tracer provider on drop.
///
/// Returned by [`init_otlp`]. Hold it for as long as you want spans exported —
/// typically for the whole program. When it drops, buffered spans are flushed
/// to the collector and the provider is shut down.
///
/// This type is `#[must_use]`: binding it to `_` would drop it immediately and
/// tear the exporter down before any spans are recorded. Bind it to a named
/// variable (for example `let _otel = init_otlp(..)?;`) instead.
/// Initializes OTLP span export and installs a global `tracing` subscriber.
///
/// Builds an OTLP span exporter (gRPC/tonic) pointed at `endpoint`, wraps it in
/// a batching [`SdkTracerProvider`] whose [`Resource`] carries
/// `service.name = service_name`, sets that provider as the global
/// OpenTelemetry tracer provider, and installs a [`tracing_subscriber`]
/// [`Registry`](tracing_subscriber::Registry) composed of:
///
/// * a [`tracing_opentelemetry`] layer bridging `tracing` spans to OpenTelemetry,
/// * an [`EnvFilter`] (from `RUST_LOG`, defaulting to `info,amalgam=debug`), and
/// * a `fmt` layer for human-readable console output.
///
/// After this returns, every `tracing` span the crate emits (such as
/// `amalgam.get_or_set`) is exported to the collector at `endpoint`.
///
/// `endpoint` is a gRPC URL, for example `http://127.0.0.1:4317` (the default
/// OTLP/gRPC port).
///
/// Keep the returned [`OtelGuard`] alive for as long as you want spans exported;
/// see its documentation.
///
/// # Errors
///
/// Returns an error if the OTLP exporter cannot be built (for example an invalid
/// `endpoint`), or if a global `tracing` subscriber is already installed.
///
/// # Examples
///
/// ```no_run
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
/// let _otel = amalgam::otel::init_otlp("amalgam-example", "http://127.0.0.1:4317")?;
/// # Ok(())
/// # }
/// ```