@@ -5,8 +5,10 @@ import {
55 defaultTextMapGetter ,
66 defaultTextMapSetter ,
77 diag ,
8+ INVALID_SPAN_CONTEXT ,
89 ROOT_CONTEXT ,
910 type Span ,
11+ type SpanOptions ,
1012 SpanStatusCode ,
1113 trace ,
1214} from "@opentelemetry/api" ;
@@ -52,7 +54,7 @@ export interface OptionOtelHandle {
5254 ) : {
5355 emit : ( record : Omit < LogRecord , "context" > ) => void ;
5456 } ;
55- /** True only for a local Span created by this runtime , not a remote parent. */
57+ /** True only for a recording local Span, not a remote or suppressed parent. */
5658 hasActiveSpan ( ) : boolean ;
5759 readonly propagation : {
5860 /** Capture the current context so delayed iterators can re-enter it. */
@@ -65,6 +67,12 @@ export interface OptionOtelHandle {
6567 run : < T > ( captured : Context , fn : ( ) => T ) => T ;
6668 } ;
6769 shutdown ( ) : Promise < void > ;
70+ /** Run a callback with a Span active only in this runtime's private Context. */
71+ withActiveSpan < T > (
72+ name : string ,
73+ options : SpanOptions & { parentContext ?: Context } ,
74+ fn : ( span : Span ) => Promise < T > | T
75+ ) : Promise < T > ;
6876 withSpan < T > ( name : string , fn : ( ) => Promise < T > | T ) : Promise < T > ;
6977 withSpan < T > (
7078 name : string ,
@@ -186,30 +194,28 @@ export const createOptionOtelRuntime = (
186194 run : ( captured , fn ) => contextManager . with ( captured , fn ) ,
187195 } ;
188196
189- const withSpan = < T > (
190- name : string ,
191- attributesOrFn : Attributes | ( ( ) => Promise < T > | T ) ,
192- maybeFn ?: ( ) => Promise < T > | T
193- ) : Promise < T > => {
194- const fn = typeof attributesOrFn === "function" ? attributesOrFn : maybeFn ;
195- if ( ! fn ) {
196- throw new Error ( "withSpan: function argument is required" ) ;
197- }
198- const attributes =
199- typeof attributesOrFn === "function" ? undefined : attributesOrFn ;
200- const parent = contextManager . active ( ) ;
197+ const withActiveSpan : OptionOtelHandle [ "withActiveSpan" ] = async (
198+ name ,
199+ options ,
200+ fn
201+ ) => {
202+ const { parentContext, ...spanOptions } = options ;
203+ const parent = parentContext ?? contextManager . active ( ) ;
201204 let span : Span ;
202205 try {
203- span = tracer . startSpan ( name , { attributes } , parent ) ;
206+ span = tracer . startSpan ( name , spanOptions , parent ) ;
204207 } catch ( error ) {
205208 reportDiagnostic ( "failed to start Span" , error ) ;
206- return Promise . resolve ( ) . then ( fn ) ;
209+ return await fn ( trace . wrapSpanContext ( INVALID_SPAN_CONTEXT ) ) ;
207210 }
208211
209- const active = trace . setSpan ( parent , span ) . setValue ( localSpanKey , span ) ;
210- return contextManager . with ( active , async ( ) => {
212+ const spanContext = trace . setSpan ( parent , span ) ;
213+ const active = span . isRecording ( )
214+ ? spanContext . setValue ( localSpanKey , span )
215+ : spanContext ;
216+ return await contextManager . with ( active , async ( ) => {
211217 try {
212- return await fn ( ) ;
218+ return await fn ( span ) ;
213219 } catch ( error ) {
214220 try {
215221 span . recordException ( error instanceof Error ? error : String ( error ) ) ;
@@ -232,6 +238,20 @@ export const createOptionOtelRuntime = (
232238 } ) ;
233239 } ;
234240
241+ const withSpan = < T > (
242+ name : string ,
243+ attributesOrFn : Attributes | ( ( ) => Promise < T > | T ) ,
244+ maybeFn ?: ( ) => Promise < T > | T
245+ ) : Promise < T > => {
246+ const fn = typeof attributesOrFn === "function" ? attributesOrFn : maybeFn ;
247+ if ( ! fn ) {
248+ throw new Error ( "withSpan: function argument is required" ) ;
249+ }
250+ const attributes =
251+ typeof attributesOrFn === "function" ? undefined : attributesOrFn ;
252+ return withActiveSpan ( name , { attributes } , ( ) => fn ( ) ) ;
253+ } ;
254+
235255 return {
236256 createLogger ( name , version ) {
237257 const logger : Logger = loggerProvider . getLogger ( name , version ) ;
@@ -260,6 +280,7 @@ export const createOptionOtelRuntime = (
260280 }
261281 return shutdownPromise ;
262282 } ,
283+ withActiveSpan,
263284 withSpan : withSpan as OptionOtelHandle [ "withSpan" ] ,
264285 } ;
265286} ;
0 commit comments