@@ -3,16 +3,47 @@ import { type Instrumentation, registerInstrumentations } from '@opentelemetry/i
33/** Exported only for tests. */
44export const INSTRUMENTED : Record < string , Instrumentation > = { } ;
55
6- /**
7- * Instrument an OpenTelemetry instrumentation once.
8- * This will skip running instrumentation again if it was already instrumented.
9- */
6+ export function generateInstrumentOnce <
7+ Options ,
8+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9+ InstrumentationClass extends new ( ...args : any [ ] ) => Instrumentation ,
10+ > (
11+ name : string ,
12+ instrumentationClass : InstrumentationClass ,
13+ optionsCallback : ( options : Options ) => ConstructorParameters < InstrumentationClass > [ 0 ] ,
14+ ) : ( ( options : Options ) => InstanceType < InstrumentationClass > ) & { id : string } ;
1015export function generateInstrumentOnce <
1116 Options = unknown ,
1217 InstrumentationInstance extends Instrumentation = Instrumentation ,
1318> (
1419 name : string ,
1520 creator : ( options ?: Options ) => InstrumentationInstance ,
21+ ) : ( ( options ?: Options ) => InstrumentationInstance ) & { id : string } ;
22+ /**
23+ * Instrument an OpenTelemetry instrumentation once.
24+ * This will skip running instrumentation again if it was already instrumented.
25+ */
26+ export function generateInstrumentOnce < Options > (
27+ name : string ,
28+ creatorOrClass : ( new ( ...args : any [ ] ) => Instrumentation ) | ( ( options ?: Options ) => Instrumentation ) ,
29+ optionsCallback ?: ( options : Options ) => unknown ,
30+ ) : ( ( options : Options ) => Instrumentation ) & { id : string } {
31+ if ( optionsCallback ) {
32+ return _generateInstrumentOnceWithOptions (
33+ name ,
34+ creatorOrClass as new ( ...args : unknown [ ] ) => Instrumentation ,
35+ optionsCallback ,
36+ ) ;
37+ }
38+
39+ return _generateInstrumentOnce ( name , creatorOrClass as ( options ?: Options ) => Instrumentation ) ;
40+ }
41+
42+ // The plain version without handling of options
43+ // Should not be used with custom options that are mutated in the creator!
44+ function _generateInstrumentOnce < Options = unknown , InstrumentationInstance extends Instrumentation = Instrumentation > (
45+ name : string ,
46+ creator : ( options ?: Options ) => InstrumentationInstance ,
1647) : ( ( options ?: Options ) => InstrumentationInstance ) & { id : string } {
1748 return Object . assign (
1849 ( options ?: Options ) => {
@@ -38,6 +69,40 @@ export function generateInstrumentOnce<
3869 ) ;
3970}
4071
72+ // This version handles options properly
73+ function _generateInstrumentOnceWithOptions <
74+ Options ,
75+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
76+ InstrumentationClass extends new ( ...args : any [ ] ) => Instrumentation ,
77+ > (
78+ name : string ,
79+ instrumentationClass : InstrumentationClass ,
80+ optionsCallback : ( options : Options ) => ConstructorParameters < InstrumentationClass > [ 0 ] ,
81+ ) : ( ( options : Options ) => InstanceType < InstrumentationClass > ) & { id : string } {
82+ return Object . assign (
83+ ( _options : Options ) => {
84+ const options = optionsCallback ( _options ) ;
85+
86+ const instrumented = INSTRUMENTED [ name ] as InstanceType < InstrumentationClass > | undefined ;
87+ if ( instrumented ) {
88+ // Ensure we update options
89+ instrumented . setConfig ( options ) ;
90+ return instrumented ;
91+ }
92+
93+ const instrumentation = new instrumentationClass ( options ) as InstanceType < InstrumentationClass > ;
94+ INSTRUMENTED [ name ] = instrumentation ;
95+
96+ registerInstrumentations ( {
97+ instrumentations : [ instrumentation ] ,
98+ } ) ;
99+
100+ return instrumentation ;
101+ } ,
102+ { id : name } ,
103+ ) ;
104+ }
105+
41106/**
42107 * Ensure a given callback is called when the instrumentation is actually wrapping something.
43108 * This can be used to ensure some logic is only called when the instrumentation is actually active.
0 commit comments