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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
//! 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;
pub use OpenTelemetryConfig;
pub use ;
pub use ;
pub use ToValue;
pub use 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 span;
/// Private module for macro implementation details.
/// Not part of the public API - may change without notice.