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
//! Convenience macros for telemetry instrumentation.
pub
/// 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 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