autotel 2.25.2 → 2.25.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +152 -1
  2. package/dist/attributes.d.cts +2 -2
  3. package/dist/attributes.d.ts +2 -2
  4. package/dist/auto.cjs +6 -6
  5. package/dist/auto.js +4 -4
  6. package/dist/{chunk-BGVKKL2N.cjs → chunk-7FIGORWI.cjs} +46 -2
  7. package/dist/chunk-7FIGORWI.cjs.map +1 -0
  8. package/dist/{chunk-4KGC5N3J.cjs → chunk-A5ZUL2RZ.cjs} +16 -16
  9. package/dist/{chunk-4KGC5N3J.cjs.map → chunk-A5ZUL2RZ.cjs.map} +1 -1
  10. package/dist/{chunk-SR35DG5A.js → chunk-BBBWDIYQ.js} +27 -13
  11. package/dist/chunk-BBBWDIYQ.js.map +1 -0
  12. package/dist/{chunk-QUW4I2OI.js → chunk-CMUM4JQI.js} +3 -3
  13. package/dist/{chunk-QUW4I2OI.js.map → chunk-CMUM4JQI.js.map} +1 -1
  14. package/dist/{chunk-MNMLCLHH.cjs → chunk-EEJGUBWV.cjs} +5 -5
  15. package/dist/{chunk-MNMLCLHH.cjs.map → chunk-EEJGUBWV.cjs.map} +1 -1
  16. package/dist/{chunk-W4EUTSB2.cjs → chunk-HZ3FYBJG.cjs} +27 -12
  17. package/dist/chunk-HZ3FYBJG.cjs.map +1 -0
  18. package/dist/{chunk-L627YSSP.cjs → chunk-I6JPSD4R.cjs} +9 -9
  19. package/dist/{chunk-L627YSSP.cjs.map → chunk-I6JPSD4R.cjs.map} +1 -1
  20. package/dist/{chunk-JVICEM6W.cjs → chunk-ITYASFHQ.cjs} +91 -19
  21. package/dist/chunk-ITYASFHQ.cjs.map +1 -0
  22. package/dist/{chunk-XRKAL7WJ.cjs → chunk-JSNUWSBH.cjs} +6 -6
  23. package/dist/chunk-JSNUWSBH.cjs.map +1 -0
  24. package/dist/{chunk-GVLK7YUU.cjs → chunk-KZEC4CHV.cjs} +6 -4
  25. package/dist/chunk-KZEC4CHV.cjs.map +1 -0
  26. package/dist/{chunk-UKUYBUFQ.cjs → chunk-MN6PZ4AN.cjs} +7 -7
  27. package/dist/{chunk-UKUYBUFQ.cjs.map → chunk-MN6PZ4AN.cjs.map} +1 -1
  28. package/dist/{chunk-VXLEJWLY.js → chunk-MNBAXRVG.js} +89 -17
  29. package/dist/chunk-MNBAXRVG.js.map +1 -0
  30. package/dist/{chunk-6YIDHH2S.cjs → chunk-OFPZULMQ.cjs} +32 -10
  31. package/dist/chunk-OFPZULMQ.cjs.map +1 -0
  32. package/dist/{chunk-IKRHEUS7.js → chunk-OPTGXEVN.js} +370 -351
  33. package/dist/chunk-OPTGXEVN.js.map +1 -0
  34. package/dist/{chunk-77PLEJ54.js → chunk-QDREXAD7.js} +4 -4
  35. package/dist/{chunk-77PLEJ54.js.map → chunk-QDREXAD7.js.map} +1 -1
  36. package/dist/{chunk-RWOVNF3V.cjs → chunk-QQLP4M6W.cjs} +400 -381
  37. package/dist/chunk-QQLP4M6W.cjs.map +1 -0
  38. package/dist/{chunk-YTGF4L2C.js → chunk-RUD7KS4R.js} +27 -5
  39. package/dist/chunk-RUD7KS4R.js.map +1 -0
  40. package/dist/{chunk-USSL3D6L.js → chunk-S4OFEXLA.js} +6 -6
  41. package/dist/chunk-S4OFEXLA.js.map +1 -0
  42. package/dist/{chunk-XND7WBVX.js → chunk-VYA6QDNA.js} +43 -3
  43. package/dist/chunk-VYA6QDNA.js.map +1 -0
  44. package/dist/{chunk-KUSYIHW7.js → chunk-WYP6OOCT.js} +3 -3
  45. package/dist/{chunk-KUSYIHW7.js.map → chunk-WYP6OOCT.js.map} +1 -1
  46. package/dist/{chunk-4SCBD22Z.js → chunk-XB2GITM5.js} +4 -4
  47. package/dist/{chunk-4SCBD22Z.js.map → chunk-XB2GITM5.js.map} +1 -1
  48. package/dist/{chunk-X4RMFFMR.js → chunk-XDKK53OL.js} +6 -4
  49. package/dist/chunk-XDKK53OL.js.map +1 -0
  50. package/dist/correlation-id.cjs +10 -9
  51. package/dist/correlation-id.d.cts +4 -1
  52. package/dist/correlation-id.d.ts +4 -1
  53. package/dist/correlation-id.js +2 -1
  54. package/dist/decorators.cjs +8 -8
  55. package/dist/decorators.js +7 -7
  56. package/dist/event.cjs +10 -9
  57. package/dist/event.js +7 -6
  58. package/dist/functional.cjs +14 -14
  59. package/dist/functional.js +7 -7
  60. package/dist/http.cjs +2 -2
  61. package/dist/http.js +1 -1
  62. package/dist/index.cjs +85 -65
  63. package/dist/index.d.cts +4 -4
  64. package/dist/index.d.ts +4 -4
  65. package/dist/index.js +16 -16
  66. package/dist/{init-Q4uIQKbq.d.cts → init-CIzpC5kZ.d.cts} +9 -2
  67. package/dist/{init-ls4xSZe5.d.ts → init-C_PiC_Su.d.ts} +9 -2
  68. package/dist/instrumentation.cjs +12 -12
  69. package/dist/instrumentation.cjs.map +1 -1
  70. package/dist/instrumentation.js +4 -4
  71. package/dist/instrumentation.js.map +1 -1
  72. package/dist/messaging-adapters.d.cts +1 -1
  73. package/dist/messaging-adapters.d.ts +1 -1
  74. package/dist/messaging.cjs +11 -11
  75. package/dist/messaging.d.cts +1 -1
  76. package/dist/messaging.d.ts +1 -1
  77. package/dist/messaging.js +8 -8
  78. package/dist/metric-helpers.d.cts +1 -1
  79. package/dist/metric-helpers.d.ts +1 -1
  80. package/dist/sampling.cjs +26 -10
  81. package/dist/sampling.d.cts +49 -1
  82. package/dist/sampling.d.ts +49 -1
  83. package/dist/sampling.js +1 -1
  84. package/dist/semantic-helpers.cjs +12 -12
  85. package/dist/semantic-helpers.js +8 -8
  86. package/dist/tail-sampling-processor.cjs +6 -2
  87. package/dist/tail-sampling-processor.d.cts +2 -2
  88. package/dist/tail-sampling-processor.d.ts +2 -2
  89. package/dist/tail-sampling-processor.js +5 -1
  90. package/dist/trace-helpers.d.cts +1 -1
  91. package/dist/trace-helpers.d.ts +1 -1
  92. package/dist/{utils-D1trOLNm.d.ts → utils-Buel3cj0.d.ts} +1 -1
  93. package/dist/{utils-DuNJfXSH.d.cts → utils-CbUkl8r1.d.cts} +1 -1
  94. package/dist/webhook.cjs +8 -8
  95. package/dist/webhook.js +7 -7
  96. package/dist/workflow-distributed.cjs +9 -9
  97. package/dist/workflow-distributed.js +7 -7
  98. package/dist/workflow.cjs +12 -12
  99. package/dist/workflow.js +8 -8
  100. package/dist/yaml-config.cjs +5 -5
  101. package/dist/yaml-config.d.cts +5 -4
  102. package/dist/yaml-config.d.ts +5 -4
  103. package/dist/yaml-config.js +2 -2
  104. package/package.json +1 -1
  105. package/src/correlation-id.ts +10 -5
  106. package/src/env-config.test.ts +77 -0
  107. package/src/env-config.ts +106 -0
  108. package/src/functional.ts +447 -421
  109. package/src/index.ts +6 -0
  110. package/src/init.customization.test.ts +61 -0
  111. package/src/init.integrations.test.ts +6 -1
  112. package/src/init.ts +23 -13
  113. package/src/instrumentation.ts +1 -1
  114. package/src/sampling.test.ts +96 -3
  115. package/src/sampling.ts +90 -0
  116. package/src/tail-sampling-processor.test.ts +26 -22
  117. package/src/tail-sampling-processor.ts +8 -4
  118. package/src/trace-context.test.ts +73 -0
  119. package/src/trace-context.ts +44 -12
  120. package/src/yaml-config.test.ts +71 -0
  121. package/src/yaml-config.ts +32 -2
  122. package/dist/chunk-6YIDHH2S.cjs.map +0 -1
  123. package/dist/chunk-BGVKKL2N.cjs.map +0 -1
  124. package/dist/chunk-GVLK7YUU.cjs.map +0 -1
  125. package/dist/chunk-IKRHEUS7.js.map +0 -1
  126. package/dist/chunk-JVICEM6W.cjs.map +0 -1
  127. package/dist/chunk-RWOVNF3V.cjs.map +0 -1
  128. package/dist/chunk-SR35DG5A.js.map +0 -1
  129. package/dist/chunk-USSL3D6L.js.map +0 -1
  130. package/dist/chunk-VXLEJWLY.js.map +0 -1
  131. package/dist/chunk-W4EUTSB2.cjs.map +0 -1
  132. package/dist/chunk-X4RMFFMR.js.map +0 -1
  133. package/dist/chunk-XND7WBVX.js.map +0 -1
  134. package/dist/chunk-XRKAL7WJ.cjs.map +0 -1
  135. package/dist/chunk-YTGF4L2C.js.map +0 -1
package/src/functional.ts CHANGED
@@ -42,11 +42,18 @@ import {
42
42
  } from '@opentelemetry/api';
43
43
  import { getConfig } from './config';
44
44
  import { getConfig as getInitConfig, getSdk } from './init';
45
- import { type Sampler, type SamplingContext, AlwaysSampler } from './sampling';
45
+ import {
46
+ type Sampler,
47
+ type SamplingContext,
48
+ AlwaysSampler,
49
+ AUTOTEL_SAMPLING_TAIL_KEEP,
50
+ AUTOTEL_SAMPLING_TAIL_EVALUATED,
51
+ } from './sampling';
46
52
  import { getEventQueue } from './track';
47
53
  import type { TraceContext } from './trace-context';
48
54
  import {
49
55
  createTraceContext,
56
+ enterOrRun,
50
57
  getActiveContextWithBaggage,
51
58
  getContextStorage,
52
59
  } from './trace-context';
@@ -762,160 +769,166 @@ function wrapWithTracing<TArgs extends unknown[], TReturn>(
762
769
  spanOptions.kind = options.spanKind;
763
770
  }
764
771
 
765
- return tracer.startActiveSpan(spanName, spanOptions, async (span) => {
766
- // Run within operation context so events can auto-capture operation.name
767
- return runInOperationContext(spanName, async () => {
768
- let shouldKeepSpan = true;
772
+ const parentContext = getActiveContextWithBaggage();
773
+ return tracer.startActiveSpan(
774
+ spanName,
775
+ spanOptions,
776
+ parentContext,
777
+ async (span) => {
778
+ // Run within operation context so events can auto-capture operation.name
779
+ return runInOperationContext(spanName, async () => {
780
+ let shouldKeepSpan = true;
781
+
782
+ setSpanName(span, spanName);
783
+
784
+ // Initialize context storage with the active context BEFORE creating trace context
785
+ const initialContext = context.active();
786
+ const contextStorage = getContextStorage();
787
+ if (!contextStorage.getStore()) {
788
+ enterOrRun(contextStorage, initialContext);
789
+ }
769
790
 
770
- setSpanName(span, spanName);
791
+ const ctxValue = createTraceContext(span);
792
+ const fn = fnFactory(ctxValue);
793
+ const argsAttributes = options.attributesFromArgs
794
+ ? options.attributesFromArgs(args)
795
+ : {};
771
796
 
772
- // Initialize context storage with the active context BEFORE creating trace context
773
- const initialContext = context.active();
774
- const contextStorage = getContextStorage();
775
- if (!contextStorage.getStore()) {
776
- contextStorage.enterWith(initialContext);
777
- }
797
+ const handleTailSampling = (
798
+ success: boolean,
799
+ duration: number,
800
+ error?: unknown,
801
+ ) => {
802
+ if (
803
+ needsTailSampling &&
804
+ 'shouldKeepTrace' in sampler &&
805
+ typeof sampler.shouldKeepTrace === 'function'
806
+ ) {
807
+ shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
808
+ success,
809
+ duration,
810
+ error,
811
+ });
812
+ span.setAttribute(AUTOTEL_SAMPLING_TAIL_KEEP, shouldKeepSpan);
813
+ span.setAttribute(AUTOTEL_SAMPLING_TAIL_EVALUATED, true);
814
+ }
815
+ };
778
816
 
779
- const ctxValue = createTraceContext(span);
780
- const fn = fnFactory(ctxValue);
781
- const argsAttributes = options.attributesFromArgs
782
- ? options.attributesFromArgs(args)
783
- : {};
817
+ const onSuccess = async (result: TReturn) => {
818
+ const duration = performance.now() - startTime;
784
819
 
785
- const handleTailSampling = (
786
- success: boolean,
787
- duration: number,
788
- error?: unknown,
789
- ) => {
790
- if (
791
- needsTailSampling &&
792
- 'shouldKeepTrace' in sampler &&
793
- typeof sampler.shouldKeepTrace === 'function'
794
- ) {
795
- shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
796
- success,
797
- duration,
798
- error,
820
+ callCounter?.add(1, {
821
+ operation: spanName,
822
+ status: 'success',
799
823
  });
800
- span.setAttribute('sampling.tail.keep', shouldKeepSpan);
801
- span.setAttribute('sampling.tail.evaluated', true);
802
- }
803
- };
804
-
805
- const onSuccess = async (result: TReturn) => {
806
- const duration = performance.now() - startTime;
807
824
 
808
- callCounter?.add(1, {
809
- operation: spanName,
810
- status: 'success',
811
- });
825
+ durationHistogram?.record(duration, {
826
+ operation: spanName,
827
+ status: 'success',
828
+ });
812
829
 
813
- durationHistogram?.record(duration, {
814
- operation: spanName,
815
- status: 'success',
816
- });
830
+ const resultAttributes = options.attributesFromResult
831
+ ? options.attributesFromResult(result)
832
+ : {};
833
+
834
+ span.setStatus({ code: SpanStatusCode.OK });
835
+ span.setAttributes({
836
+ ...argsAttributes,
837
+ ...resultAttributes,
838
+ 'operation.name': spanName,
839
+ 'code.function': spanName,
840
+ 'operation.duration': duration,
841
+ 'operation.success': true,
842
+ });
817
843
 
818
- const resultAttributes = options.attributesFromResult
819
- ? options.attributesFromResult(result)
820
- : {};
844
+ handleTailSampling(true, duration);
821
845
 
822
- span.setStatus({ code: SpanStatusCode.OK });
823
- span.setAttributes({
824
- ...argsAttributes,
825
- ...resultAttributes,
826
- 'operation.name': spanName,
827
- 'code.function': spanName,
828
- 'operation.duration': duration,
829
- 'operation.success': true,
830
- });
831
-
832
- handleTailSampling(true, duration);
846
+ span.end();
847
+ await flushIfNeeded();
848
+ return result;
849
+ };
833
850
 
834
- span.end();
835
- await flushIfNeeded();
836
- return result;
837
- };
851
+ const onError = async (error: unknown): Promise<never> => {
852
+ const duration = performance.now() - startTime;
838
853
 
839
- const onError = async (error: unknown): Promise<never> => {
840
- const duration = performance.now() - startTime;
854
+ callCounter?.add(1, {
855
+ operation: spanName,
856
+ status: 'error',
857
+ });
841
858
 
842
- callCounter?.add(1, {
843
- operation: spanName,
844
- status: 'error',
845
- });
859
+ durationHistogram?.record(duration, {
860
+ operation: spanName,
861
+ status: 'error',
862
+ });
846
863
 
847
- durationHistogram?.record(duration, {
848
- operation: spanName,
849
- status: 'error',
850
- });
864
+ const errorMessage =
865
+ error instanceof Error ? error.message : 'Unknown error';
866
+ const truncatedMessage = truncateErrorMessage(errorMessage);
851
867
 
852
- const errorMessage =
853
- error instanceof Error ? error.message : 'Unknown error';
854
- const truncatedMessage = truncateErrorMessage(errorMessage);
868
+ span.setStatus({
869
+ code: SpanStatusCode.ERROR,
870
+ message: truncatedMessage,
871
+ });
855
872
 
856
- span.setStatus({
857
- code: SpanStatusCode.ERROR,
858
- message: truncatedMessage,
859
- });
873
+ span.setAttributes({
874
+ ...argsAttributes,
875
+ 'operation.name': spanName,
876
+ 'code.function': spanName,
877
+ 'operation.duration': duration,
878
+ 'operation.success': false,
879
+ error: true,
880
+ 'exception.type':
881
+ error instanceof Error ? error.constructor.name : 'Error',
882
+ 'exception.message': truncatedMessage,
883
+ });
860
884
 
861
- span.setAttributes({
862
- ...argsAttributes,
863
- 'operation.name': spanName,
864
- 'code.function': spanName,
865
- 'operation.duration': duration,
866
- 'operation.success': false,
867
- error: true,
868
- 'exception.type':
869
- error instanceof Error ? error.constructor.name : 'Error',
870
- 'exception.message': truncatedMessage,
871
- });
885
+ if (error instanceof Error && error.stack) {
886
+ span.setAttribute(
887
+ 'exception.stack',
888
+ error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH),
889
+ );
890
+ }
872
891
 
873
- if (error instanceof Error && error.stack) {
874
- span.setAttribute(
875
- 'exception.stack',
876
- error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH),
892
+ span.recordException(
893
+ error instanceof Error ? error : new Error(String(error)),
877
894
  );
878
- }
879
895
 
880
- span.recordException(
881
- error instanceof Error ? error : new Error(String(error)),
882
- );
883
-
884
- handleTailSampling(false, duration, error);
896
+ handleTailSampling(false, duration, error);
885
897
 
886
- span.end();
887
- await flushIfNeeded();
888
- throw error;
889
- };
890
-
891
- try {
892
- callCounter?.add(1, {
893
- operation: spanName,
894
- status: 'started',
895
- });
898
+ span.end();
899
+ await flushIfNeeded();
900
+ throw error;
901
+ };
896
902
 
897
- // Execute the user's function with the updated context
898
- // This ensures ctx.setBaggage() changes are visible to OpenTelemetry operations
899
- // (like BaggageSpanProcessor, child spans, etc.)
900
- // We use getActiveContextWithBaggage() which checks the stored context,
901
- // so if baggage is set during execution, it will be picked up
902
- const executeWithContext = async () => {
903
- // Get the current context (may have been updated by ctx.setBaggage())
904
- const currentContext = getActiveContextWithBaggage();
905
- // Establish the context in OpenTelemetry's context manager
906
- return context.with(currentContext, async () => {
907
- return fn.call(this, ...args);
903
+ try {
904
+ callCounter?.add(1, {
905
+ operation: spanName,
906
+ status: 'started',
908
907
  });
909
- };
910
- const result = await executeWithContext();
911
908
 
912
- return await onSuccess(result);
913
- } catch (error) {
914
- await onError(error);
915
- throw error;
916
- }
917
- });
918
- });
909
+ // Execute the user's function with the updated context
910
+ // This ensures ctx.setBaggage() changes are visible to OpenTelemetry operations
911
+ // (like BaggageSpanProcessor, child spans, etc.)
912
+ // We use getActiveContextWithBaggage() which checks the stored context,
913
+ // so if baggage is set during execution, it will be picked up
914
+ const executeWithContext = async () => {
915
+ // Get the current context (may have been updated by ctx.setBaggage())
916
+ const currentContext = getActiveContextWithBaggage();
917
+ // Establish the context in OpenTelemetry's context manager
918
+ return context.with(currentContext, async () => {
919
+ return fn.call(this, ...args);
920
+ });
921
+ };
922
+ const result = await executeWithContext();
923
+
924
+ return await onSuccess(result);
925
+ } catch (error) {
926
+ await onError(error);
927
+ throw error;
928
+ }
929
+ });
930
+ },
931
+ );
919
932
  };
920
933
 
921
934
  // Mark as instrumented to prevent double-wrapping
@@ -1069,143 +1082,149 @@ function wrapWithTracingSync<TArgs extends unknown[], TReturn>(
1069
1082
  spanOptions.kind = options.spanKind;
1070
1083
  }
1071
1084
 
1072
- return tracer.startActiveSpan(spanName, spanOptions, (span) => {
1073
- // Run within operation context so events can auto-capture operation.name
1074
- return runInOperationContext(spanName, () => {
1075
- let shouldKeepSpan = true;
1076
-
1077
- // Store span name for trace context helpers
1078
- setSpanName(span, spanName);
1079
-
1080
- // Create trace context for this span using shared utility
1081
- const ctxValue = createTraceContext(span);
1085
+ const parentContext = getActiveContextWithBaggage();
1086
+ return tracer.startActiveSpan(
1087
+ spanName,
1088
+ spanOptions,
1089
+ parentContext,
1090
+ (span) => {
1091
+ // Run within operation context so events can auto-capture operation.name
1092
+ return runInOperationContext(spanName, () => {
1093
+ let shouldKeepSpan = true;
1094
+
1095
+ // Store span name for trace context helpers
1096
+ setSpanName(span, spanName);
1097
+
1098
+ // Create trace context for this span using shared utility
1099
+ const ctxValue = createTraceContext(span);
1100
+
1101
+ // Get the actual function from the factory
1102
+ const fn = fnFactory(ctxValue);
1103
+
1104
+ // Extract attributes only when actually tracing
1105
+ // This avoids expensive preprocessing when sampling rejects the trace
1106
+ const argsAttributes = options.attributesFromArgs
1107
+ ? options.attributesFromArgs(args)
1108
+ : {};
1082
1109
 
1083
- // Get the actual function from the factory
1084
- const fn = fnFactory(ctxValue);
1110
+ const handleTailSampling = (
1111
+ success: boolean,
1112
+ duration: number,
1113
+ error?: unknown,
1114
+ ) => {
1115
+ if (
1116
+ needsTailSampling &&
1117
+ 'shouldKeepTrace' in sampler &&
1118
+ typeof sampler.shouldKeepTrace === 'function'
1119
+ ) {
1120
+ shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
1121
+ success,
1122
+ duration,
1123
+ error,
1124
+ });
1125
+ span.setAttribute(AUTOTEL_SAMPLING_TAIL_KEEP, shouldKeepSpan);
1126
+ span.setAttribute(AUTOTEL_SAMPLING_TAIL_EVALUATED, true);
1127
+ }
1128
+ };
1085
1129
 
1086
- // Extract attributes only when actually tracing
1087
- // This avoids expensive preprocessing when sampling rejects the trace
1088
- const argsAttributes = options.attributesFromArgs
1089
- ? options.attributesFromArgs(args)
1090
- : {};
1130
+ const onSuccess = (result: TReturn) => {
1131
+ const duration = performance.now() - startTime;
1091
1132
 
1092
- const handleTailSampling = (
1093
- success: boolean,
1094
- duration: number,
1095
- error?: unknown,
1096
- ) => {
1097
- if (
1098
- needsTailSampling &&
1099
- 'shouldKeepTrace' in sampler &&
1100
- typeof sampler.shouldKeepTrace === 'function'
1101
- ) {
1102
- shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
1103
- success,
1104
- duration,
1105
- error,
1133
+ callCounter?.add(1, {
1134
+ operation: spanName,
1135
+ status: 'success',
1106
1136
  });
1107
- span.setAttribute('sampling.tail.keep', shouldKeepSpan);
1108
- span.setAttribute('sampling.tail.evaluated', true);
1109
- }
1110
- };
1111
-
1112
- const onSuccess = (result: TReturn) => {
1113
- const duration = performance.now() - startTime;
1114
1137
 
1115
- callCounter?.add(1, {
1116
- operation: spanName,
1117
- status: 'success',
1118
- });
1119
-
1120
- durationHistogram?.record(duration, {
1121
- operation: spanName,
1122
- status: 'success',
1123
- });
1138
+ durationHistogram?.record(duration, {
1139
+ operation: spanName,
1140
+ status: 'success',
1141
+ });
1124
1142
 
1125
- const resultAttributes = options.attributesFromResult
1126
- ? options.attributesFromResult(result)
1127
- : {};
1143
+ const resultAttributes = options.attributesFromResult
1144
+ ? options.attributesFromResult(result)
1145
+ : {};
1146
+
1147
+ span.setStatus({ code: SpanStatusCode.OK });
1148
+ span.setAttributes({
1149
+ ...argsAttributes,
1150
+ ...resultAttributes,
1151
+ 'operation.name': spanName,
1152
+ 'code.function': spanName,
1153
+ 'operation.duration': duration,
1154
+ 'operation.success': true,
1155
+ });
1128
1156
 
1129
- span.setStatus({ code: SpanStatusCode.OK });
1130
- span.setAttributes({
1131
- ...argsAttributes,
1132
- ...resultAttributes,
1133
- 'operation.name': spanName,
1134
- 'code.function': spanName,
1135
- 'operation.duration': duration,
1136
- 'operation.success': true,
1137
- });
1157
+ handleTailSampling(true, duration);
1138
1158
 
1139
- handleTailSampling(true, duration);
1159
+ span.end();
1160
+ void flushIfNeeded();
1161
+ return result;
1162
+ };
1140
1163
 
1141
- span.end();
1142
- void flushIfNeeded();
1143
- return result;
1144
- };
1164
+ const onError = (error: unknown): never => {
1165
+ const duration = performance.now() - startTime;
1145
1166
 
1146
- const onError = (error: unknown): never => {
1147
- const duration = performance.now() - startTime;
1167
+ callCounter?.add(1, {
1168
+ operation: spanName,
1169
+ status: 'error',
1170
+ });
1148
1171
 
1149
- callCounter?.add(1, {
1150
- operation: spanName,
1151
- status: 'error',
1152
- });
1172
+ durationHistogram?.record(duration, {
1173
+ operation: spanName,
1174
+ status: 'error',
1175
+ });
1153
1176
 
1154
- durationHistogram?.record(duration, {
1155
- operation: spanName,
1156
- status: 'error',
1157
- });
1177
+ const errorMessage =
1178
+ error instanceof Error ? error.message : 'Unknown error';
1179
+ const truncatedMessage = truncateErrorMessage(errorMessage);
1158
1180
 
1159
- const errorMessage =
1160
- error instanceof Error ? error.message : 'Unknown error';
1161
- const truncatedMessage = truncateErrorMessage(errorMessage);
1181
+ span.setStatus({
1182
+ code: SpanStatusCode.ERROR,
1183
+ message: truncatedMessage,
1184
+ });
1162
1185
 
1163
- span.setStatus({
1164
- code: SpanStatusCode.ERROR,
1165
- message: truncatedMessage,
1166
- });
1186
+ span.setAttributes({
1187
+ ...argsAttributes,
1188
+ 'operation.name': spanName,
1189
+ 'code.function': spanName,
1190
+ 'operation.duration': duration,
1191
+ 'operation.success': false,
1192
+ error: true,
1193
+ 'exception.type':
1194
+ error instanceof Error ? error.constructor.name : 'Error',
1195
+ 'exception.message': truncatedMessage,
1196
+ });
1167
1197
 
1168
- span.setAttributes({
1169
- ...argsAttributes,
1170
- 'operation.name': spanName,
1171
- 'code.function': spanName,
1172
- 'operation.duration': duration,
1173
- 'operation.success': false,
1174
- error: true,
1175
- 'exception.type':
1176
- error instanceof Error ? error.constructor.name : 'Error',
1177
- 'exception.message': truncatedMessage,
1178
- });
1198
+ span.recordException(
1199
+ error instanceof Error ? error : new Error(String(error)),
1200
+ );
1179
1201
 
1180
- span.recordException(
1181
- error instanceof Error ? error : new Error(String(error)),
1182
- );
1202
+ handleTailSampling(false, duration, error);
1183
1203
 
1184
- handleTailSampling(false, duration, error);
1204
+ span.end();
1205
+ void flushIfNeeded();
1206
+ throw error;
1207
+ };
1185
1208
 
1186
- span.end();
1187
- void flushIfNeeded();
1188
- throw error;
1189
- };
1209
+ try {
1210
+ callCounter?.add(1, {
1211
+ operation: spanName,
1212
+ status: 'started',
1213
+ });
1190
1214
 
1191
- try {
1192
- callCounter?.add(1, {
1193
- operation: spanName,
1194
- status: 'started',
1195
- });
1215
+ const result = fn.call(this, ...args);
1196
1216
 
1197
- const result = fn.call(this, ...args);
1217
+ if (result instanceof Promise) {
1218
+ return result.then(onSuccess, onError);
1219
+ }
1198
1220
 
1199
- if (result instanceof Promise) {
1200
- return result.then(onSuccess, onError);
1221
+ return onSuccess(result);
1222
+ } catch (error) {
1223
+ return onError(error);
1201
1224
  }
1202
-
1203
- return onSuccess(result);
1204
- } catch (error) {
1205
- return onError(error);
1206
- }
1207
- });
1208
- });
1225
+ });
1226
+ },
1227
+ );
1209
1228
  }
1210
1229
 
1211
1230
  // Mark as instrumented to prevent double-wrapping
@@ -1330,215 +1349,221 @@ function executeImmediately<TReturn = unknown>(
1330
1349
  spanOptions.kind = options.spanKind;
1331
1350
  }
1332
1351
 
1333
- return tracer.startActiveSpan(spanName, spanOptions, (span) => {
1334
- return runInOperationContext(spanName, () => {
1335
- let shouldKeepSpan = true;
1336
-
1337
- setSpanName(span, spanName);
1338
- const ctxValue = createTraceContext(span);
1339
-
1340
- const handleTailSampling = (
1341
- success: boolean,
1342
- duration: number,
1343
- error?: unknown,
1344
- ) => {
1345
- if (
1346
- needsTailSampling &&
1347
- 'shouldKeepTrace' in sampler &&
1348
- typeof sampler.shouldKeepTrace === 'function'
1349
- ) {
1350
- shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
1351
- success,
1352
- duration,
1353
- error,
1354
- });
1355
- span.setAttribute('sampling.tail.keep', shouldKeepSpan);
1356
- span.setAttribute('sampling.tail.evaluated', true);
1357
- }
1358
- };
1352
+ const parentContext = getActiveContextWithBaggage();
1353
+ return tracer.startActiveSpan(
1354
+ spanName,
1355
+ spanOptions,
1356
+ parentContext,
1357
+ (span) => {
1358
+ return runInOperationContext(spanName, () => {
1359
+ let shouldKeepSpan = true;
1359
1360
 
1360
- // Sync handlers for synchronous results (can't await)
1361
- // NOTE: forceFlushOnShutdown will NOT block for synchronous trace() calls
1362
- // Flush is fire-and-forget, so spans may be dropped if process exits immediately
1363
- const onSuccessSync = (result: TReturn) => {
1364
- const duration = performance.now() - startTime;
1361
+ setSpanName(span, spanName);
1362
+ const ctxValue = createTraceContext(span);
1365
1363
 
1366
- callCounter?.add(1, {
1367
- operation: spanName,
1368
- status: 'success',
1369
- });
1364
+ const handleTailSampling = (
1365
+ success: boolean,
1366
+ duration: number,
1367
+ error?: unknown,
1368
+ ) => {
1369
+ if (
1370
+ needsTailSampling &&
1371
+ 'shouldKeepTrace' in sampler &&
1372
+ typeof sampler.shouldKeepTrace === 'function'
1373
+ ) {
1374
+ shouldKeepSpan = sampler.shouldKeepTrace(samplingContext, {
1375
+ success,
1376
+ duration,
1377
+ error,
1378
+ });
1379
+ span.setAttribute(AUTOTEL_SAMPLING_TAIL_KEEP, shouldKeepSpan);
1380
+ span.setAttribute(AUTOTEL_SAMPLING_TAIL_EVALUATED, true);
1381
+ }
1382
+ };
1370
1383
 
1371
- durationHistogram?.record(duration, {
1372
- operation: spanName,
1373
- status: 'success',
1374
- });
1384
+ // Sync handlers for synchronous results (can't await)
1385
+ // NOTE: forceFlushOnShutdown will NOT block for synchronous trace() calls
1386
+ // Flush is fire-and-forget, so spans may be dropped if process exits immediately
1387
+ const onSuccessSync = (result: TReturn) => {
1388
+ const duration = performance.now() - startTime;
1375
1389
 
1376
- span.setStatus({ code: SpanStatusCode.OK });
1377
- span.setAttributes({
1378
- 'operation.name': spanName,
1379
- 'code.function': spanName,
1380
- 'operation.duration': duration,
1381
- 'operation.success': true,
1382
- });
1390
+ callCounter?.add(1, {
1391
+ operation: spanName,
1392
+ status: 'success',
1393
+ });
1383
1394
 
1384
- handleTailSampling(true, duration);
1395
+ durationHistogram?.record(duration, {
1396
+ operation: spanName,
1397
+ status: 'success',
1398
+ });
1385
1399
 
1386
- span.end();
1387
- void flushIfNeeded();
1388
- return result;
1389
- };
1400
+ span.setStatus({ code: SpanStatusCode.OK });
1401
+ span.setAttributes({
1402
+ 'operation.name': spanName,
1403
+ 'code.function': spanName,
1404
+ 'operation.duration': duration,
1405
+ 'operation.success': true,
1406
+ });
1390
1407
 
1391
- const onErrorSync = (error: unknown): never => {
1392
- const duration = performance.now() - startTime;
1408
+ handleTailSampling(true, duration);
1393
1409
 
1394
- callCounter?.add(1, {
1395
- operation: spanName,
1396
- status: 'error',
1397
- });
1410
+ span.end();
1411
+ void flushIfNeeded();
1412
+ return result;
1413
+ };
1398
1414
 
1399
- durationHistogram?.record(duration, {
1400
- operation: spanName,
1401
- status: 'error',
1402
- });
1415
+ const onErrorSync = (error: unknown): never => {
1416
+ const duration = performance.now() - startTime;
1403
1417
 
1404
- const errorMessage =
1405
- error instanceof Error ? error.message : 'Unknown error';
1406
- const truncatedMessage = truncateErrorMessage(errorMessage);
1418
+ callCounter?.add(1, {
1419
+ operation: spanName,
1420
+ status: 'error',
1421
+ });
1407
1422
 
1408
- span.setStatus({
1409
- code: SpanStatusCode.ERROR,
1410
- message: truncatedMessage,
1411
- });
1423
+ durationHistogram?.record(duration, {
1424
+ operation: spanName,
1425
+ status: 'error',
1426
+ });
1412
1427
 
1413
- span.setAttributes({
1414
- 'operation.name': spanName,
1415
- 'code.function': spanName,
1416
- 'operation.duration': duration,
1417
- 'operation.success': false,
1418
- error: true,
1419
- 'exception.type':
1420
- error instanceof Error ? error.constructor.name : 'Error',
1421
- 'exception.message': truncatedMessage,
1422
- });
1428
+ const errorMessage =
1429
+ error instanceof Error ? error.message : 'Unknown error';
1430
+ const truncatedMessage = truncateErrorMessage(errorMessage);
1431
+
1432
+ span.setStatus({
1433
+ code: SpanStatusCode.ERROR,
1434
+ message: truncatedMessage,
1435
+ });
1423
1436
 
1424
- if (error instanceof Error && error.stack) {
1425
- span.setAttribute(
1426
- 'exception.stack',
1427
- error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH),
1437
+ span.setAttributes({
1438
+ 'operation.name': spanName,
1439
+ 'code.function': spanName,
1440
+ 'operation.duration': duration,
1441
+ 'operation.success': false,
1442
+ error: true,
1443
+ 'exception.type':
1444
+ error instanceof Error ? error.constructor.name : 'Error',
1445
+ 'exception.message': truncatedMessage,
1446
+ });
1447
+
1448
+ if (error instanceof Error && error.stack) {
1449
+ span.setAttribute(
1450
+ 'exception.stack',
1451
+ error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH),
1452
+ );
1453
+ }
1454
+
1455
+ span.recordException(
1456
+ error instanceof Error ? error : new Error(String(error)),
1428
1457
  );
1429
- }
1430
1458
 
1431
- span.recordException(
1432
- error instanceof Error ? error : new Error(String(error)),
1433
- );
1459
+ handleTailSampling(false, duration, error);
1434
1460
 
1435
- handleTailSampling(false, duration, error);
1461
+ span.end();
1462
+ void flushIfNeeded();
1463
+ throw error;
1464
+ };
1436
1465
 
1437
- span.end();
1438
- void flushIfNeeded();
1439
- throw error;
1440
- };
1466
+ // Async handlers for Promise results (await flush)
1467
+ const onSuccessAsync = async (result: TReturn) => {
1468
+ const duration = performance.now() - startTime;
1441
1469
 
1442
- // Async handlers for Promise results (await flush)
1443
- const onSuccessAsync = async (result: TReturn) => {
1444
- const duration = performance.now() - startTime;
1470
+ callCounter?.add(1, {
1471
+ operation: spanName,
1472
+ status: 'success',
1473
+ });
1445
1474
 
1446
- callCounter?.add(1, {
1447
- operation: spanName,
1448
- status: 'success',
1449
- });
1475
+ durationHistogram?.record(duration, {
1476
+ operation: spanName,
1477
+ status: 'success',
1478
+ });
1450
1479
 
1451
- durationHistogram?.record(duration, {
1452
- operation: spanName,
1453
- status: 'success',
1454
- });
1480
+ span.setStatus({ code: SpanStatusCode.OK });
1481
+ span.setAttributes({
1482
+ 'operation.name': spanName,
1483
+ 'code.function': spanName,
1484
+ 'operation.duration': duration,
1485
+ 'operation.success': true,
1486
+ });
1455
1487
 
1456
- span.setStatus({ code: SpanStatusCode.OK });
1457
- span.setAttributes({
1458
- 'operation.name': spanName,
1459
- 'code.function': spanName,
1460
- 'operation.duration': duration,
1461
- 'operation.success': true,
1462
- });
1488
+ handleTailSampling(true, duration);
1463
1489
 
1464
- handleTailSampling(true, duration);
1490
+ span.end();
1491
+ await flushIfNeeded();
1492
+ return result;
1493
+ };
1465
1494
 
1466
- span.end();
1467
- await flushIfNeeded();
1468
- return result;
1469
- };
1495
+ const onErrorAsync = async (error: unknown): Promise<never> => {
1496
+ const duration = performance.now() - startTime;
1470
1497
 
1471
- const onErrorAsync = async (error: unknown): Promise<never> => {
1472
- const duration = performance.now() - startTime;
1498
+ callCounter?.add(1, {
1499
+ operation: spanName,
1500
+ status: 'error',
1501
+ });
1473
1502
 
1474
- callCounter?.add(1, {
1475
- operation: spanName,
1476
- status: 'error',
1477
- });
1503
+ durationHistogram?.record(duration, {
1504
+ operation: spanName,
1505
+ status: 'error',
1506
+ });
1478
1507
 
1479
- durationHistogram?.record(duration, {
1480
- operation: spanName,
1481
- status: 'error',
1482
- });
1508
+ const errorMessage =
1509
+ error instanceof Error ? error.message : 'Unknown error';
1510
+ const truncatedMessage = truncateErrorMessage(errorMessage);
1483
1511
 
1484
- const errorMessage =
1485
- error instanceof Error ? error.message : 'Unknown error';
1486
- const truncatedMessage = truncateErrorMessage(errorMessage);
1512
+ span.setStatus({
1513
+ code: SpanStatusCode.ERROR,
1514
+ message: truncatedMessage,
1515
+ });
1487
1516
 
1488
- span.setStatus({
1489
- code: SpanStatusCode.ERROR,
1490
- message: truncatedMessage,
1491
- });
1517
+ span.setAttributes({
1518
+ 'operation.name': spanName,
1519
+ 'code.function': spanName,
1520
+ 'operation.duration': duration,
1521
+ 'operation.success': false,
1522
+ error: true,
1523
+ 'exception.type':
1524
+ error instanceof Error ? error.constructor.name : 'Error',
1525
+ 'exception.message': truncatedMessage,
1526
+ });
1492
1527
 
1493
- span.setAttributes({
1494
- 'operation.name': spanName,
1495
- 'code.function': spanName,
1496
- 'operation.duration': duration,
1497
- 'operation.success': false,
1498
- error: true,
1499
- 'exception.type':
1500
- error instanceof Error ? error.constructor.name : 'Error',
1501
- 'exception.message': truncatedMessage,
1502
- });
1528
+ if (error instanceof Error && error.stack) {
1529
+ span.setAttribute(
1530
+ 'exception.stack',
1531
+ error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH),
1532
+ );
1533
+ }
1503
1534
 
1504
- if (error instanceof Error && error.stack) {
1505
- span.setAttribute(
1506
- 'exception.stack',
1507
- error.stack.slice(0, MAX_ERROR_MESSAGE_LENGTH),
1535
+ span.recordException(
1536
+ error instanceof Error ? error : new Error(String(error)),
1508
1537
  );
1509
- }
1510
1538
 
1511
- span.recordException(
1512
- error instanceof Error ? error : new Error(String(error)),
1513
- );
1539
+ handleTailSampling(false, duration, error);
1514
1540
 
1515
- handleTailSampling(false, duration, error);
1541
+ span.end();
1542
+ await flushIfNeeded();
1543
+ throw error;
1544
+ };
1516
1545
 
1517
- span.end();
1518
- await flushIfNeeded();
1519
- throw error;
1520
- };
1546
+ try {
1547
+ callCounter?.add(1, {
1548
+ operation: spanName,
1549
+ status: 'started',
1550
+ });
1521
1551
 
1522
- try {
1523
- callCounter?.add(1, {
1524
- operation: spanName,
1525
- status: 'started',
1526
- });
1552
+ const result = fn(ctxValue);
1527
1553
 
1528
- const result = fn(ctxValue);
1554
+ // Check if result is a Promise - use async handlers to await flush
1555
+ if (result instanceof Promise) {
1556
+ return result.then(onSuccessAsync, onErrorAsync);
1557
+ }
1529
1558
 
1530
- // Check if result is a Promise - use async handlers to await flush
1531
- if (result instanceof Promise) {
1532
- return result.then(onSuccessAsync, onErrorAsync);
1559
+ // Synchronous result - use sync handlers
1560
+ return onSuccessSync(result);
1561
+ } catch (error) {
1562
+ return onErrorSync(error);
1533
1563
  }
1534
-
1535
- // Synchronous result - use sync handlers
1536
- return onSuccessSync(result);
1537
- } catch (error) {
1538
- return onErrorSync(error);
1539
- }
1540
- });
1541
- });
1564
+ });
1565
+ },
1566
+ );
1542
1567
  }
1543
1568
 
1544
1569
  /**
@@ -2206,7 +2231,8 @@ export function span<T = unknown>(
2206
2231
  });
2207
2232
  };
2208
2233
 
2209
- const result = tracer.startActiveSpan(name, executeSpan);
2234
+ const parentContext = getActiveContextWithBaggage();
2235
+ const result = tracer.startActiveSpan(name, {}, parentContext, executeSpan);
2210
2236
 
2211
2237
  // tracer.startActiveSpan might return a Promise even for sync callbacks
2212
2238
  // Check if it's a Promise and handle accordingly
@@ -2351,8 +2377,8 @@ export function withBaggage<T = unknown>(
2351
2377
  const ctxStorage = getContextStorage();
2352
2378
  const previousStored = ctxStorage.getStore();
2353
2379
  const baggageEnrichedStored = previousStored
2354
- ? propagation.setBaggage(previousStored, updatedBaggage)
2355
- : newContext;
2380
+ ? { value: propagation.setBaggage(previousStored.value, updatedBaggage) }
2381
+ : { value: newContext };
2356
2382
 
2357
2383
  // Run the function within the new context, scoped properly
2358
2384
  const result = previousStored