1212//! no-op. Spans and logs use the `tracing` facade (the async-native surface the
1313//! OpenTelemetry ecosystem bridges with `tracing-opentelemetry` /
1414//! `opentelemetry-appender-tracing`), so the host's subscriber decides where
15- //! they go. Spans are attached to futures with [`Instrument`], never a
16- //! [`Span::enter`] guard held across an `.await`: a suspended task would leave
15+ //! they go. Method spans use `#[tracing::instrument]`; the `libsy.run` span is
16+ //! attached to the spawned run task with [`tracing::Instrument`]. Neither holds
17+ //! a [`Span::enter`] guard across an `.await` — a suspended task would leave
1718//! the span entered on its executor thread, mis-parenting every span other
1819//! tasks create there (see the `tracing` docs on spans in asynchronous code).
1920//!
@@ -34,7 +35,7 @@ use std::time::{Duration, Instant};
3435
3536use opentelemetry:: metrics:: Meter ;
3637use opentelemetry:: { global, KeyValue } ;
37- use tracing:: { Instrument , Span } ;
38+ use tracing:: Span ;
3839
3940use crate :: { Context , Decision , Metadata , Response } ;
4041
@@ -49,7 +50,7 @@ const SCOPE: &str = "libsy";
4950pub ( crate ) const ALGORITHM_KEY : & str = "algorithm" ;
5051
5152/// The algorithm label carried by a request context; empty until stamped.
52- fn algorithm_label < S > ( ctx : & Context < S > ) -> & str {
53+ pub ( crate ) fn algorithm_label < S > ( ctx : & Context < S > ) -> & str {
5354 ctx. values
5455 . get ( ALGORITHM_KEY )
5556 . map ( String :: as_str)
@@ -126,48 +127,6 @@ pub(crate) async fn observe_run<S>(
126127 result
127128}
128129
129- /// Drives one offloaded model call inside its own `libsy.llm_call` span,
130- /// recording the call counter, latency histogram, token usage, span fields,
131- /// and failure log when the call resolves.
132- pub ( crate ) async fn observe_llm_call (
133- ctx : & Context ,
134- selected_model : & str ,
135- call : impl Future < Output = Result < Response , BoxErr > > ,
136- ) -> Result < Response , BoxErr > {
137- let algorithm = algorithm_label ( ctx) ;
138- let span = llm_call_span ( algorithm, selected_model) ;
139- async {
140- let started = Instant :: now ( ) ;
141- let result = call. await ;
142- record_llm_call (
143- algorithm,
144- selected_model,
145- started. elapsed ( ) ,
146- & result,
147- & Span :: current ( ) ,
148- ) ;
149- result
150- }
151- . instrument ( span)
152- . await
153- }
154-
155- /// Span covering one *actual* provider API call the crate itself performs —
156- /// the default-client serve path inside [`Algorithm::run`](crate::Algorithm::run).
157- /// `libsy.llm_call` measures fulfillment as the algorithm observes it; this
158- /// span isolates the client call that fulfills it. A host serving calls over
159- /// its own transport should emit an equivalent span in its `LlmClient`.
160- pub ( crate ) fn client_call_span ( ctx : & Context , selected_model : & str ) -> Span {
161- tracing:: info_span!(
162- target: SCOPE ,
163- "libsy.client_call" ,
164- algorithm = algorithm_label( ctx) ,
165- selected_model,
166- outcome = tracing:: field:: Empty ,
167- error = tracing:: field:: Empty ,
168- )
169- }
170-
171130/// Records the outcome fields on the enclosing `libsy.client_call` span. The
172131/// failure itself is not logged here — it propagates to the algorithm, where
173132/// the `libsy.llm_call` recording logs it once.
@@ -179,26 +138,6 @@ pub(crate) fn record_client_call(result: &Result<Response, BoxErr>) {
179138 }
180139}
181140
182- /// Span covering one offloaded model call, a child of the surrounding
183- /// `libsy.run` span. It measures *fulfillment* as the algorithm observes it —
184- /// host queueing and serving included, not just the provider call. `outcome`,
185- /// `error`, and the token-count fields are filled in by [`record_llm_call`]
186- /// when the call resolves.
187- fn llm_call_span ( algorithm : & str , selected_model : & str ) -> Span {
188- tracing:: info_span!(
189- target: SCOPE ,
190- "libsy.llm_call" ,
191- algorithm,
192- selected_model,
193- outcome = tracing:: field:: Empty ,
194- error = tracing:: field:: Empty ,
195- input_tokens = tracing:: field:: Empty ,
196- output_tokens = tracing:: field:: Empty ,
197- total_tokens = tracing:: field:: Empty ,
198- reasoning_tokens = tracing:: field:: Empty ,
199- )
200- }
201-
202141/// Records the end of one algorithm run: the run counter and duration
203142/// histogram, the `outcome`/`error` fields on `span`, and a warn log when the
204143/// run failed.
@@ -226,7 +165,7 @@ fn record_run(algorithm: &str, duration: Duration, result: &Result<Response, Box
226165/// latency histogram, token counters from the response usage (absent fields are
227166/// skipped, not recorded as zero), the `outcome`/`error`/token fields on
228167/// `span`, and a warn log when the call failed.
229- fn record_llm_call (
168+ pub ( crate ) fn record_llm_call (
230169 algorithm : & str ,
231170 selected_model : & str ,
232171 duration : Duration ,
0 commit comments