@@ -21,7 +21,7 @@ import {
2121 SimpleSpanProcessor ,
2222 SpanExporter ,
2323} from "@opentelemetry/sdk-trace-node" ;
24- import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions" ;
24+ import { SemanticResourceAttributes , SEMATTRS_HTTP_URL } from "@opentelemetry/semantic-conventions" ;
2525import { VERSION } from "../../version.js" ;
2626import {
2727 OTEL_ATTRIBUTE_PER_EVENT_COUNT_LIMIT ,
@@ -287,17 +287,27 @@ function setLogLevel(level: TracingDiagnosticLogLevel) {
287287}
288288
289289class ExternalSpanExporterWrapper {
290+ private readonly _isExternallySampled : boolean ;
291+
290292 constructor (
291293 private underlyingExporter : SpanExporter ,
292294 private externalTraceId : string ,
293295 private externalTraceContext :
294- | { traceId : string ; spanId : string ; tracestate ?: string }
296+ | { traceId : string ; spanId : string ; tracestate ?: string ; traceFlags ?: string }
295297 | undefined
296- ) { }
298+ ) {
299+ this . _isExternallySampled =
300+ typeof externalTraceContext ?. traceFlags === "string"
301+ ? externalTraceContext . traceFlags === "01"
302+ : true ;
303+ }
297304
298305 private transformSpan ( span : ReadableSpan ) : ReadableSpan | undefined {
299- if ( span . attributes [ SemanticInternalAttributes . SPAN_PARTIAL ] ) {
300- // Skip partial spans
306+ if ( ! this . _isExternallySampled ) {
307+ return ;
308+ }
309+
310+ if ( isSpanInternalOnly ( span ) ) {
301311 return ;
302312 }
303313
@@ -325,8 +335,15 @@ class ExternalSpanExporterWrapper {
325335 traceState : this . externalTraceContext . tracestate
326336 ? new TraceState ( this . externalTraceContext . tracestate )
327337 : undefined ,
328- traceFlags : parentSpanContext ?. traceFlags ?? 0 ,
338+ traceFlags :
339+ typeof this . externalTraceContext . traceFlags === "string"
340+ ? this . externalTraceContext . traceFlags === "01"
341+ ? 1
342+ : 0
343+ : parentSpanContext ?. traceFlags ?? 0 ,
329344 } ;
345+ } else if ( isAttemptSpan ) {
346+ parentSpanContext = undefined ;
330347 }
331348
332349 return {
@@ -360,15 +377,28 @@ class ExternalSpanExporterWrapper {
360377}
361378
362379class ExternalLogRecordExporterWrapper {
380+ private readonly _isExternallySampled : boolean ;
381+
363382 constructor (
364383 private underlyingExporter : LogRecordExporter ,
365384 private externalTraceId : string ,
366385 private externalTraceContext :
367- | { traceId : string ; spanId : string ; tracestate ?: string }
386+ | { traceId : string ; spanId : string ; tracestate ?: string ; traceFlags ?: string }
368387 | undefined
369- ) { }
388+ ) {
389+ this . _isExternallySampled =
390+ typeof externalTraceContext ?. traceFlags === "string"
391+ ? externalTraceContext . traceFlags === "01"
392+ : true ;
393+ }
370394
371395 export ( logs : any [ ] , resultCallback : ( result : any ) => void ) : void {
396+ if ( ! this . _isExternallySampled ) {
397+ this . underlyingExporter . export ( [ ] , resultCallback ) ;
398+
399+ return ;
400+ }
401+
372402 const modifiedLogs = logs . map ( this . transformLogRecord . bind ( this ) ) ;
373403
374404 this . underlyingExporter . export ( modifiedLogs , resultCallback ) ;
@@ -410,3 +440,40 @@ class ExternalLogRecordExporterWrapper {
410440 } ) ;
411441 }
412442}
443+
444+ function isSpanInternalOnly ( span : ReadableSpan ) : boolean {
445+ if ( span . attributes [ SemanticInternalAttributes . SPAN_PARTIAL ] ) {
446+ // Skip partial spans
447+ return true ;
448+ }
449+
450+ const urlPath = span . attributes [ "url.path" ] ;
451+
452+ if ( typeof urlPath === "string" && urlPath === "/api/v1/usage/ingest" ) {
453+ return true ;
454+ }
455+
456+ const httpUrl = span . attributes [ SEMATTRS_HTTP_URL ] ?? span . attributes [ "url.full" ] ;
457+
458+ if ( typeof httpUrl === "string" && httpUrl . includes ( "https://api.trigger.dev" ) ) {
459+ return true ;
460+ }
461+
462+ if ( typeof httpUrl === "string" && httpUrl . includes ( "https://billing.trigger.dev" ) ) {
463+ return true ;
464+ }
465+
466+ if ( typeof httpUrl === "string" && httpUrl . includes ( "https://cloud.trigger.dev" ) ) {
467+ return true ;
468+ }
469+
470+ if ( typeof httpUrl === "string" && httpUrl . includes ( "https://engine.trigger.dev" ) ) {
471+ return true ;
472+ }
473+
474+ if ( typeof httpUrl === "string" && httpUrl . includes ( "/api/v1/usage/ingest" ) ) {
475+ return true ;
476+ }
477+
478+ return false ;
479+ }
0 commit comments