11/* eslint-disable @typescript-eslint/no-this-alias */
22/* eslint-disable @typescript-eslint/ban-types */
3- import { context , Context , diag , propagation , ROOT_CONTEXT , Span , SpanKind , SpanStatusCode , trace } from "@opentelemetry/api" ;
3+ import { context , Context , diag , Exception , propagation , ROOT_CONTEXT , Span , SpanAttributes , SpanAttributeValue , SpanContext , SpanKind , SpanStatus , SpanStatusCode , TimeInput , trace } from "@opentelemetry/api" ;
44import { RPCMetadata , RPCType , setRPCMetadata } from "@opentelemetry/core" ;
55import {
66 InstrumentationBase ,
@@ -386,7 +386,7 @@ export class WSInstrumentation extends InstrumentationBase<WS> {
386386 upgradeHead : Buffer ,
387387 callback : ( client : WebSocket , request : IncomingMessage ) => void
388388 ) {
389- const parentSpan = self . _requestSpans . get ( request ) ;
389+ const parentSpan = self . _requestSpans . get ( request ) !== undefined ? new TimeStampedSpan ( self . _requestSpans . get ( request ) ! ) : undefined ;
390390 const span = self . tracer . startSpan ( `WS upgrade` , {
391391 kind : SpanKind . SERVER ,
392392 attributes : getIncomingRequestAttributes ( request , {
@@ -419,7 +419,9 @@ export class WSInstrumentation extends InstrumentationBase<WS> {
419419 parentSpan ?. setAttributes ( {
420420 [ SemanticAttributes . HTTP_STATUS_CODE ] : 101 ,
421421 } ) ;
422- parentSpan ?. end ( ) ;
422+ if ( parentSpan ) {
423+ parentSpan . endTime = new Date ( ) ; // Set the end time to the current time but don't end the span yet
424+ }
423425 self . _requestSpans . delete ( request ) ;
424426
425427 return callback . call ( this , websocket , request ) ;
@@ -430,3 +432,49 @@ export class WSInstrumentation extends InstrumentationBase<WS> {
430432 } ;
431433 } ;
432434}
435+
436+ class TimeStampedSpan implements Span {
437+ constructor ( private readonly span : Span ) { }
438+ spanContext ( ) : SpanContext {
439+ return this . span . spanContext ( ) ;
440+ }
441+ setAttribute ( key : string , value : SpanAttributeValue ) : this {
442+ this . span . setAttribute ( key , value ) ;
443+ return this ;
444+ }
445+ setAttributes ( attributes : SpanAttributes ) : this {
446+ this . span . setAttributes ( attributes ) ;
447+ return this ;
448+ }
449+ addEvent ( name : string , attributesOrStartTime ?: SpanAttributes | TimeInput , startTime ?: TimeInput ) : this {
450+ this . span . addEvent ( name , attributesOrStartTime , startTime ) ;
451+ return this ;
452+ }
453+ setStatus ( status : SpanStatus ) : this {
454+ this . span . setStatus ( status ) ;
455+ return this ;
456+ }
457+ updateName ( name : string ) : this {
458+ this . span . updateName ( name ) ;
459+ return this ;
460+ }
461+ isRecording ( ) : boolean {
462+ return this . span . isRecording ( ) ;
463+ }
464+ recordException ( exception : Exception , time ?: TimeInput ) : void {
465+ this . span . recordException ( exception , time ) ;
466+ }
467+ private _endTime : TimeInput | undefined ;
468+
469+ set endTime ( endTime : TimeInput ) {
470+ this . _endTime = endTime ;
471+ }
472+
473+ end ( endTime ?: TimeInput ) : void {
474+ if ( this . _endTime ) {
475+ this . span . end ( this . _endTime ) ;
476+ } else {
477+ this . span . end ( endTime ) ;
478+ }
479+ }
480+ }
0 commit comments