@@ -6,36 +6,56 @@ import api, { type Span, type SpanOptions, SpanStatusCode } from '@opentelemetry
66 */
77export const ATTR_PEER_SERVICE = 'peer.service' as const ;
88
9- export const tracer = api . trace . getTracer ( '@chialab/sveltekit-utils' ) ;
9+ export const traceDecoratorFactory = ( name : string , version ?: string ) => {
10+ const tracer = api . trace . getTracer ( name , version ) ;
1011
11- /**
12- * Decorator to trace a method or function by wrapping it in a new active span.
13- *
14- * @param options Span options
15- */
16- export const trace =
17- ( options : SpanOptions = { } ) =>
18- ( _ : any , method : PropertyKey , descriptor : PropertyDescriptor ) => ( {
19- ...descriptor ,
20- value ( ...args : any [ ] ) {
21- return tracer . startActiveSpan (
22- [ this ?. constructor ?. name , method ] . filter ( Boolean ) . join ( '.' ) ,
23- options ,
24- async ( span : Span ) => {
12+ return < This , Value extends ( this : This , ...args : any ) => unknown > ( options : SpanOptions = { } ) =>
13+ ( target : Value , ctx : ClassMethodDecoratorContext < This , Value > ) : Value => {
14+ type R = ReturnType < Value > ;
15+
16+ return function ( this : This , ...args : Parameters < Value > ) : R {
17+ // @ts -expect-error Typing this properly would be cumbersome.
18+ const className = ctx . static ? this . name : this . constructor . name ;
19+
20+ return tracer . startActiveSpan ( [ className , ctx . name ] . filter ( Boolean ) . join ( '.' ) , options , ( span : Span ) : R => {
2521 try {
26- // Wait for the wrapped function to end before closing the span and returning
27- return await descriptor . value . call ( this , ...args ) ;
28- } catch ( e ) {
22+ const result = target . call ( this , ...args ) as R ;
23+ if ( result && typeof result === 'object' && 'then' in result && typeof result . then === 'function' ) {
24+ return result . then (
25+ ( result : R ) => {
26+ span . end ( ) ;
27+
28+ return result ;
29+ } ,
30+ ( err : unknown ) => {
31+ span . setStatus ( { code : SpanStatusCode . ERROR } ) ;
32+ if ( err instanceof Error ) {
33+ span . recordException ( err ) ;
34+ }
35+ span . end ( ) ;
36+
37+ throw err ;
38+ } ,
39+ ) ;
40+ }
41+
42+ return result ;
43+ } catch ( err : unknown ) {
2944 span . setStatus ( { code : SpanStatusCode . ERROR } ) ;
30- if ( e instanceof Error ) {
31- span . recordException ( e ) ;
45+ if ( err instanceof Error ) {
46+ span . recordException ( err ) ;
3247 }
3348
34- throw e ;
49+ throw err ;
3550 } finally {
3651 span . end ( ) ;
3752 }
38- } ,
39- ) ;
40- } ,
41- } ) ;
53+ } ) ;
54+ } as Value ;
55+ } ;
56+ } ;
57+
58+ /**
59+ * Decorator to trace a method or function by wrapping it in a new active span.
60+ */
61+ export const trace = traceDecoratorFactory ( '@chialab/sveltekit-utils' ) ;
0 commit comments