@@ -20,6 +20,7 @@ import {
20
20
import {
21
21
BatchSpanProcessor ,
22
22
NodeTracerProvider ,
23
+ ReadableSpan ,
23
24
SimpleSpanProcessor ,
24
25
SpanExporter ,
25
26
} from "@opentelemetry/sdk-trace-node" ;
@@ -85,6 +86,7 @@ export type TracingSDKConfig = {
85
86
forceFlushTimeoutMillis ?: number ;
86
87
resource ?: IResource ;
87
88
instrumentations ?: Instrumentation [ ] ;
89
+ exporters ?: SpanExporter [ ] ;
88
90
diagLogLevel ?: TracingDiagnosticLogLevel ;
89
91
} ;
90
92
@@ -111,6 +113,8 @@ export class TracingSDK {
111
113
. merge (
112
114
new Resource ( {
113
115
[ SemanticResourceAttributes . CLOUD_PROVIDER ] : "trigger.dev" ,
116
+ [ SemanticResourceAttributes . SERVICE_NAME ] :
117
+ getEnvVar ( "OTEL_SERVICE_NAME" ) ?? "trigger.dev" ,
114
118
[ SemanticInternalAttributes . TRIGGER ] : true ,
115
119
[ SemanticInternalAttributes . CLI_VERSION ] : VERSION ,
116
120
} )
@@ -153,6 +157,25 @@ export class TracingSDK {
153
157
)
154
158
) ;
155
159
160
+ const externalTraceId = crypto . randomUUID ( ) ;
161
+
162
+ for ( const exporter of config . exporters ?? [ ] ) {
163
+ traceProvider . addSpanProcessor (
164
+ getEnvVar ( "OTEL_BATCH_PROCESSING_ENABLED" ) === "1"
165
+ ? new BatchSpanProcessor ( new ExternalSpanExporterWrapper ( exporter , externalTraceId ) , {
166
+ maxExportBatchSize : parseInt ( getEnvVar ( "OTEL_SPAN_MAX_EXPORT_BATCH_SIZE" ) ?? "64" ) ,
167
+ scheduledDelayMillis : parseInt (
168
+ getEnvVar ( "OTEL_SPAN_SCHEDULED_DELAY_MILLIS" ) ?? "200"
169
+ ) ,
170
+ exportTimeoutMillis : parseInt (
171
+ getEnvVar ( "OTEL_SPAN_EXPORT_TIMEOUT_MILLIS" ) ?? "30000"
172
+ ) ,
173
+ maxQueueSize : parseInt ( getEnvVar ( "OTEL_SPAN_MAX_QUEUE_SIZE" ) ?? "512" ) ,
174
+ } )
175
+ : new SimpleSpanProcessor ( new ExternalSpanExporterWrapper ( exporter , externalTraceId ) )
176
+ ) ;
177
+ }
178
+
156
179
traceProvider . register ( ) ;
157
180
158
181
registerInstrumentations ( {
@@ -236,3 +259,49 @@ function setLogLevel(level: TracingDiagnosticLogLevel) {
236
259
237
260
diag . setLogger ( new DiagConsoleLogger ( ) , diagLogLevel ) ;
238
261
}
262
+
263
+ class ExternalSpanExporterWrapper {
264
+ constructor (
265
+ private underlyingExporter : SpanExporter ,
266
+ private externalTraceId : string
267
+ ) { }
268
+
269
+ private transformSpan ( span : ReadableSpan ) : ReadableSpan | undefined {
270
+ if ( span . attributes [ SemanticInternalAttributes . SPAN_PARTIAL ] ) {
271
+ // Skip partial spans
272
+ return ;
273
+ }
274
+
275
+ const spanContext = span . spanContext ( ) ;
276
+
277
+ return {
278
+ ...span ,
279
+ spanContext : ( ) => ( { ...spanContext , traceId : this . externalTraceId } ) ,
280
+ parentSpanId : span . attributes [ SemanticInternalAttributes . SPAN_ATTEMPT ]
281
+ ? undefined
282
+ : span . parentSpanId ,
283
+ } ;
284
+ }
285
+
286
+ export ( spans : any [ ] , resultCallback : ( result : any ) => void ) : void {
287
+ try {
288
+ const modifiedSpans = spans . map ( this . transformSpan . bind ( this ) ) ;
289
+ this . underlyingExporter . export (
290
+ modifiedSpans . filter ( Boolean ) as ReadableSpan [ ] ,
291
+ resultCallback
292
+ ) ;
293
+ } catch ( e ) {
294
+ console . error ( e ) ;
295
+ }
296
+ }
297
+
298
+ shutdown ( ) : Promise < void > {
299
+ return this . underlyingExporter . shutdown ( ) ;
300
+ }
301
+
302
+ forceFlush ?( ) : Promise < void > {
303
+ return this . underlyingExporter . forceFlush
304
+ ? this . underlyingExporter . forceFlush ( )
305
+ : Promise . resolve ( ) ;
306
+ }
307
+ }
0 commit comments