autotel 4.0.0 → 4.2.0

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 (232) hide show
  1. package/README.md +26 -1
  2. package/dist/auto.cjs +2 -2
  3. package/dist/auto.js +1 -1
  4. package/dist/correlation-id.cjs +1 -1
  5. package/dist/correlation-id.js +1 -1
  6. package/dist/decorators.cjs +1 -1
  7. package/dist/decorators.js +1 -1
  8. package/dist/{event-Dlqr4ZNL.cjs → event-BhHREDJk.cjs} +3 -3
  9. package/dist/{event-Dlqr4ZNL.cjs.map → event-BhHREDJk.cjs.map} +1 -1
  10. package/dist/{event-_58ryBjh.js → event-ByBTV9M2.js} +3 -3
  11. package/dist/{event-_58ryBjh.js.map → event-ByBTV9M2.js.map} +1 -1
  12. package/dist/event.cjs +1 -1
  13. package/dist/event.js +1 -1
  14. package/dist/{functional-BGkT8J-h.js → functional-DtI0u4vx.js} +19 -19
  15. package/dist/functional-DtI0u4vx.js.map +1 -0
  16. package/dist/{functional-C4CzoVrX.cjs → functional-zpzNLhky.cjs} +4 -4
  17. package/dist/{functional-C4CzoVrX.cjs.map → functional-zpzNLhky.cjs.map} +1 -1
  18. package/dist/functional.cjs +1 -1
  19. package/dist/functional.js +1 -1
  20. package/dist/http.cjs +1 -1
  21. package/dist/http.js +1 -1
  22. package/dist/index.cjs +5 -5
  23. package/dist/index.d.cts +1 -1
  24. package/dist/index.d.ts +1 -1
  25. package/dist/index.js +5 -5
  26. package/dist/{init-DJQOdVlN.d.ts → init-B7u-DjxM.d.ts} +57 -2
  27. package/dist/init-B7u-DjxM.d.ts.map +1 -0
  28. package/dist/{init-DvapOXCc.cjs → init-BX7AmFRl.cjs} +40 -21
  29. package/dist/init-BX7AmFRl.cjs.map +1 -0
  30. package/dist/{init-Ch6t7MNI.js → init-D-jnNMix.js} +39 -20
  31. package/dist/init-D-jnNMix.js.map +1 -0
  32. package/dist/{init-CNp-ee80.d.cts → init-DSrRmVnz.d.cts} +57 -2
  33. package/dist/init-DSrRmVnz.d.cts.map +1 -0
  34. package/dist/instrumentation.cjs +1 -1
  35. package/dist/instrumentation.js +1 -1
  36. package/dist/logger-D3Ej3DII.js +446 -0
  37. package/dist/logger-D3Ej3DII.js.map +1 -0
  38. package/dist/logger-thMPLpOG.cjs +487 -0
  39. package/dist/logger-thMPLpOG.cjs.map +1 -0
  40. package/dist/logger.cjs +8 -236
  41. package/dist/logger.js +2 -204
  42. package/dist/messaging.cjs +1 -1
  43. package/dist/messaging.js +1 -1
  44. package/dist/semantic-helpers.cjs +1 -1
  45. package/dist/semantic-helpers.js +1 -1
  46. package/dist/{track-3HY4NGV-.cjs → track-D59FfpL0.cjs} +2 -2
  47. package/dist/{track-3HY4NGV-.cjs.map → track-D59FfpL0.cjs.map} +1 -1
  48. package/dist/{track-nsKVy-pj.js → track-wc0HafS_.js} +6 -6
  49. package/dist/track-wc0HafS_.js.map +1 -0
  50. package/dist/webhook.cjs +1 -1
  51. package/dist/webhook.js +1 -1
  52. package/dist/workflow-distributed.cjs +1 -1
  53. package/dist/workflow-distributed.js +1 -1
  54. package/dist/workflow.cjs +1 -1
  55. package/dist/workflow.js +1 -1
  56. package/dist/{yaml-config-B3dQ82GR.cjs → yaml-config-Ck2uB0Dp.cjs} +2 -1
  57. package/dist/yaml-config-Ck2uB0Dp.cjs.map +1 -0
  58. package/dist/yaml-config.cjs +1 -1
  59. package/dist/yaml-config.d.cts +7 -1
  60. package/dist/yaml-config.d.cts.map +1 -1
  61. package/dist/yaml-config.d.ts +7 -1
  62. package/dist/yaml-config.d.ts.map +1 -1
  63. package/dist/yaml-config.js +1 -0
  64. package/dist/yaml-config.js.map +1 -1
  65. package/package.json +1 -2
  66. package/skills/autotel-core/SKILL.md +2 -0
  67. package/skills/autotel-instrumentation/SKILL.md +25 -0
  68. package/skills/debug-missing-spans/SKILL.md +3 -1
  69. package/skills/migrate-to-autotel/SKILL.md +24 -23
  70. package/skills/review-otel-patterns/SKILL.md +5 -4
  71. package/dist/functional-BGkT8J-h.js.map +0 -1
  72. package/dist/init-CNp-ee80.d.cts.map +0 -1
  73. package/dist/init-Ch6t7MNI.js.map +0 -1
  74. package/dist/init-DJQOdVlN.d.ts.map +0 -1
  75. package/dist/init-DvapOXCc.cjs.map +0 -1
  76. package/dist/logger.cjs.map +0 -1
  77. package/dist/logger.js.map +0 -1
  78. package/dist/track-nsKVy-pj.js.map +0 -1
  79. package/dist/yaml-config-B3dQ82GR.cjs.map +0 -1
  80. package/src/attribute-redacting-processor.test.ts +0 -763
  81. package/src/attribute-redacting-processor.ts +0 -621
  82. package/src/attributes/attachers.ts +0 -161
  83. package/src/attributes/builders.ts +0 -529
  84. package/src/attributes/domains.ts +0 -42
  85. package/src/attributes/index.ts +0 -81
  86. package/src/attributes/registry.ts +0 -323
  87. package/src/attributes/types.ts +0 -211
  88. package/src/attributes/utils.ts +0 -64
  89. package/src/attributes/validators.ts +0 -266
  90. package/src/attributes.test.ts +0 -292
  91. package/src/auto.ts +0 -67
  92. package/src/autotel-logger.test.ts +0 -548
  93. package/src/autotel-logger.ts +0 -364
  94. package/src/baggage-span-processor.test.ts +0 -202
  95. package/src/baggage-span-processor.ts +0 -100
  96. package/src/business-baggage.test.ts +0 -500
  97. package/src/business-baggage.ts +0 -669
  98. package/src/circuit-breaker.test.ts +0 -341
  99. package/src/circuit-breaker.ts +0 -184
  100. package/src/config.test.ts +0 -94
  101. package/src/config.ts +0 -172
  102. package/src/correlated-events.test.ts +0 -151
  103. package/src/correlated-events.ts +0 -47
  104. package/src/correlation-id.test.ts +0 -163
  105. package/src/correlation-id.ts +0 -206
  106. package/src/db.test.ts +0 -252
  107. package/src/db.ts +0 -447
  108. package/src/decorators.test.ts +0 -153
  109. package/src/decorators.ts +0 -188
  110. package/src/define-event.test.ts +0 -41
  111. package/src/define-event.ts +0 -58
  112. package/src/devtools.ts +0 -60
  113. package/src/drain-pipeline.test.ts +0 -68
  114. package/src/drain-pipeline.ts +0 -199
  115. package/src/drain-toolkit.test.ts +0 -113
  116. package/src/drain-toolkit.ts +0 -129
  117. package/src/enricher-toolkit.test.ts +0 -67
  118. package/src/enricher-toolkit.ts +0 -79
  119. package/src/enrichers.test.ts +0 -150
  120. package/src/enrichers.ts +0 -145
  121. package/src/env-config.test.ts +0 -323
  122. package/src/env-config.ts +0 -309
  123. package/src/error-catalog.test.ts +0 -133
  124. package/src/error-catalog.ts +0 -262
  125. package/src/event-queue.test.ts +0 -864
  126. package/src/event-queue.ts +0 -699
  127. package/src/event-subscriber.ts +0 -262
  128. package/src/event-testing.ts +0 -197
  129. package/src/event.test.ts +0 -1104
  130. package/src/event.ts +0 -988
  131. package/src/events-config.ts +0 -235
  132. package/src/exporters.ts +0 -165
  133. package/src/filtering-span-processor.test.ts +0 -281
  134. package/src/filtering-span-processor.ts +0 -111
  135. package/src/flatten-attributes.test.ts +0 -76
  136. package/src/flatten-attributes.ts +0 -80
  137. package/src/functional.strict-types.typecheck.ts +0 -53
  138. package/src/functional.test.ts +0 -1464
  139. package/src/functional.ts +0 -2539
  140. package/src/functional.types.test.ts +0 -135
  141. package/src/hook.mjs +0 -15
  142. package/src/http.test.ts +0 -485
  143. package/src/http.ts +0 -424
  144. package/src/index.ts +0 -433
  145. package/src/init-auto-redactor.test.ts +0 -53
  146. package/src/init-redactor.test.ts +0 -8
  147. package/src/init.customization.test.ts +0 -594
  148. package/src/init.integrations.test.ts +0 -399
  149. package/src/init.openllmetry.test.ts +0 -194
  150. package/src/init.protocol.test.ts +0 -215
  151. package/src/init.ts +0 -2312
  152. package/src/instrumentation.test.ts +0 -108
  153. package/src/instrumentation.ts +0 -319
  154. package/src/logger.test.ts +0 -125
  155. package/src/logger.ts +0 -341
  156. package/src/messaging-adapters.test.ts +0 -595
  157. package/src/messaging-adapters.ts +0 -583
  158. package/src/messaging-testing.test.ts +0 -573
  159. package/src/messaging-testing.ts +0 -935
  160. package/src/messaging.test.ts +0 -1646
  161. package/src/messaging.ts +0 -2245
  162. package/src/metric-helpers.ts +0 -47
  163. package/src/metric-testing.ts +0 -197
  164. package/src/metric.ts +0 -446
  165. package/src/metrics.test.ts +0 -241
  166. package/src/node-require.ts +0 -123
  167. package/src/operation-context.ts +0 -93
  168. package/src/parse-error.test.ts +0 -73
  169. package/src/parse-error.ts +0 -112
  170. package/src/posthog-logs.test.ts +0 -115
  171. package/src/posthog-logs.ts +0 -77
  172. package/src/pretty-console-exporter.test.ts +0 -545
  173. package/src/pretty-console-exporter.ts +0 -413
  174. package/src/pretty-log-formatter.test.ts +0 -123
  175. package/src/pretty-log-formatter.ts +0 -210
  176. package/src/processors/canonical-log-line-processor.test.ts +0 -523
  177. package/src/processors/canonical-log-line-processor.ts +0 -396
  178. package/src/processors.ts +0 -152
  179. package/src/rate-limiter.test.ts +0 -199
  180. package/src/rate-limiter.ts +0 -98
  181. package/src/redact-values.test.ts +0 -90
  182. package/src/redact-values.ts +0 -34
  183. package/src/register.ts +0 -37
  184. package/src/request-logger.test.ts +0 -545
  185. package/src/request-logger.ts +0 -342
  186. package/src/sampling.test.ts +0 -1060
  187. package/src/sampling.ts +0 -737
  188. package/src/security-schema.test.ts +0 -45
  189. package/src/security-schema.ts +0 -107
  190. package/src/semantic-conventions.ts +0 -15
  191. package/src/semantic-helpers.test.ts +0 -226
  192. package/src/semantic-helpers.ts +0 -438
  193. package/src/shutdown.test.ts +0 -364
  194. package/src/shutdown.ts +0 -246
  195. package/src/span-name-normalizer.test.ts +0 -377
  196. package/src/span-name-normalizer.ts +0 -213
  197. package/src/stable-hash.ts +0 -27
  198. package/src/structured-error.test.ts +0 -191
  199. package/src/structured-error.ts +0 -157
  200. package/src/stub.integration.test.ts +0 -361
  201. package/src/tail-sampling-processor.test.ts +0 -230
  202. package/src/tail-sampling-processor.ts +0 -55
  203. package/src/test-span-collector.test.ts +0 -234
  204. package/src/test-span-collector.ts +0 -150
  205. package/src/testing.ts +0 -705
  206. package/src/trace-context.test.ts +0 -73
  207. package/src/trace-context.ts +0 -567
  208. package/src/trace-helpers.new.test.ts +0 -278
  209. package/src/trace-helpers.test.ts +0 -290
  210. package/src/trace-helpers.ts +0 -710
  211. package/src/trace-hybrid.test.ts +0 -42
  212. package/src/trace-hybrid.ts +0 -37
  213. package/src/tracer-provider.test.ts +0 -183
  214. package/src/tracer-provider.ts +0 -266
  215. package/src/track.test.ts +0 -154
  216. package/src/track.ts +0 -216
  217. package/src/validate.test.ts +0 -287
  218. package/src/validate.ts +0 -307
  219. package/src/validation-attributes.ts +0 -43
  220. package/src/validation.test.ts +0 -330
  221. package/src/validation.ts +0 -246
  222. package/src/variable-name-inference.test.ts +0 -178
  223. package/src/variable-name-inference.ts +0 -242
  224. package/src/webhook.test.ts +0 -649
  225. package/src/webhook.ts +0 -637
  226. package/src/workflow-distributed.test.ts +0 -786
  227. package/src/workflow-distributed.ts +0 -916
  228. package/src/workflow.async-safety.integration.test.ts +0 -345
  229. package/src/workflow.test.ts +0 -647
  230. package/src/workflow.ts +0 -810
  231. package/src/yaml-config.test.ts +0 -337
  232. package/src/yaml-config.ts +0 -342
@@ -572,6 +572,21 @@ function normalizeOtlpHeaders(headers) {
572
572
  }
573
573
  return parsed;
574
574
  }
575
+ function resolveOtlpDestinations(config, fallbackEndpoint) {
576
+ return (config.destinations !== void 0 ? config.destinations : fallbackEndpoint ? [{
577
+ endpoint: fallbackEndpoint,
578
+ headers: config.headers,
579
+ protocol: config.protocol
580
+ }] : []).map((destination) => ({
581
+ endpoint: destination.endpoint,
582
+ protocol: resolveProtocol(destination.protocol ?? config.protocol),
583
+ headers: normalizeOtlpHeaders(destination.headers ?? config.headers),
584
+ signals: destination.signals ? new Set(destination.signals) : void 0
585
+ }));
586
+ }
587
+ function destinationSupportsSignal(destination, signal) {
588
+ return destination.signals ? destination.signals.has(signal) : true;
589
+ }
575
590
  /**
576
591
  * Initialize autotel - Write Once, Observe Everywhere
577
592
  *
@@ -666,7 +681,6 @@ function init(cfg) {
666
681
  validationConfig = mergedConfig.validation || null;
667
682
  eventsConfig = mergedConfig.events || null;
668
683
  let endpoint = mergedConfig.endpoint ?? devtoolsConfig.endpoint;
669
- const otlpHeaders = normalizeOtlpHeaders(mergedConfig.headers);
670
684
  const version = mergedConfig.version || detectVersion();
671
685
  const environment = mergedConfig.environment || process.env.NODE_ENV || "development";
672
686
  const metricsEnabled = resolveMetricsFlag(mergedConfig.metrics);
@@ -697,7 +711,7 @@ function init(cfg) {
697
711
  }));
698
712
  if (mergedConfig.resource) resource = resource.merge(mergedConfig.resource);
699
713
  if (mergedConfig.resourceAttributes) resource = resource.merge(resourceFromAttributes(mergedConfig.resourceAttributes));
700
- const protocol = resolveProtocol(mergedConfig.protocol);
714
+ const otlpDestinations = resolveOtlpDestinations(mergedConfig, endpoint);
701
715
  const configuredSpanProcessors = mergedConfig.spanProcessors && mergedConfig.spanProcessors.length > 0 ? mergedConfig.spanProcessors : mergedConfig.spanProcessor ? [mergedConfig.spanProcessor] : void 0;
702
716
  const configuredSpanExporters = mergedConfig.spanExporters && mergedConfig.spanExporters.length > 0 ? mergedConfig.spanExporters : mergedConfig.spanExporter ? [mergedConfig.spanExporter] : void 0;
703
717
  const configuredMetricReaders = mergedConfig.metricReaders && mergedConfig.metricReaders.length > 0 ? mergedConfig.metricReaders : mergedConfig.metricReader ? [mergedConfig.metricReader] : void 0;
@@ -705,10 +719,11 @@ function init(cfg) {
705
719
  let spanProcessors = [];
706
720
  if (configuredSpanProcessors && configuredSpanProcessors.length > 0) spanProcessors.push(...configuredSpanProcessors);
707
721
  else if (configuredSpanExporters && configuredSpanExporters.length > 0) for (const exporter of configuredSpanExporters) spanProcessors.push(new TailSamplingSpanProcessor(new BatchSpanProcessor(exporter)));
708
- else if (endpoint) {
709
- const traceExporter = createTraceExporter(protocol, {
710
- url: formatEndpointUrl(endpoint, "traces", protocol),
711
- headers: otlpHeaders
722
+ else for (const destination of otlpDestinations) {
723
+ if (!destinationSupportsSignal(destination, "traces")) continue;
724
+ const traceExporter = createTraceExporter(destination.protocol, {
725
+ url: formatEndpointUrl(destination.endpoint, "traces", destination.protocol),
726
+ headers: destination.headers
712
727
  });
713
728
  spanProcessors.push(new TailSamplingSpanProcessor(new BatchSpanProcessor(traceExporter)));
714
729
  }
@@ -746,24 +761,28 @@ function init(cfg) {
746
761
  if (mergedConfig.spanFilter && spanProcessors.length > 0) spanProcessors = spanProcessors.map((processor) => new FilteringSpanProcessor(processor, { filter: mergedConfig.spanFilter }));
747
762
  const metricReaders = [];
748
763
  if (configuredMetricReaders && configuredMetricReaders.length > 0) metricReaders.push(...configuredMetricReaders);
749
- else if (metricsEnabled && endpoint) {
750
- const metricExporter = createMetricExporter(protocol, {
751
- url: formatEndpointUrl(endpoint, "metrics", protocol),
752
- headers: otlpHeaders
764
+ else if (metricsEnabled) for (const destination of otlpDestinations) {
765
+ if (!destinationSupportsSignal(destination, "metrics")) continue;
766
+ const metricExporter = createMetricExporter(destination.protocol, {
767
+ url: formatEndpointUrl(destination.endpoint, "metrics", destination.protocol),
768
+ headers: destination.headers
753
769
  });
754
770
  metricReaders.push(new PeriodicExportingMetricReader({ exporter: metricExporter }));
755
771
  }
756
772
  let logRecordProcessors;
757
773
  if (configuredLogRecordProcessors && configuredLogRecordProcessors.length > 0) logRecordProcessors = [...configuredLogRecordProcessors];
758
- if (logsEnabled && endpoint) {
759
- let processor = new BatchLogRecordProcessor(createLogExporter(protocol, {
760
- url: formatEndpointUrl(endpoint, "logs", protocol),
761
- headers: otlpHeaders
762
- }));
763
- if (_stringRedactor) processor = new RedactingLogRecordProcessor(processor, _stringRedactor);
764
- if (!logRecordProcessors) logRecordProcessors = [];
765
- logRecordProcessors.push(processor);
766
- logger.info({}, "[autotel] OTLP log exporter configured");
774
+ if (logsEnabled) {
775
+ for (const destination of otlpDestinations) {
776
+ if (!destinationSupportsSignal(destination, "logs")) continue;
777
+ let processor = new BatchLogRecordProcessor(createLogExporter(destination.protocol, {
778
+ url: formatEndpointUrl(destination.endpoint, "logs", destination.protocol),
779
+ headers: destination.headers
780
+ }));
781
+ if (_stringRedactor) processor = new RedactingLogRecordProcessor(processor, _stringRedactor);
782
+ if (!logRecordProcessors) logRecordProcessors = [];
783
+ logRecordProcessors.push(processor);
784
+ }
785
+ if (otlpDestinations.some((destination) => destinationSupportsSignal(destination, "logs"))) logger.info({}, "[autotel] OTLP log exporter configured");
767
786
  }
768
787
  const posthogProcessors = buildPostHogLogProcessors(mergedConfig.posthog, _stringRedactor);
769
788
  if (posthogProcessors.length > 0) {
@@ -1012,4 +1031,4 @@ function getSdk() {
1012
1031
 
1013
1032
  //#endregion
1014
1033
  export { getSdk as a, isInitialized as c, warnIfNotInitialized as d, createStringRedactor as f, getLogger as i, isLoggerLocked as l, getConfig as n, getValidationConfig as o, BaggageSpanProcessor as p, getEventsConfig as r, init as s, _closeEmbeddedDevtools as t, lockLogger as u };
1015
- //# sourceMappingURL=init-Ch6t7MNI.js.map
1034
+ //# sourceMappingURL=init-D-jnNMix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-D-jnNMix.js","names":["otelContext","OTLPTraceExporterHTTP","OTLPMetricExporterHTTP","OTLPLogExporterHTTP"],"sources":["../src/posthog-logs.ts","../src/baggage-span-processor.ts","../src/redact-values.ts","../src/env-config.ts","../src/devtools.ts","../src/init.ts"],"sourcesContent":["import type { LogRecordProcessor } from '@opentelemetry/sdk-logs';\nimport { safeRequire } from './node-require';\nimport type { StringRedactor } from './redact-values';\n\nexport class RedactingLogRecordProcessor implements LogRecordProcessor {\n constructor(\n private wrapped: LogRecordProcessor,\n private redact: StringRedactor,\n ) {}\n\n onEmit(logRecord: any, context?: any): void {\n if (logRecord.body && typeof logRecord.body === 'string') {\n logRecord.body = this.redact(logRecord.body);\n }\n if (logRecord.attributes) {\n for (const [key, value] of Object.entries(logRecord.attributes)) {\n if (typeof value === 'string') {\n logRecord.attributes[key] = this.redact(value);\n } else if (Array.isArray(value)) {\n logRecord.attributes[key] = value.map((item: unknown) =>\n typeof item === 'string' ? this.redact(item) : item,\n );\n }\n }\n }\n this.wrapped.onEmit(logRecord, context);\n }\n\n shutdown(): Promise<void> {\n return this.wrapped.shutdown();\n }\n\n forceFlush(): Promise<void> {\n return this.wrapped.forceFlush();\n }\n}\n\nexport interface PostHogConfig {\n /** OTLP logs endpoint URL (e.g., https://us.i.posthog.com/i/v1/logs?token=phc_xxx) */\n url: string;\n}\n\n/**\n * Build log record processors for PostHog OTLP logs integration.\n *\n * Resolution order:\n * 1. config.url if provided\n * 2. POSTHOG_LOGS_URL env var\n * 3. Empty array (disabled)\n */\nexport function buildPostHogLogProcessors(\n config: PostHogConfig | undefined,\n stringRedactor?: StringRedactor | null,\n): LogRecordProcessor[] {\n const url = config?.url || process.env.POSTHOG_LOGS_URL;\n if (!url) return [];\n\n const sdkLogs = safeRequire<{\n BatchLogRecordProcessor: new (exporter: unknown) => LogRecordProcessor;\n }>('@opentelemetry/sdk-logs');\n\n const exporterModule = safeRequire<{\n OTLPLogExporter: new (config: { url: string }) => unknown;\n }>('@opentelemetry/exporter-logs-otlp-http');\n\n if (!sdkLogs || !exporterModule) return [];\n\n const exporter = new exporterModule.OTLPLogExporter({ url });\n let processor: LogRecordProcessor = new sdkLogs.BatchLogRecordProcessor(\n exporter,\n );\n if (stringRedactor) {\n processor = new RedactingLogRecordProcessor(processor, stringRedactor);\n }\n\n return [processor];\n}\n","/**\n * Span processor that copies baggage entries to span attributes\n *\n * This makes baggage visible in trace UIs without manual attribute setting.\n * Enabled via init({ baggage: true }) or init({ baggage: 'custom-prefix' })\n */\n\nimport type { Span, Context } from '@opentelemetry/api';\nimport { propagation, context as otelContext } from '@opentelemetry/api';\nimport type { SpanProcessor } from '@opentelemetry/sdk-trace-base';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport { requireModule } from './node-require';\n\nexport interface BaggageSpanProcessorOptions {\n /**\n * Prefix for baggage attributes\n * @default 'baggage.'\n */\n prefix?: string;\n}\n\n/**\n * Span processor that automatically copies baggage entries to span attributes\n *\n * This makes baggage visible in trace UIs (Jaeger, Grafana, DataDog, etc.)\n * without manually calling ctx.setAttribute() for each baggage entry.\n *\n * @example Enable in init()\n * ```typescript\n * init({\n * service: 'my-app',\n * baggage: true // Uses default 'baggage.' prefix\n * });\n *\n * // Now baggage automatically appears as span attributes\n * await withBaggage({\n * baggage: { 'tenant.id': 't1', 'user.id': 'u1' },\n * fn: async () => {\n * // Span has baggage.tenant.id and baggage.user.id attributes!\n * }\n * });\n * ```\n *\n * @example Custom prefix\n * ```typescript\n * init({\n * service: 'my-app',\n * baggage: 'ctx' // Uses 'ctx.' prefix\n * });\n * // Creates attributes: ctx.tenant.id, ctx.user.id\n * ```\n */\nexport class BaggageSpanProcessor implements SpanProcessor {\n private readonly prefix: string;\n\n constructor(options: BaggageSpanProcessorOptions = {}) {\n this.prefix = options.prefix ?? 'baggage.';\n }\n\n onStart(span: Span, parentContext: Context): void {\n // Read baggage from parentContext first (spans created with explicit context)\n // Then fall back to active context (spans created without explicit context)\n // Also check getActiveContextWithBaggage() to see baggage set via ctx.setBaggage()\n let baggage = propagation.getBaggage(parentContext);\n if (!baggage) {\n baggage = propagation.getBaggage(otelContext.active());\n }\n // Check stored context from ctx.setBaggage() if still no baggage\n if (!baggage) {\n try {\n const { getActiveContextWithBaggage } = requireModule<{\n getActiveContextWithBaggage: () => Context;\n }>('./trace-context');\n const storedContext = getActiveContextWithBaggage();\n baggage = propagation.getBaggage(storedContext);\n } catch {\n // Fallback if trace-context isn't available\n }\n }\n if (!baggage) return;\n\n // Copy all baggage entries to span attributes\n for (const [key, entry] of baggage.getAllEntries()) {\n span.setAttribute(`${this.prefix}${key}`, entry.value);\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onEnd(_span: ReadableSpan): void {\n // No-op - required by SpanProcessor interface\n }\n\n async shutdown(): Promise<void> {\n // No-op\n }\n\n async forceFlush(): Promise<void> {\n // No-op\n }\n}\n","/** Standalone string redaction for use outside the span processor pipeline. */\n\nimport {\n REDACTOR_PRESETS,\n type AttributeRedactorConfig,\n type AttributeRedactorPreset,\n type ValuePatternConfig,\n} from './attribute-redacting-processor';\n\nexport type StringRedactor = (value: string) => string;\nexport function createStringRedactor(\n config: AttributeRedactorConfig | AttributeRedactorPreset,\n): StringRedactor {\n const resolved =\n typeof config === 'string' ? REDACTOR_PRESETS[config] : config;\n const valuePatterns: ValuePatternConfig[] = resolved.valuePatterns ?? [];\n const defaultReplacement = resolved.replacement ?? '[REDACTED]';\n\n return (value: string): string => {\n let result = value;\n for (const { pattern, replacement, mask } of valuePatterns) {\n pattern.lastIndex = 0;\n // Smart masks (e.g. email → a***@***.com) take precedence over the\n // static replacement so callers see the same output as the\n // span-attribute redactor does.\n if (mask) {\n result = result.replaceAll(pattern, (match) => mask(match));\n } else {\n result = result.replaceAll(pattern, replacement ?? defaultReplacement);\n }\n }\n return result;\n };\n}\n","/**\n * Standard OpenTelemetry environment variables\n */\nimport type { Sampler as OtelSampler } from '@opentelemetry/sdk-trace-base';\nimport {\n AlwaysOffSampler,\n AlwaysOnSampler,\n ParentBasedSampler,\n TraceIdRatioBasedSampler,\n} from '@opentelemetry/sdk-trace-base';\n\nexport interface OtelEnvVars {\n OTEL_SERVICE_NAME?: string;\n OTEL_EXPORTER_OTLP_ENDPOINT?: string;\n OTEL_EXPORTER_OTLP_HEADERS?: string;\n OTEL_RESOURCE_ATTRIBUTES?: string;\n OTEL_EXPORTER_OTLP_PROTOCOL?: 'http' | 'grpc';\n OTEL_TRACES_SAMPLER?: string;\n OTEL_TRACES_SAMPLER_ARG?: string;\n}\n\n/**\n * Parsed resource attributes as key-value pairs\n */\nexport interface ResourceAttributes {\n [key: string]: string;\n}\n\n/**\n * Parsed OTLP headers as key-value pairs\n */\nexport interface OtlpHeaders {\n [key: string]: string;\n}\n\n/**\n * Environment-resolved configuration (subset of AutotelConfig)\n * Defined locally to avoid circular dependency with init.ts\n */\nexport interface EnvConfig {\n service?: string;\n endpoint?: string;\n protocol?: 'http' | 'grpc';\n headers?: Record<string, string>;\n resourceAttributes?: Record<string, string>;\n otelSampler?: OtelSampler;\n}\n\n/**\n * Validate URL format\n */\nfunction isValidUrl(urlString: string): boolean {\n try {\n const url = new URL(urlString);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/**\n * Resolve OpenTelemetry environment variables from process.env\n */\nexport function resolveOtelEnv(): OtelEnvVars {\n const env: OtelEnvVars = {};\n\n // OTEL_SERVICE_NAME - optional string\n if (process.env.OTEL_SERVICE_NAME) {\n const value = process.env.OTEL_SERVICE_NAME.trim();\n if (value) {\n env.OTEL_SERVICE_NAME = value;\n }\n }\n\n // OTEL_EXPORTER_OTLP_ENDPOINT - optional URL\n if (process.env.OTEL_EXPORTER_OTLP_ENDPOINT) {\n const value = process.env.OTEL_EXPORTER_OTLP_ENDPOINT.trim();\n if (value && isValidUrl(value)) {\n env.OTEL_EXPORTER_OTLP_ENDPOINT = value;\n }\n }\n\n // OTEL_EXPORTER_OTLP_HEADERS - optional string\n if (process.env.OTEL_EXPORTER_OTLP_HEADERS) {\n const value = process.env.OTEL_EXPORTER_OTLP_HEADERS.trim();\n if (value) {\n env.OTEL_EXPORTER_OTLP_HEADERS = value;\n }\n }\n\n // OTEL_RESOURCE_ATTRIBUTES - optional string\n if (process.env.OTEL_RESOURCE_ATTRIBUTES) {\n const value = process.env.OTEL_RESOURCE_ATTRIBUTES.trim();\n if (value) {\n env.OTEL_RESOURCE_ATTRIBUTES = value;\n }\n }\n\n // OTEL_EXPORTER_OTLP_PROTOCOL - optional enum ('http' | 'grpc')\n if (process.env.OTEL_EXPORTER_OTLP_PROTOCOL) {\n const value = process.env.OTEL_EXPORTER_OTLP_PROTOCOL.trim().toLowerCase();\n if (value === 'http' || value === 'grpc') {\n env.OTEL_EXPORTER_OTLP_PROTOCOL = value;\n }\n }\n\n if (process.env.OTEL_TRACES_SAMPLER) {\n const value = process.env.OTEL_TRACES_SAMPLER.trim();\n if (value) {\n env.OTEL_TRACES_SAMPLER = value;\n }\n }\n\n if (process.env.OTEL_TRACES_SAMPLER_ARG) {\n const value = process.env.OTEL_TRACES_SAMPLER_ARG.trim();\n if (value) {\n env.OTEL_TRACES_SAMPLER_ARG = value;\n }\n }\n\n return env;\n}\n\nfunction parseRatioSamplerArg(\n samplerName: string,\n samplerArg: string | undefined,\n): number {\n if (samplerArg === undefined) {\n return 1.0;\n }\n\n const ratio = Number(samplerArg);\n if (!Number.isFinite(ratio) || ratio < 0 || ratio > 1) {\n console.error(\n `[autotel] Invalid OTEL_TRACES_SAMPLER_ARG=\"${samplerArg}\" for ${samplerName}. Expected a number in [0..1]. Falling back to 1.0.`,\n );\n return 1.0;\n }\n\n return ratio;\n}\n\nfunction warnOnUnusedSamplerArg(\n samplerName: string,\n samplerArg: string | undefined,\n): void {\n if (samplerArg !== undefined) {\n console.error(\n `[autotel] OTEL_TRACES_SAMPLER_ARG is not used by OTEL_TRACES_SAMPLER=\"${samplerName}\". Ignoring value \"${samplerArg}\".`,\n );\n }\n}\n\nexport function createSamplerFromEnv(\n env: Pick<OtelEnvVars, 'OTEL_TRACES_SAMPLER' | 'OTEL_TRACES_SAMPLER_ARG'>,\n): OtelSampler | undefined {\n const samplerName = env.OTEL_TRACES_SAMPLER;\n if (!samplerName) {\n return undefined;\n }\n\n switch (samplerName) {\n case 'always_on':\n warnOnUnusedSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG);\n return new AlwaysOnSampler();\n case 'always_off':\n warnOnUnusedSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG);\n return new AlwaysOffSampler();\n case 'traceidratio':\n return new TraceIdRatioBasedSampler(\n parseRatioSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG),\n );\n case 'parentbased_always_on':\n warnOnUnusedSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG);\n return new ParentBasedSampler({ root: new AlwaysOnSampler() });\n case 'parentbased_always_off':\n warnOnUnusedSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG);\n return new ParentBasedSampler({ root: new AlwaysOffSampler() });\n case 'parentbased_traceidratio':\n return new ParentBasedSampler({\n root: new TraceIdRatioBasedSampler(\n parseRatioSamplerArg(samplerName, env.OTEL_TRACES_SAMPLER_ARG),\n ),\n });\n case 'jaeger_remote':\n case 'parentbased_jaeger_remote':\n case 'xray':\n console.error(\n `[autotel] OTEL_TRACES_SAMPLER=\"${samplerName}\" is not supported yet by autotel. Falling back to the next sampler source.`,\n );\n return undefined;\n default:\n console.error(\n `[autotel] Unknown OTEL_TRACES_SAMPLER=\"${samplerName}\". Falling back to the next sampler source.`,\n );\n return undefined;\n }\n}\n\n/**\n * Parse OTEL_RESOURCE_ATTRIBUTES from comma-separated key=value pairs\n * Example: \"service.version=1.0.0,deployment.environment=production\"\n */\nexport function parseResourceAttributes(\n input: string | undefined,\n): ResourceAttributes {\n if (!input || input.trim() === '') {\n return {};\n }\n\n const attributes: ResourceAttributes = {};\n const pairs = input.split(',');\n\n for (const pair of pairs) {\n const trimmedPair = pair.trim();\n if (!trimmedPair) continue;\n\n const equalIndex = trimmedPair.indexOf('=');\n if (equalIndex === -1) {\n // Invalid format, skip this pair\n continue;\n }\n\n const key = trimmedPair.slice(0, equalIndex).trim();\n const value = trimmedPair.slice(equalIndex + 1).trim();\n\n if (key && value) {\n attributes[key] = value;\n }\n }\n\n return attributes;\n}\n\n/**\n * Parse OTEL_EXPORTER_OTLP_HEADERS from comma-separated key=value pairs\n * Example: \"api-key=secret123,x-custom-header=value\"\n */\nexport function parseOtlpHeaders(input: string | undefined): OtlpHeaders {\n if (!input || input.trim() === '') {\n return {};\n }\n\n const headers: OtlpHeaders = {};\n const pairs = input.split(',');\n\n for (const pair of pairs) {\n const trimmedPair = pair.trim();\n if (!trimmedPair) continue;\n\n const equalIndex = trimmedPair.indexOf('=');\n if (equalIndex === -1) {\n // Invalid format, skip this pair\n continue;\n }\n\n const key = trimmedPair.slice(0, equalIndex).trim();\n const value = trimmedPair.slice(equalIndex + 1).trim();\n\n if (key && value) {\n headers[key] = value;\n }\n }\n\n return headers;\n}\n\n/**\n * Convert resolved environment variables to config\n */\nexport function envToConfig(env: OtelEnvVars): EnvConfig {\n const config: EnvConfig = {};\n\n if (env.OTEL_SERVICE_NAME) {\n config.service = env.OTEL_SERVICE_NAME;\n }\n\n if (env.OTEL_EXPORTER_OTLP_ENDPOINT) {\n config.endpoint = env.OTEL_EXPORTER_OTLP_ENDPOINT;\n }\n\n if (env.OTEL_EXPORTER_OTLP_PROTOCOL) {\n config.protocol = env.OTEL_EXPORTER_OTLP_PROTOCOL;\n }\n\n if (env.OTEL_EXPORTER_OTLP_HEADERS) {\n config.headers = parseOtlpHeaders(env.OTEL_EXPORTER_OTLP_HEADERS);\n }\n\n const resourceAttrs = parseResourceAttributes(env.OTEL_RESOURCE_ATTRIBUTES);\n if (Object.keys(resourceAttrs).length > 0) {\n config.resourceAttributes = resourceAttrs;\n }\n\n const sampler = createSamplerFromEnv(env);\n if (sampler) {\n config.otelSampler = sampler;\n }\n\n return config;\n}\n\n/**\n * Main function to resolve config from environment variables\n */\nexport function resolveConfigFromEnv(): EnvConfig {\n const env = resolveOtelEnv();\n return envToConfig(env);\n}\n","export interface AutotelDevtoolsConfig {\n enabled?: boolean;\n endpoint?: string;\n embedded?: boolean;\n host?: string;\n port?: number;\n verbose?: boolean;\n}\n\nexport interface ResolvedAutotelDevtoolsConfig {\n enabled: boolean;\n endpoint?: string;\n embedded: boolean;\n host: string;\n port: number;\n verbose: boolean;\n}\n\nconst defaultHost = '127.0.0.1';\nconst defaultPort = 4318;\n\nexport function resolveDevtoolsConfig(\n config: boolean | AutotelDevtoolsConfig | undefined,\n): ResolvedAutotelDevtoolsConfig {\n if (!config) {\n return {\n enabled: false,\n endpoint: undefined,\n embedded: false,\n host: defaultHost,\n port: defaultPort,\n verbose: false,\n };\n }\n\n if (config === true) {\n return {\n enabled: true,\n endpoint: `http://${defaultHost}:${defaultPort}`,\n embedded: false,\n host: defaultHost,\n port: defaultPort,\n verbose: false,\n };\n }\n\n const enabled = config.enabled ?? true;\n const host = config.host ?? defaultHost;\n const port = config.port ?? defaultPort;\n const endpoint = config.endpoint ?? `http://${host}:${port}`;\n\n return {\n enabled,\n endpoint: enabled ? endpoint : undefined,\n embedded: enabled && (config.embedded ?? false),\n host,\n port,\n verbose: config.verbose ?? false,\n };\n}\n","/**\n * Simplified initialization for autotel\n *\n * Single init() function with sensible defaults.\n * Replaces initInstrumentation() and separate events config.\n */\n\nimport { NodeSDK } from '@opentelemetry/sdk-node';\nimport type { NodeSDKConfiguration } from '@opentelemetry/sdk-node';\nimport {\n BatchSpanProcessor,\n type SpanProcessor,\n SimpleSpanProcessor,\n ConsoleSpanExporter,\n SamplingDecision,\n type SpanExporter,\n type Sampler as OtelSampler,\n type SamplingResult,\n} from '@opentelemetry/sdk-trace-base';\nimport {\n resourceFromAttributes,\n type Resource,\n} from '@opentelemetry/resources';\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from '@opentelemetry/semantic-conventions';\nimport type { Sampler, SamplingPreset } from './sampling';\nimport { samplingPresets, resolveSamplingPreset } from './sampling';\nimport type { EventSubscriber } from './event-subscriber';\nimport type { Logger } from './logger';\nimport type { Attributes, Context, SpanKind, Link } from '@opentelemetry/api';\nimport type { ValidationConfig } from './validation';\nimport {\n PeriodicExportingMetricReader,\n type MetricReader,\n} from '@opentelemetry/sdk-metrics';\nimport { OTLPMetricExporter as OTLPMetricExporterHTTP } from '@opentelemetry/exporter-metrics-otlp-http';\nimport { OTLPTraceExporter as OTLPTraceExporterHTTP } from '@opentelemetry/exporter-trace-otlp-http';\nimport { OTLPLogExporter as OTLPLogExporterHTTP } from '@opentelemetry/exporter-logs-otlp-http';\nimport type { PushMetricExporter } from '@opentelemetry/sdk-metrics';\nimport {\n BatchLogRecordProcessor,\n type LogRecordExporter,\n type LogRecordProcessor,\n} from '@opentelemetry/sdk-logs';\nimport {\n buildPostHogLogProcessors,\n RedactingLogRecordProcessor,\n} from './posthog-logs';\nimport { TailSamplingSpanProcessor } from './tail-sampling-processor';\nimport { BaggageSpanProcessor } from './baggage-span-processor';\nimport {\n FilteringSpanProcessor,\n type SpanFilterPredicate,\n} from './filtering-span-processor';\nimport {\n SpanNameNormalizingProcessor,\n type SpanNameNormalizerConfig,\n} from './span-name-normalizer';\nimport {\n AttributeRedactingProcessor,\n normalizeAttributeRedactorConfig,\n type AttributeRedactorConfig,\n type AttributeRedactorPreset,\n} from './attribute-redacting-processor';\nimport { createStringRedactor, type StringRedactor } from './redact-values';\nimport { PrettyConsoleExporter } from './pretty-console-exporter';\nimport { resolveConfigFromEnv } from './env-config';\nimport { loadYamlConfig } from './yaml-config';\nimport { requireModule, safeRequire } from './node-require';\nimport {\n CanonicalLogLineProcessor,\n type CanonicalLogLineOptions,\n} from './processors/canonical-log-line-processor';\nimport type { EventsConfig } from './events-config';\nimport { resolveDevtoolsConfig, type AutotelDevtoolsConfig } from './devtools';\n\n/**\n * Silent logger (no-op) - used as default when user doesn't provide one.\n * Internal autotel logs are silent by default to avoid spam.\n * Users can import { autotelLogger } from 'autotel/logger' to create their own.\n */\nconst silentLogger: Logger = {\n info: () => {},\n warn: () => {},\n error: () => {},\n debug: () => {},\n};\n\n/**\n * Adapts an Autotel Sampler to the OTel SDK Sampler interface.\n */\nfunction toOtelSampler(sampler: Sampler): OtelSampler {\n return {\n shouldSample(\n _context: Context,\n _traceId: string,\n spanName: string,\n _spanKind: SpanKind,\n _attributes: Attributes,\n links: Link[],\n ): SamplingResult {\n const shouldTrace = sampler.shouldSample({\n operationName: spanName,\n args: [],\n links,\n });\n return {\n decision: shouldTrace\n ? SamplingDecision.RECORD_AND_SAMPLED\n : SamplingDecision.NOT_RECORD,\n };\n },\n toString(): string {\n return `AutotelSamplerAdapter`;\n },\n };\n}\n\n// Type imports for exporters\ntype OTLPExporterConfig = {\n url?: string;\n headers?: Record<string, string>;\n timeoutMillis?: number;\n concurrencyLimit?: number;\n};\n\nexport type OtlpSignal = 'traces' | 'metrics' | 'logs';\n\nexport interface OtlpDestinationConfig {\n /**\n * Base OTLP endpoint for this destination.\n * HTTP destinations may omit `/v1/{signal}`; autotel appends it automatically.\n * gRPC destinations should point at the collector host:port.\n */\n endpoint: string;\n\n /**\n * Headers for this destination. Falls back to top-level `headers`.\n */\n headers?: Record<string, string> | string;\n\n /**\n * Protocol for this destination. Falls back to top-level `protocol`.\n */\n protocol?: 'http' | 'grpc';\n\n /**\n * Signals to send to this destination.\n * Defaults to all signals supported by the current init() config.\n */\n signals?: OtlpSignal[];\n}\n\n// Lazy-load gRPC exporters (optional peer dependencies)\nlet OTLPTraceExporterGRPC:\n | (new (config: OTLPExporterConfig) => SpanExporter)\n | undefined;\nlet OTLPMetricExporterGRPC:\n | (new (config: OTLPExporterConfig) => PushMetricExporter)\n | undefined;\nlet OTLPLogExporterGRPC:\n | (new (config: OTLPExporterConfig) => LogRecordExporter)\n | undefined;\n\n/**\n * Helper: Lazy-load gRPC trace exporter\n */\nfunction loadGRPCTraceExporter(): new (\n config: OTLPExporterConfig,\n) => SpanExporter {\n if (OTLPTraceExporterGRPC) return OTLPTraceExporterGRPC;\n\n try {\n // Dynamic import for optional peer dependency\n const grpcModule = requireModule<{\n OTLPTraceExporter: new (config: OTLPExporterConfig) => SpanExporter;\n }>('@opentelemetry/exporter-trace-otlp-grpc');\n OTLPTraceExporterGRPC = grpcModule.OTLPTraceExporter;\n return OTLPTraceExporterGRPC;\n } catch {\n throw new Error(\n 'gRPC trace exporter not found. Install @opentelemetry/exporter-trace-otlp-grpc',\n );\n }\n}\n\n/**\n * Helper: Lazy-load gRPC metric exporter\n */\nfunction loadGRPCMetricExporter(): new (\n config: OTLPExporterConfig,\n) => PushMetricExporter {\n if (OTLPMetricExporterGRPC) return OTLPMetricExporterGRPC;\n\n try {\n // Dynamic import for optional peer dependency\n const grpcModule = requireModule<{\n OTLPMetricExporter: new (\n config: OTLPExporterConfig,\n ) => PushMetricExporter;\n }>('@opentelemetry/exporter-metrics-otlp-grpc');\n OTLPMetricExporterGRPC = grpcModule.OTLPMetricExporter;\n return OTLPMetricExporterGRPC;\n } catch {\n throw new Error(\n 'gRPC metric exporter not found. Install @opentelemetry/exporter-metrics-otlp-grpc',\n );\n }\n}\n\n/**\n * Helper: Create trace exporter based on protocol\n */\nfunction createTraceExporter(\n protocol: 'http' | 'grpc',\n config: OTLPExporterConfig,\n): SpanExporter {\n if (protocol === 'grpc') {\n const Exporter = loadGRPCTraceExporter();\n return new Exporter(config);\n }\n\n // Default: HTTP\n return new OTLPTraceExporterHTTP(config);\n}\n\n/**\n * Helper: Create metric exporter based on protocol\n */\nfunction createMetricExporter(\n protocol: 'http' | 'grpc',\n config: OTLPExporterConfig,\n): PushMetricExporter {\n if (protocol === 'grpc') {\n const Exporter = loadGRPCMetricExporter();\n return new Exporter(config);\n }\n\n // Default: HTTP\n return new OTLPMetricExporterHTTP(config);\n}\n\n/**\n * Helper: Lazy-load gRPC log exporter\n */\nfunction loadGRPCLogExporter(): new (\n config: OTLPExporterConfig,\n) => LogRecordExporter {\n if (OTLPLogExporterGRPC) return OTLPLogExporterGRPC;\n\n try {\n const grpcModule = requireModule<{\n OTLPLogExporter: new (config: OTLPExporterConfig) => LogRecordExporter;\n }>('@opentelemetry/exporter-logs-otlp-grpc');\n OTLPLogExporterGRPC = grpcModule.OTLPLogExporter;\n return OTLPLogExporterGRPC;\n } catch {\n throw new Error(\n 'gRPC log exporter not found. Install @opentelemetry/exporter-logs-otlp-grpc',\n );\n }\n}\n\n/**\n * Helper: Create log exporter based on protocol\n */\nfunction createLogExporter(\n protocol: 'http' | 'grpc',\n config: OTLPExporterConfig,\n): LogRecordExporter {\n if (protocol === 'grpc') {\n const Exporter = loadGRPCLogExporter();\n return new Exporter(config);\n }\n\n // Default: HTTP\n return new OTLPLogExporterHTTP(config);\n}\n\n/**\n * Helper: Resolve protocol from config and environment\n */\nfunction resolveProtocol(configProtocol?: 'http' | 'grpc'): 'http' | 'grpc' {\n // 1. Check config parameter (highest priority)\n if (configProtocol === 'grpc' || configProtocol === 'http') {\n return configProtocol;\n }\n\n // 2. Check OTEL_EXPORTER_OTLP_PROTOCOL env var\n const envProtocol = process.env.OTEL_EXPORTER_OTLP_PROTOCOL;\n if (envProtocol === 'grpc') return 'grpc';\n if (envProtocol === 'http/protobuf' || envProtocol === 'http') return 'http';\n\n // 3. Default to HTTP\n return 'http';\n}\n\n/**\n * Helper: Adjust endpoint URL for protocol\n * gRPC exporters don't need the /v1/traces or /v1/metrics path\n * HTTP exporters need the full path\n */\nfunction formatEndpointUrl(\n endpoint: string,\n signal: 'traces' | 'metrics' | 'logs',\n protocol: 'http' | 'grpc',\n): string {\n if (protocol === 'grpc') {\n // gRPC: strip any paths, return base endpoint\n return endpoint.replace(/\\/(v1\\/)?(traces|metrics|logs)$/, '');\n }\n\n // HTTP: append signal path if not present\n if (!endpoint.endsWith(`/v1/${signal}`)) {\n return `${endpoint}/v1/${signal}`;\n }\n\n return endpoint;\n}\n\n// Built-in logger is created dynamically in init() with service name\n\nexport interface AutotelConfig {\n /** Service name (required) */\n service: string;\n\n /**\n * Local developer UX for autotel-devtools.\n *\n * - `true`: send traces, metrics, and logs to `http://127.0.0.1:4318`\n * - `{ embedded: true }`: attempt to start `autotel-devtools` automatically\n *\n * When enabled:\n * - `endpoint` defaults to the local devtools URL\n * - `logs` default to `true` unless explicitly set\n *\n * This keeps production config unchanged while making local debugging\n * effectively zero-config.\n */\n devtools?: boolean | AutotelDevtoolsConfig;\n\n /** Event subscribers - bring your own (PostHog, Mixpanel, etc.) */\n subscribers?: EventSubscriber[];\n\n /**\n * Additional OpenTelemetry instrumentations to register (raw OTel classes).\n * Useful when you need custom instrumentation configs or instrumentations\n * not covered by autoInstrumentations.\n *\n * **Important:** If you need custom instrumentation configs (like `requireParentSpan: false`),\n * use EITHER manual instrumentations OR autoInstrumentations, not both for the same library.\n * Manual instrumentations always take precedence over auto-instrumentations.\n *\n * @example Manual instrumentations with custom config\n * ```typescript\n * import { MongoDBInstrumentation } from '@opentelemetry/instrumentation-mongodb'\n *\n * init({\n * service: 'my-app',\n * autoInstrumentations: false, // Disable auto-instrumentations\n * instrumentations: [\n * new MongoDBInstrumentation({\n * requireParentSpan: false // Custom config\n * })\n * ]\n * })\n * ```\n *\n * @example Mix auto + manual (auto for most, manual for specific configs)\n * ```typescript\n * import { MongoDBInstrumentation } from '@opentelemetry/instrumentation-mongodb'\n *\n * init({\n * service: 'my-app',\n * autoInstrumentations: ['http', 'express'], // Auto for these\n * instrumentations: [\n * new MongoDBInstrumentation({\n * requireParentSpan: false // Manual config for MongoDB\n * })\n * ]\n * })\n * ```\n */\n instrumentations?: NodeSDKConfiguration['instrumentations'];\n\n /**\n * Simple names for auto-instrumentation.\n * Uses @opentelemetry/auto-instrumentations-node (peer dependency).\n *\n * **Important:** If you provide manual instrumentations for the same library,\n * the manual config takes precedence and auto-instrumentation for that library is disabled.\n *\n * @example Enable all auto-instrumentations (simple approach)\n * ```typescript\n * init({\n * service: 'my-app',\n * autoInstrumentations: true // Enable all with defaults\n * })\n * ```\n *\n * @example Enable specific auto-instrumentations\n * ```typescript\n * init({\n * service: 'my-app',\n * autoInstrumentations: ['express', 'pino', 'http']\n * })\n * ```\n *\n * @example Configure specific auto-instrumentations\n * ```typescript\n * init({\n * service: 'my-app',\n * autoInstrumentations: {\n * express: { enabled: true },\n * pino: { enabled: true },\n * http: { enabled: false }\n * }\n * })\n * ```\n *\n * @example Manual config when you need custom settings\n * ```typescript\n * import { MongoDBInstrumentation } from '@opentelemetry/instrumentation-mongodb'\n *\n * init({\n * service: 'my-app',\n * autoInstrumentations: false, // Use manual control\n * instrumentations: [\n * new MongoDBInstrumentation({\n * requireParentSpan: false // Custom config not available with auto\n * })\n * ]\n * })\n * ```\n */\n autoInstrumentations?:\n | string[]\n | boolean\n | Record<string, { enabled?: boolean }>;\n\n /**\n * OTLP endpoint for traces/metrics/logs\n * Single-destination shorthand. For multi-backend OTLP fan-out, use\n * `destinations` instead.\n * Only used if you don't provide custom exporters/processors\n * @default process.env.OTLP_ENDPOINT || 'http://localhost:4318'\n */\n endpoint?: string;\n\n /**\n * Declarative OTLP multi-destination config.\n * Each destination can override endpoint, headers, protocol, and signals.\n *\n * This is the high-level alternative to wiring `spanExporters`,\n * `spanProcessors`, `metricReaders`, and `logRecordProcessors` manually when\n * you want to fan telemetry out to multiple OTLP backends.\n *\n * When provided, `destinations` takes precedence over the single `endpoint`\n * shorthand for built-in OTLP exporters/readers/processors.\n *\n * @example Grafana + Honeycomb for traces, Grafana only for metrics/logs\n * ```typescript\n * init({\n * service: 'my-app',\n * logs: true,\n * destinations: [\n * {\n * endpoint: 'https://otlp-gateway-prod-eu-west-2.grafana.net/otlp',\n * headers: { Authorization: 'Basic ...' },\n * },\n * {\n * endpoint: 'https://api.honeycomb.io',\n * headers: { 'x-honeycomb-team': '...' },\n * signals: ['traces'],\n * },\n * ],\n * })\n * ```\n */\n destinations?: OtlpDestinationConfig[];\n\n /**\n * Custom span processors for traces (supports multiple processors)\n * Allows you to use any backend: Jaeger, Zipkin, Datadog, New Relic, etc.\n * If not provided, defaults to OTLP with tail sampling\n *\n * @example Multiple processors\n * ```typescript\n * import { JaegerExporter } from '@opentelemetry/exporter-jaeger'\n * import { BatchSpanProcessor, SimpleSpanProcessor, ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base'\n *\n * init({\n * service: 'my-app',\n * spanProcessors: [\n * new BatchSpanProcessor(new JaegerExporter()),\n * new SimpleSpanProcessor(new ConsoleSpanExporter()) // Debug alongside production\n * ]\n * })\n * ```\n *\n * @example Single processor\n * ```typescript\n * import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'\n *\n * init({\n * service: 'my-app',\n * spanProcessors: [new SimpleSpanProcessor(new ConsoleSpanExporter())]\n * })\n * ```\n */\n spanProcessors?: SpanProcessor[];\n\n /**\n * Custom span processor for traces (single-item alias of spanProcessors)\n * @deprecated Use spanProcessors for consistency with other multi-value config fields\n */\n spanProcessor?: SpanProcessor;\n\n /**\n * Custom span exporters for traces (alternative to spanProcessors, supports multiple exporters)\n * Provide either spanProcessors OR spanExporters, not both\n * Each exporter will be wrapped in TailSamplingSpanProcessor + BatchSpanProcessor\n *\n * @example Multiple exporters\n * ```typescript\n * import { ZipkinExporter } from '@opentelemetry/exporter-zipkin'\n * import { JaegerExporter } from '@opentelemetry/exporter-jaeger'\n *\n * init({\n * service: 'my-app',\n * spanExporters: [\n * new ZipkinExporter({ url: 'http://localhost:9411/api/v2/spans' }),\n * new JaegerExporter() // Send to multiple backends simultaneously\n * ]\n * })\n * ```\n *\n * @example Single exporter\n * ```typescript\n * import { ZipkinExporter } from '@opentelemetry/exporter-zipkin'\n *\n * init({\n * service: 'my-app',\n * spanExporters: [new ZipkinExporter({ url: 'http://localhost:9411/api/v2/spans' })]\n * })\n * ```\n */\n spanExporters?: SpanExporter[];\n\n /**\n * Custom span exporter for traces (single-item alias of spanExporters)\n * @deprecated Use spanExporters for consistency with other multi-value config fields\n */\n spanExporter?: SpanExporter;\n\n /**\n * Custom metric readers (supports multiple readers)\n * Allows sending metrics to multiple backends: OTLP, Prometheus, custom readers\n * Defaults to OTLP metrics exporter when metrics are enabled.\n *\n * @example Multiple metric readers\n * ```typescript\n * import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'\n * import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'\n * import { PrometheusExporter } from '@opentelemetry/exporter-prometheus'\n *\n * init({\n * service: 'my-app',\n * metricReaders: [\n * new PeriodicExportingMetricReader({ exporter: new OTLPMetricExporter() }),\n * new PrometheusExporter() // Export to multiple backends\n * ]\n * })\n * ```\n */\n metricReaders?: MetricReader[];\n\n /**\n * Custom metric reader (single-item alias of metricReaders)\n * @deprecated Use metricReaders for consistency with other multi-value config fields\n */\n metricReader?: MetricReader;\n\n /**\n * Custom log record processors. When omitted, logs are not configured.\n */\n logRecordProcessors?: LogRecordProcessor[];\n\n /**\n * Custom log record processor (single-item alias of logRecordProcessors)\n * @deprecated Use logRecordProcessors for consistency with other multi-value config fields\n */\n logRecordProcessor?: LogRecordProcessor;\n\n /**\n * PostHog integration - auto-configures OTLP log exporter.\n *\n * @example\n * ```typescript\n * init({\n * service: 'my-app',\n * posthog: { url: 'https://us.i.posthog.com/i/v1/logs?token=phc_xxx' }\n * });\n * ```\n *\n * Also reads from POSTHOG_LOGS_URL environment variable as fallback.\n */\n posthog?: { url: string };\n\n /** Additional resource attributes to merge with defaults. */\n resourceAttributes?: Attributes;\n\n /** Provide a fully custom Resource to merge (advanced use case). */\n resource?: Resource;\n\n /**\n * Headers for OTLP exporters. Accepts either an object map or\n * a \"key=value\" comma separated string.\n *\n * @example\n * ```typescript\n * init({\n * service: 'my-app',\n * endpoint: 'https://api.honeycomb.io',\n * headers: { 'x-honeycomb-team': 'YOUR_API_KEY' }\n * })\n * ```\n */\n headers?: Record<string, string> | string;\n\n /**\n * OTLP protocol to use for traces, metrics, and logs\n * - 'http': HTTP/protobuf (default, uses port 4318)\n * - 'grpc': gRPC (uses port 4317)\n *\n * Can be overridden with OTEL_EXPORTER_OTLP_PROTOCOL env var.\n *\n * Note: gRPC exporters are optional peer dependencies. Install them with:\n * ```bash\n * pnpm add @opentelemetry/exporter-trace-otlp-grpc @opentelemetry/exporter-metrics-otlp-grpc\n * ```\n *\n * @example HTTP (default)\n * ```typescript\n * init({\n * service: 'my-app',\n * protocol: 'http', // or omit (defaults to http)\n * endpoint: 'http://localhost:4318'\n * })\n * ```\n *\n * @example gRPC\n * ```typescript\n * init({\n * service: 'my-app',\n * protocol: 'grpc',\n * endpoint: 'grpc://localhost:4317'\n * })\n * ```\n *\n * @default 'http'\n */\n protocol?: 'http' | 'grpc';\n\n /**\n * Optional factory to build a customised NodeSDK instance from our defaults.\n */\n sdkFactory?: (defaults: Partial<NodeSDKConfiguration>) => NodeSDK;\n\n /**\n * Infrastructure metrics configuration\n * - true: always enabled (default)\n * - false: always disabled\n * - 'auto': always enabled (same as true)\n *\n * Can be overridden with AUTOTEL_METRICS=on|off env var\n */\n metrics?: boolean | 'auto';\n\n /**\n * OTLP logs configuration\n * - true: auto-configure OTLP log exporter from endpoint\n * - false: disabled (default)\n * - 'auto': same as false (opt-in only)\n *\n * When enabled and an endpoint is configured, autotel will automatically\n * create a BatchLogRecordProcessor with an OTLPLogExporter - no manual\n * imports needed. Works alongside logRecordProcessors (additive).\n *\n * Requires @opentelemetry/sdk-logs and @opentelemetry/exporter-logs-otlp-http\n * (or -grpc) as peer dependencies.\n *\n * Can be overridden with AUTOTEL_LOGS=on|off env var.\n *\n * @example\n * ```typescript\n * init({\n * service: 'my-app',\n * endpoint: 'http://localhost:4318',\n * logs: true,\n * });\n * ```\n */\n logs?: boolean | 'auto';\n\n /** Sampling strategy - takes precedence over `sampling` preset */\n sampler?: Sampler;\n\n /**\n * Sampling preset shorthand — resolves to a pre-configured sampler.\n * If both `sampler` and `sampling` are provided, `sampler` takes precedence.\n *\n * @default 'production' (10% baseline + always-on for errors/slow)\n *\n * **Footgun for one-shot scripts:** the default samples ~90% of spans away,\n * which means a fixture-capture script that emits a single normal span\n * almost always sees zero output. For local debugging and capture use:\n *\n * ```typescript\n * init({\n * service: 'fixture-capture',\n * spanProcessors: [new SimpleSpanProcessor(new InMemorySpanExporter())],\n * sampling: 'development', // capture EVERY span\n * });\n * ```\n *\n * Read `exporter.getFinishedSpans()` **before** calling `shutdown()` —\n * `InMemorySpanExporter.shutdown()` resets state.\n */\n sampling?: SamplingPreset;\n\n /** Service version (default: auto-detect from package.json or '1.0.0') */\n version?: string;\n\n /** Environment (default: process.env.NODE_ENV || 'development') */\n environment?: string;\n\n /**\n * Logger instance for internal autotel diagnostic messages\n *\n * This logger is used by autotel internally to log initialization, warnings,\n * and debug information. Any logger with info/warn/error/debug methods works.\n *\n * **For OTel instrumentation of your application logs**, use the `autoInstrumentations` option:\n * - `autoInstrumentations: ['pino']` - Injects traceId/spanId into Pino logs\n * - `autoInstrumentations: ['winston']` - Injects traceId/spanId into Winston logs\n *\n * Default: silent logger (no-op)\n *\n * @example Pino with OTel instrumentation\n * ```typescript\n * import pino from 'pino'\n * import { init } from 'autotel'\n *\n * const logger = pino({ level: 'info' })\n * init({\n * service: 'my-app',\n * logger, // For autotel's internal logs\n * autoInstrumentations: ['pino'] // For OTel trace context in YOUR logs\n * })\n * ```\n *\n * @example Custom logger for autotel diagnostics\n * ```typescript\n * const logger = {\n * info: (msg, extra) => console.log(msg, extra),\n * warn: (msg, extra) => console.warn(msg, extra),\n * error: (msg, err, extra) => console.error(msg, err, extra),\n * debug: (msg, extra) => console.debug(msg, extra),\n * }\n * init({ service: 'my-app', logger })\n * ```\n */\n logger?: Logger;\n\n /**\n * Flush events queue when root spans end\n * - true: Flush on root span completion (default)\n * - false: Use batching (events flush every 10 seconds automatically)\n *\n * Only flushes on root spans to avoid excessive network calls.\n * Default is true for serverless/short-lived processes. Set to false\n * for long-running services where batching is more efficient.\n */\n flushOnRootSpanEnd?: boolean;\n\n /**\n * Force-flush OpenTelemetry spans on shutdown (default: false)\n *\n * When enabled, spans are force-flushed along with events on root\n * span completion. This is useful for serverless/short-lived processes where\n * spans may not export before the process ends.\n *\n * - true: Force-flush spans on root span completion (~50-200ms latency)\n * - false: Spans export via normal batch processor (default behavior)\n *\n * Only applies when flushOnRootSpanEnd is also enabled.\n *\n * Note: For edge runtimes (Cloudflare Workers, Vercel Edge), use the\n * 'autotel-edge' package instead, which handles this automatically.\n *\n * @example Serverless with force-flush\n * ```typescript\n * init({\n * service: 'my-lambda',\n * flushOnRootSpanEnd: true,\n * forceFlushOnShutdown: true, // Force-flush spans\n * });\n * ```\n */\n forceFlushOnShutdown?: boolean;\n\n /**\n * Automatically copy baggage entries to span attributes\n *\n * When enabled, all baggage entries are automatically added as span attributes,\n * making them visible in trace UIs (Jaeger, Grafana, DataDog, etc.) without\n * manually calling ctx.setAttribute() for each entry.\n *\n * - `true`: adds baggage with 'baggage.' prefix (e.g. baggage.tenant.id)\n * - `string`: uses custom prefix (e.g. 'ctx' → ctx.tenant.id, '' → tenant.id)\n * - `false` or omit: disabled (default)\n *\n * @default false\n *\n * @example Enable with default prefix\n * ```typescript\n * init({\n * service: 'my-app',\n * baggage: true\n * });\n *\n * // Now baggage automatically appears as span attributes\n * await withBaggage({\n * baggage: { 'tenant.id': 't1', 'user.id': 'u1' },\n * fn: async () => {\n * // Span has baggage.tenant.id and baggage.user.id attributes!\n * }\n * });\n * ```\n *\n * @example Custom prefix\n * ```typescript\n * init({\n * service: 'my-app',\n * baggage: 'ctx' // Uses 'ctx.' prefix\n * });\n * // Creates attributes: ctx.tenant.id, ctx.user.id\n * ```\n *\n * @example No prefix\n * ```typescript\n * init({\n * service: 'my-app',\n * baggage: '' // No prefix\n * });\n * // Creates attributes: tenant.id, user.id\n * ```\n */\n baggage?: boolean | string;\n\n /**\n * Validation configuration for events events\n * - Override default sensitive field patterns for redaction\n * - Customize max lengths, nesting depth, etc.\n *\n * @example Disable redaction for development\n * ```typescript\n * init({\n * service: 'my-app',\n * validation: {\n * sensitivePatterns: [] // Disable all redaction\n * }\n * })\n * ```\n *\n * @example Add custom patterns\n * ```typescript\n * init({\n * service: 'my-app',\n * validation: {\n * sensitivePatterns: [\n * /password/i,\n * /apiKey/i,\n * /customSecret/i // Your custom pattern\n * ]\n * }\n * })\n * ```\n */\n validation?: Partial<ValidationConfig>;\n\n /**\n * Events configuration for trace context, correlation IDs, and enrichment\n *\n * Controls how product events integrate with distributed tracing:\n * - `includeTraceContext`: Automatically include trace context in events\n * - `includeLinkedTraceIds`: Include full array of linked trace IDs (for batch/fan-in)\n * - `traceUrl`: Generate clickable trace URLs in events\n * - `enrichFromBaggage`: Auto-enrich events from baggage with guardrails\n *\n * @example Basic trace context\n * ```typescript\n * init({\n * service: 'my-app',\n * events: {\n * includeTraceContext: true\n * }\n * });\n * // Events now include autotel.trace_id, autotel.span_id, autotel.correlation_id\n * ```\n *\n * @example With clickable trace URLs\n * ```typescript\n * init({\n * service: 'my-app',\n * events: {\n * includeTraceContext: true,\n * traceUrl: (ctx) => `https://grafana.internal/explore?traceId=${ctx.traceId}`\n * }\n * });\n * ```\n *\n * @example With baggage enrichment\n * ```typescript\n * init({\n * service: 'my-app',\n * events: {\n * includeTraceContext: true,\n * enrichFromBaggage: {\n * allow: ['tenant.id', 'user.id'],\n * prefix: 'ctx.',\n * maxKeys: 10,\n * maxBytes: 1024\n * }\n * }\n * });\n * ```\n */\n events?: EventsConfig;\n\n /**\n * Debug mode for local span inspection.\n * Enables console output to help you see spans as they're created.\n *\n * - `true`: Raw JSON output (ConsoleSpanExporter)\n * - `'pretty'`: Colorized, hierarchical output (PrettyConsoleExporter)\n * - `false`/undefined: No console output (default)\n *\n * When enabled: Outputs spans to console AND sends to backend (if endpoint/exporter configured)\n *\n * Perfect for progressive development:\n * - Start with debug: 'pretty' (no endpoint) → see traces immediately with nice formatting\n * - Add endpoint later → console + backend, verify before choosing provider\n * - Remove debug in production → backend only, clean production config\n *\n * Can be overridden with AUTOTEL_DEBUG environment variable.\n *\n * @example Pretty debug output (recommended for development)\n * ```typescript\n * init({\n * service: 'my-app',\n * debug: 'pretty' // Colorized, hierarchical output\n * })\n * ```\n *\n * @example Raw JSON output (verbose)\n * ```typescript\n * init({\n * service: 'my-app',\n * debug: true // Raw ConsoleSpanExporter output\n * })\n * ```\n *\n * @example Environment variable\n * ```bash\n * AUTOTEL_DEBUG=pretty node server.js\n * AUTOTEL_DEBUG=true node server.js\n * ```\n */\n debug?: boolean | 'pretty';\n\n /**\n * Filter predicate to drop unwanted spans before processing.\n *\n * Useful for filtering out noisy spans from specific instrumentations\n * (e.g., Next.js internal spans, health check endpoints).\n *\n * The filter runs on completed spans (onEnd), so you have access to:\n * - `span.name` - Span name\n * - `span.attributes` - All span attributes\n * - `span.instrumentationScope` - `{ name, version }` of the instrumentation\n * - `span.status` - Span status code and message\n * - `span.duration` - Span duration as `[seconds, nanoseconds]`\n *\n * Return `true` to keep the span, `false` to drop it.\n *\n * @example Filter out Next.js instrumentation spans\n * ```typescript\n * init({\n * service: 'my-app',\n * spanFilter: (span) => span.instrumentationScope.name !== 'next.js'\n * })\n * ```\n *\n * @example Filter out health check spans\n * ```typescript\n * init({\n * service: 'my-app',\n * spanFilter: (span) => !span.name.includes('/health')\n * })\n * ```\n *\n * @example Complex filtering (multiple conditions)\n * ```typescript\n * init({\n * service: 'my-app',\n * spanFilter: (span) => {\n * // Drop Next.js internal spans\n * if (span.instrumentationScope.name === 'next.js') return false;\n * // Drop health checks\n * if (span.name.includes('/health')) return false;\n * // Drop very short spans (less than 1ms)\n * const [secs, nanos] = span.duration;\n * if (secs === 0 && nanos < 1_000_000) return false;\n * return true;\n * }\n * })\n * ```\n */\n spanFilter?: SpanFilterPredicate;\n\n /**\n * Normalize span names to reduce cardinality from dynamic path segments.\n *\n * High-cardinality span names (e.g., `/users/123/posts/456`) cause issues:\n * - Cost explosions in observability backends\n * - Cardinality limits exceeded\n * - Poor UX when searching/filtering traces\n *\n * The normalizer transforms dynamic segments into placeholders:\n * - `/users/123` → `/users/:id`\n * - `/items/550e8400-e29b-...` → `/items/:uuid`\n *\n * Provide either a custom function or use a built-in preset:\n * - `'rest-api'` - Numeric IDs, UUIDs, ObjectIds, dates, timestamps, emails\n * - `'graphql'` - GraphQL operation name normalization\n * - `'minimal'` - Only numeric IDs and UUIDs\n *\n * @example Custom normalizer function\n * ```typescript\n * init({\n * service: 'my-app',\n * spanNameNormalizer: (name) => {\n * return name\n * .replace(/\\/[0-9]+/g, '/:id')\n * .replace(/\\/[a-f0-9-]{36}/gi, '/:uuid');\n * }\n * })\n * ```\n *\n * @example Using built-in preset\n * ```typescript\n * init({\n * service: 'my-app',\n * spanNameNormalizer: 'rest-api'\n * })\n * ```\n *\n * @example Combining with spanFilter\n * ```typescript\n * init({\n * service: 'my-app',\n * spanNameNormalizer: 'rest-api',\n * spanFilter: (span) => span.instrumentationScope.name !== 'next.js'\n * })\n * ```\n */\n spanNameNormalizer?: SpanNameNormalizerConfig;\n\n /**\n * Automatically redact PII and sensitive data from span attributes before export.\n * Critical for compliance (GDPR, PCI-DSS, HIPAA) and data security.\n *\n * Auto-enabled in production: when this is left unset and the resolved\n * environment is `production`, the `'default'` preset is applied. Override\n * with the `AUTOTEL_REDACT_PII` env var (`off` / `strict` / `pci-dss` / ...)\n * or pass `false` to disable redaction entirely.\n *\n * Can be a preset name, custom configuration, or `false` to disable:\n * - `'default'`: Emails, phones, SSNs, credit cards, sensitive keys (password, secret, token)\n * - `'strict'`: Default + Bearer tokens, JWTs, API keys in values\n * - `'pci-dss'`: Payment card industry focus (credit cards, CVV, card-related keys)\n *\n * @example Use default preset\n * ```typescript\n * init({\n * service: 'my-app',\n * attributeRedactor: 'default'\n * })\n * ```\n *\n * @example Custom patterns\n * ```typescript\n * init({\n * service: 'my-app',\n * attributeRedactor: {\n * keyPatterns: [/password/i, /secret/i],\n * valuePatterns: [\n * { name: 'customerId', pattern: /CUST-\\d{8}/g, replacement: 'CUST-***' }\n * ]\n * }\n * })\n * ```\n *\n * @example Custom redactor function\n * ```typescript\n * init({\n * service: 'my-app',\n * attributeRedactor: {\n * redactor: (key, value) => {\n * if (key === 'user.email' && typeof value === 'string') {\n * return value.replace(/@.+/, '@[REDACTED]');\n * }\n * return value;\n * }\n * }\n * })\n * ```\n */\n attributeRedactor?: AttributeRedactorConfig | AttributeRedactorPreset | false;\n\n /**\n * OpenLLMetry integration for LLM observability.\n * Requires @traceloop/node-server-sdk as an optional peer dependency.\n *\n * @example Enable OpenLLMetry with default settings\n * ```typescript\n * init({\n * service: 'my-app',\n * openllmetry: { enabled: true }\n * })\n * ```\n *\n * @example Enable with custom options\n * ```typescript\n * init({\n * service: 'my-app',\n * openllmetry: {\n * enabled: true,\n * options: {\n * disableBatch: process.env.NODE_ENV !== 'production',\n * apiKey: process.env.TRACELOOP_API_KEY\n * }\n * }\n * })\n * ```\n */\n openllmetry?: {\n enabled: boolean;\n options?: Record<string, unknown>;\n };\n\n /**\n * Canonical log lines - automatically emit spans as wide events (canonical log lines)\n *\n * When enabled, each span (or root span only) is automatically emitted as a\n * comprehensive log record with ALL span attributes. This implements the\n * \"canonical log line\" pattern: one comprehensive event per request with all context.\n *\n * **Benefits:**\n * - One log line per request with all context (wide event)\n * - High-cardinality, high-dimensionality data for powerful queries\n * - Automatic - no manual logging needed\n * - Queryable as structured data instead of string search\n *\n * @example Basic usage (one canonical log line per request)\n * ```typescript\n * init({\n * service: 'checkout-api',\n * canonicalLogLines: {\n * enabled: true,\n * rootSpansOnly: true, // One canonical log line per request\n * },\n * });\n * ```\n *\n * @example With custom logger\n * ```typescript\n * import pino from 'pino';\n * const logger = pino();\n * init({\n * service: 'my-app',\n * logger,\n * canonicalLogLines: {\n * enabled: true,\n * logger, // Use Pino for canonical log lines\n * rootSpansOnly: true,\n * },\n * });\n * ```\n *\n * @example Custom message format\n * ```typescript\n * init({\n * service: 'my-app',\n * canonicalLogLines: {\n * enabled: true,\n * messageFormat: (span) => {\n * const status = span.status.code === 2 ? 'ERROR' : 'SUCCESS';\n * return `${span.name} [${status}]`;\n * },\n * },\n * });\n * ```\n */\n canonicalLogLines?: {\n enabled: boolean;\n /** Logger to use for emitting canonical log lines (defaults to OTel Logs API) */\n logger?: Logger;\n /** Only emit canonical log lines for root spans (default: false) */\n rootSpansOnly?: boolean;\n /** Minimum log level for canonical log lines (default: 'info') */\n minLevel?: 'debug' | 'info' | 'warn' | 'error';\n /** Custom message format (default: uses span name) */\n messageFormat?: (\n span: import('@opentelemetry/sdk-trace-base').ReadableSpan,\n ) => string;\n /** Whether to include resource attributes (default: true) */\n includeResourceAttributes?: boolean;\n /** Predicate to decide whether to emit (runs after event is built). */\n shouldEmit?: CanonicalLogLineOptions['shouldEmit'];\n /**\n * Declarative tail sampling conditions (OR logic).\n * Ignored when `shouldEmit` is provided.\n * @example keep: [{ status: 500 }, { durationMs: 1000 }]\n */\n keep?: CanonicalLogLineOptions['keep'];\n /** Callback invoked after emit for custom fan-out. */\n drain?: CanonicalLogLineOptions['drain'];\n /** Handler for drain failures. */\n onDrainError?: CanonicalLogLineOptions['onDrainError'];\n /**\n * Pretty-print canonical log lines to console.\n * Defaults to true when NODE_ENV is 'development'.\n */\n pretty?: boolean;\n };\n\n /**\n * Suppress console output while keeping OTel exporters running.\n * Useful for platforms like GCP Cloud Run / AWS Lambda where stdout\n * is managed externally by the platform's log collector.\n *\n * @default false\n */\n silent?: boolean;\n\n /**\n * Minimum log level for internal autotel diagnostic messages.\n * Messages below this level are dropped before processing.\n *\n * @default 'info'\n */\n minLevel?: 'debug' | 'info' | 'warn' | 'error';\n}\n\n// Internal state\nlet initialized = false;\nlet locked = false;\nlet config: AutotelConfig | null = null;\nlet sdk: NodeSDK | null = null;\nlet warnedOnce = false;\nlet logger: Logger = silentLogger; // Silent by default - no spam\nlet validationConfig: Partial<ValidationConfig> | null = null;\nlet eventsConfig: EventsConfig | null = null;\nlet _stringRedactor: StringRedactor | null = null;\nlet _optionalRequire: typeof safeRequire = safeRequire;\nlet _devtoolsClose: (() => Promise<void> | void) | null = null;\n\nconst LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 } as const;\ntype LogLevelKey = keyof typeof LOG_LEVELS;\n\n/**\n * Lock the logger to prevent further `init()` calls.\n * Use this when framework plugins set up instrumentation and you want\n * to prevent accidental re-initialization from user code.\n */\nexport function lockLogger(): void {\n locked = true;\n}\n\n/**\n * Check if the logger has been locked.\n */\nexport function isLoggerLocked(): boolean {\n return locked;\n}\n\nfunction createSilentLogger(): Logger {\n return {\n info: () => {},\n warn: () => {},\n error: () => {},\n debug: () => {},\n };\n}\n\nfunction wrapLogger(\n base: Logger,\n silent: boolean,\n minLevel: LogLevelKey,\n): Logger {\n if (silent) return createSilentLogger();\n const threshold = LOG_LEVELS[minLevel];\n const wrap = (fn: Logger['info'], level: LogLevelKey): Logger['info'] => {\n if (LOG_LEVELS[level] < threshold) {\n return (() => {}) as Logger['info'];\n }\n return ((...args: Parameters<Logger['info']>) =>\n fn(...args)) as Logger['info'];\n };\n return {\n debug: wrap(base.debug, 'debug'),\n info: wrap(base.info, 'info'),\n warn: wrap(base.warn, 'warn'),\n error: wrap(base.error, 'error'),\n };\n}\n\n/**\n * Resolve the effective attribute redactor. Explicit config wins (`false`\n * disables). Otherwise the `AUTOTEL_REDACT_PII` env var controls it, and as a\n * final default PII redaction is auto-enabled in production.\n */\nexport function resolveAttributeRedactor(\n explicit:\n | AttributeRedactorConfig\n | AttributeRedactorPreset\n | false\n | undefined,\n environment: string,\n): AttributeRedactorConfig | AttributeRedactorPreset | undefined {\n if (explicit === false) return undefined;\n if (explicit !== undefined) return explicit;\n\n const flag = process.env.AUTOTEL_REDACT_PII?.trim().toLowerCase();\n if (flag) {\n if (['off', 'false', '0', 'none', 'disabled'].includes(flag)) {\n return undefined;\n }\n if (flag === 'default' || flag === 'strict' || flag === 'pci-dss') {\n return flag;\n }\n if (['on', 'true', '1', 'enabled'].includes(flag)) {\n return 'default';\n }\n }\n\n return environment === 'production' ? 'default' : undefined;\n}\n\nfunction detectEnvironmentAttributes(): Record<string, string> {\n const attrs: Record<string, string> = {};\n\n const commitSha =\n process.env.COMMIT_SHA ||\n process.env.GITHUB_SHA ||\n process.env.VERCEL_GIT_COMMIT_SHA ||\n process.env.CF_PAGES_COMMIT_SHA ||\n process.env.AWS_CODEPIPELINE_EXECUTION_ID;\n if (commitSha) attrs['service.commit.sha'] = commitSha;\n\n const region =\n process.env.VERCEL_REGION ||\n process.env.AWS_REGION ||\n process.env.AWS_DEFAULT_REGION ||\n process.env.FLY_REGION ||\n process.env.CF_REGION ||\n process.env.GOOGLE_CLOUD_REGION;\n if (region) attrs['service.region'] = region;\n\n const version =\n process.env.APP_VERSION ||\n process.env.HEROKU_RELEASE_VERSION ||\n process.env.VERCEL_GIT_COMMIT_REF;\n if (version) attrs['service.deploy.version'] = version;\n\n return attrs;\n}\n\n/**\n * Resolve metrics flag with env var override support\n */\nexport function resolveMetricsFlag(\n configFlag: boolean | 'auto' = 'auto',\n): boolean {\n // 1. Check env var override (highest priority)\n const envFlag = process.env.AUTOTEL_METRICS;\n if (envFlag === 'on' || envFlag === 'true') return true;\n if (envFlag === 'off' || envFlag === 'false') return false;\n\n // 2. Check config flag\n if (configFlag === true) return true;\n if (configFlag === false) return false;\n\n // 3. Default: enabled in all environments (simpler)\n return true;\n}\n\n/**\n * Resolve logs flag with env var override support.\n * Defaults to disabled (opt-in only) to avoid unexpected log export\n * and to preserve the upstream SDK's OTEL_LOGS_EXPORTER handling.\n */\nexport function resolveLogsFlag(\n configFlag: boolean | 'auto' = 'auto',\n): boolean {\n // 1. Check env var override (highest priority)\n const envFlag = process.env.AUTOTEL_LOGS;\n if (envFlag === 'on' || envFlag === 'true') return true;\n if (envFlag === 'off' || envFlag === 'false') return false;\n\n // 2. Check config flag\n if (configFlag === true) return true;\n if (configFlag === false) return false;\n\n // 3. Default: disabled (opt-in only)\n return false;\n}\n\n/**\n * Resolve debug flag with env var override support\n *\n * Supports:\n * - `'pretty'`: Colorized, hierarchical output (PrettyConsoleExporter)\n * - `true` / `'true'` / `'1'`: Raw JSON output (ConsoleSpanExporter)\n * - `false` / `'false'` / `'0'`: Disabled\n */\nexport function resolveDebugFlag(\n configFlag?: boolean | 'pretty',\n): boolean | 'pretty' {\n // 1. Check env var override (highest priority)\n const envFlag = process.env.AUTOTEL_DEBUG;\n if (envFlag === 'pretty') return 'pretty';\n if (envFlag === 'true' || envFlag === '1') return true;\n if (envFlag === 'false' || envFlag === '0') return false;\n\n // 2. Return config flag (defaults to false)\n return configFlag ?? false;\n}\n\nfunction normalizeOtlpHeaders(\n headers?: Record<string, string> | string,\n): Record<string, string> | undefined {\n if (!headers) return undefined;\n if (typeof headers !== 'string') return headers;\n\n const parsed: Record<string, string> = {};\n for (const pair of headers.split(',')) {\n const [key, ...valueParts] = pair.split('=');\n if (!key || valueParts.length === 0) continue;\n parsed[key.trim()] = valueParts.join('=').trim();\n }\n return parsed;\n}\n\ntype ResolvedOtlpDestination = {\n endpoint: string;\n protocol: 'http' | 'grpc';\n headers?: Record<string, string>;\n signals?: Set<OtlpSignal>;\n};\n\nfunction resolveOtlpDestinations(\n config: AutotelConfig,\n fallbackEndpoint?: string,\n): ResolvedOtlpDestination[] {\n const rawDestinations =\n config.destinations !== undefined\n ? config.destinations\n : fallbackEndpoint\n ? [\n {\n endpoint: fallbackEndpoint,\n headers: config.headers,\n protocol: config.protocol,\n },\n ]\n : [];\n\n return rawDestinations.map((destination) => ({\n endpoint: destination.endpoint,\n protocol: resolveProtocol(destination.protocol ?? config.protocol),\n headers: normalizeOtlpHeaders(destination.headers ?? config.headers),\n signals: destination.signals ? new Set(destination.signals) : undefined,\n }));\n}\n\nfunction destinationSupportsSignal(\n destination: ResolvedOtlpDestination,\n signal: OtlpSignal,\n): boolean {\n return destination.signals ? destination.signals.has(signal) : true;\n}\n\n/**\n * Initialize autotel - Write Once, Observe Everywhere\n *\n * Follows OpenTelemetry standards: opinionated defaults with full flexibility\n * Idempotent: multiple calls are safe, last one wins\n *\n * @example Minimal setup (OTLP default)\n * ```typescript\n * init({ service: 'my-app' })\n * ```\n *\n * @example With events (observe in PostHog, Mixpanel, etc.)\n * ```typescript\n * import { PostHogSubscriber } from 'autotel-subscribers/posthog';\n *\n * init({\n * service: 'my-app',\n * subscribers: [new PostHogSubscriber({ apiKey: '...' })]\n * })\n * ```\n *\n * @example Observe in Jaeger\n * ```typescript\n * import { JaegerExporter } from '@opentelemetry/exporter-jaeger'\n *\n * init({\n * service: 'my-app',\n * spanExporter: new JaegerExporter({ endpoint: 'http://localhost:14268/api/traces' })\n * })\n * ```\n *\n * @example Observe in Zipkin\n * ```typescript\n * import { ZipkinExporter } from '@opentelemetry/exporter-zipkin'\n *\n * init({\n * service: 'my-app',\n * spanExporter: new ZipkinExporter({ url: 'http://localhost:9411/api/v2/spans' })\n * })\n * ```\n *\n * @example Observe in Datadog\n * ```typescript\n * import { DatadogSpanProcessor } from '@opentelemetry/exporter-datadog'\n *\n * init({\n * service: 'my-app',\n * spanProcessor: new DatadogSpanProcessor({ ... })\n * })\n * ```\n *\n * @example Console output (dev)\n * ```typescript\n * import { ConsoleSpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'\n *\n * init({\n * service: 'my-app',\n * spanProcessor: new SimpleSpanProcessor(new ConsoleSpanExporter())\n * })\n * ```\n */\n\nexport function init(cfg: AutotelConfig): void {\n if (locked) {\n return;\n }\n\n // Resolve configs in priority order: explicit > yaml > env > defaults\n const envConfig = resolveConfigFromEnv();\n const yamlConfig = loadYamlConfig() ?? {};\n\n // Merge configs: explicit config > yaml file > env vars > defaults\n const mergedConfig: AutotelConfig = {\n ...envConfig, // Environment variables (lowest priority)\n ...yamlConfig, // YAML file (middle priority)\n ...cfg, // Explicit config (highest priority)\n // Deep merge for resourceAttributes\n resourceAttributes: {\n ...envConfig.resourceAttributes,\n ...yamlConfig.resourceAttributes,\n ...detectEnvironmentAttributes(),\n ...cfg.resourceAttributes,\n },\n // Handle headers merge (can be string or object)\n headers: cfg.headers ?? yamlConfig.headers ?? envConfig.headers,\n } as AutotelConfig;\n\n const resolvedRedactor = resolveAttributeRedactor(\n mergedConfig.attributeRedactor,\n mergedConfig.environment || process.env.NODE_ENV || 'development',\n );\n if (resolvedRedactor === undefined) {\n mergedConfig.attributeRedactor = undefined;\n } else {\n const normalizedRedactor =\n normalizeAttributeRedactorConfig(resolvedRedactor);\n if (!normalizedRedactor) {\n throw new Error('Invalid attributeRedactor config');\n }\n mergedConfig.attributeRedactor = normalizedRedactor;\n }\n\n const devtoolsConfig = resolveDevtoolsConfig(mergedConfig.devtools);\n if (devtoolsConfig.enabled && mergedConfig.logs === undefined) {\n mergedConfig.logs = true;\n }\n\n const silent = mergedConfig.silent ?? false;\n const minLevel = mergedConfig.minLevel ?? 'info';\n const baseLogger = mergedConfig.logger || silentLogger;\n logger = wrapLogger(baseLogger, silent, minLevel);\n\n // Warn if re-initializing (same behavior in all environments)\n if (initialized) {\n logger.warn(\n {},\n '[autotel] init() called again - last config wins. This may cause unexpected behavior.',\n );\n }\n\n config = mergedConfig;\n validationConfig = mergedConfig.validation || null;\n eventsConfig = mergedConfig.events || null;\n\n // Initialize OpenTelemetry\n // Only use endpoint if explicitly configured (no default fallback)\n let endpoint = mergedConfig.endpoint ?? devtoolsConfig.endpoint;\n const version = mergedConfig.version || detectVersion();\n const environment =\n mergedConfig.environment || process.env.NODE_ENV || 'development';\n const metricsEnabled = resolveMetricsFlag(mergedConfig.metrics);\n const logsEnabled = resolveLogsFlag(mergedConfig.logs);\n\n if (devtoolsConfig.enabled && devtoolsConfig.embedded) {\n const devtoolsModule = _optionalRequire<{\n createDevtools?: (options?: {\n port?: number;\n host?: string;\n verbose?: boolean;\n }) => { port: number; close: () => Promise<void> | void };\n }>('autotel-devtools');\n\n if (devtoolsModule?.createDevtools) {\n const devtoolsInstance = devtoolsModule.createDevtools({\n port: devtoolsConfig.port,\n host: devtoolsConfig.host,\n verbose: devtoolsConfig.verbose,\n });\n _devtoolsClose = devtoolsInstance.close;\n endpoint = `http://${devtoolsConfig.host}:${devtoolsInstance.port}`;\n logger.info(\n {},\n `[autotel] autotel-devtools embedded server started at ${endpoint}`,\n );\n } else {\n logger.warn(\n {},\n '[autotel] devtools.embedded requested but autotel-devtools is not installed. Falling back to endpoint-only mode.',\n );\n }\n }\n\n // Detect hostname for proper Datadog correlation and Service Catalog discovery\n const hostname = detectHostname();\n\n let resource = resourceFromAttributes({\n [ATTR_SERVICE_NAME]: mergedConfig.service,\n [ATTR_SERVICE_VERSION]: version,\n // Support both old and new OpenTelemetry semantic conventions for environment\n 'deployment.environment': environment, // Deprecated but widely supported\n 'deployment.environment.name': environment, // OTel v1.27.0+ standard\n });\n\n // Add hostname attributes for Datadog Service Catalog and infrastructure correlation\n if (hostname) {\n resource = resource.merge(\n resourceFromAttributes({\n 'host.name': hostname, // OpenTelemetry standard\n 'datadog.host.name': hostname, // Datadog-specific, highest priority for Datadog\n }),\n );\n }\n\n if (mergedConfig.resource) {\n resource = resource.merge(mergedConfig.resource);\n }\n\n if (mergedConfig.resourceAttributes) {\n resource = resource.merge(\n resourceFromAttributes(mergedConfig.resourceAttributes),\n );\n }\n\n const otlpDestinations = resolveOtlpDestinations(mergedConfig, endpoint);\n\n // Backward-compatible singular aliases. Plural forms take precedence when both are provided.\n const configuredSpanProcessors =\n mergedConfig.spanProcessors && mergedConfig.spanProcessors.length > 0\n ? mergedConfig.spanProcessors\n : mergedConfig.spanProcessor\n ? [mergedConfig.spanProcessor]\n : undefined;\n const configuredSpanExporters =\n mergedConfig.spanExporters && mergedConfig.spanExporters.length > 0\n ? mergedConfig.spanExporters\n : mergedConfig.spanExporter\n ? [mergedConfig.spanExporter]\n : undefined;\n const configuredMetricReaders =\n mergedConfig.metricReaders && mergedConfig.metricReaders.length > 0\n ? mergedConfig.metricReaders\n : mergedConfig.metricReader\n ? [mergedConfig.metricReader]\n : undefined;\n const configuredLogRecordProcessors =\n mergedConfig.logRecordProcessors &&\n mergedConfig.logRecordProcessors.length > 0\n ? mergedConfig.logRecordProcessors\n : mergedConfig.logRecordProcessor\n ? [mergedConfig.logRecordProcessor]\n : undefined;\n\n // Build array of span processors (supports multiple)\n let spanProcessors: SpanProcessor[] = [];\n\n if (configuredSpanProcessors && configuredSpanProcessors.length > 0) {\n // User provided custom processors (full control)\n spanProcessors.push(...configuredSpanProcessors);\n } else if (configuredSpanExporters && configuredSpanExporters.length > 0) {\n // User provided custom exporters (wrap each with tail sampling)\n for (const exporter of configuredSpanExporters) {\n spanProcessors.push(\n new TailSamplingSpanProcessor(new BatchSpanProcessor(exporter)),\n );\n }\n } else {\n for (const destination of otlpDestinations) {\n if (!destinationSupportsSignal(destination, 'traces')) continue;\n\n const traceExporter = createTraceExporter(destination.protocol, {\n url: formatEndpointUrl(\n destination.endpoint,\n 'traces',\n destination.protocol,\n ),\n headers: destination.headers,\n });\n\n spanProcessors.push(\n new TailSamplingSpanProcessor(new BatchSpanProcessor(traceExporter)),\n );\n }\n }\n // If no endpoint and no custom processors/exporters, array remains empty\n // SDK will still work but won't export traces\n\n // Add baggage span processor if enabled\n if (mergedConfig.baggage) {\n const prefix =\n typeof mergedConfig.baggage === 'string'\n ? mergedConfig.baggage\n ? `${mergedConfig.baggage}.`\n : ''\n : 'baggage.';\n spanProcessors.push(new BaggageSpanProcessor({ prefix }));\n }\n\n // Apply debug mode configuration\n const debugMode = resolveDebugFlag(mergedConfig.debug);\n\n if (debugMode === 'pretty') {\n // Pretty debug: colorized, hierarchical output\n spanProcessors.push(new SimpleSpanProcessor(new PrettyConsoleExporter()));\n } else if (debugMode === true) {\n // Raw debug: JSON output\n spanProcessors.push(new SimpleSpanProcessor(new ConsoleSpanExporter()));\n }\n\n // Add canonical log line processor BEFORE wrapping processors\n // This ensures it gets wrapped with the same filter/normalizer/redactor as other processors,\n // so canonical logs respect spanFilter (filtered spans aren't logged), spanNameNormalizer\n // (normalized names are used), and attributeRedactor (sensitive data is redacted).\n if (mergedConfig.canonicalLogLines?.enabled) {\n const canonicalOptions: CanonicalLogLineOptions = {\n logger: mergedConfig.canonicalLogLines.logger || mergedConfig.logger,\n rootSpansOnly: mergedConfig.canonicalLogLines.rootSpansOnly,\n minLevel: mergedConfig.canonicalLogLines.minLevel,\n messageFormat: mergedConfig.canonicalLogLines.messageFormat,\n includeResourceAttributes:\n mergedConfig.canonicalLogLines.includeResourceAttributes,\n shouldEmit: mergedConfig.canonicalLogLines.shouldEmit,\n keep: mergedConfig.canonicalLogLines.keep,\n drain: mergedConfig.canonicalLogLines.drain,\n onDrainError: mergedConfig.canonicalLogLines.onDrainError,\n pretty: mergedConfig.canonicalLogLines.pretty,\n };\n spanProcessors.push(new CanonicalLogLineProcessor(canonicalOptions));\n }\n\n // Wrap processors in order: redactor (innermost) → normalizer → filter (outermost)\n // This ensures onEnd() execution order is: filter → normalizer → redactor\n // So filtering sees original attributes, and redaction happens last before export.\n\n // Step 1: Wrap with AttributeRedactingProcessor (innermost - executes last in onEnd)\n if (mergedConfig.attributeRedactor && spanProcessors.length > 0) {\n const redactor = mergedConfig.attributeRedactor;\n spanProcessors = spanProcessors.map(\n (processor) =>\n new AttributeRedactingProcessor(processor, {\n redactor,\n }),\n );\n }\n\n // Store string redactor for use by PostHog log/subscriber paths\n if (mergedConfig.attributeRedactor) {\n _stringRedactor = createStringRedactor(mergedConfig.attributeRedactor);\n }\n\n // Wire string redactor to subscribers that support it (e.g., PostHogSubscriber)\n if (_stringRedactor && mergedConfig.subscribers) {\n for (const subscriber of mergedConfig.subscribers) {\n if (\n 'setStringRedactor' in subscriber &&\n typeof (subscriber as any).setStringRedactor === 'function'\n ) {\n (subscriber as any).setStringRedactor(_stringRedactor);\n }\n }\n }\n\n // Step 2: Wrap with SpanNameNormalizingProcessor (middle)\n // Normalizer runs in onStart(), so span names are normalized before any onEnd processing\n if (mergedConfig.spanNameNormalizer && spanProcessors.length > 0) {\n spanProcessors = spanProcessors.map(\n (processor) =>\n new SpanNameNormalizingProcessor(processor, {\n normalizer: mergedConfig.spanNameNormalizer!,\n }),\n );\n }\n\n // Step 3: Wrap with FilteringSpanProcessor (outermost - executes first in onEnd)\n // Filter sees original (unredacted) attributes, so it can match on sensitive values\n if (mergedConfig.spanFilter && spanProcessors.length > 0) {\n spanProcessors = spanProcessors.map(\n (processor) =>\n new FilteringSpanProcessor(processor, {\n filter: mergedConfig.spanFilter!,\n }),\n );\n }\n\n // Build array of metric readers (supports multiple)\n const metricReaders: MetricReader[] = [];\n\n if (configuredMetricReaders && configuredMetricReaders.length > 0) {\n // User provided custom metric readers\n metricReaders.push(...configuredMetricReaders);\n } else if (metricsEnabled) {\n for (const destination of otlpDestinations) {\n if (!destinationSupportsSignal(destination, 'metrics')) continue;\n\n const metricExporter = createMetricExporter(destination.protocol, {\n url: formatEndpointUrl(\n destination.endpoint,\n 'metrics',\n destination.protocol,\n ),\n headers: destination.headers,\n });\n\n metricReaders.push(\n new PeriodicExportingMetricReader({\n exporter: metricExporter,\n }),\n );\n }\n }\n\n let logRecordProcessors: LogRecordProcessor[] | undefined;\n if (\n configuredLogRecordProcessors &&\n configuredLogRecordProcessors.length > 0\n ) {\n logRecordProcessors = [...configuredLogRecordProcessors];\n }\n\n // Auto-configure OTLP log exporters when logs are enabled.\n if (logsEnabled) {\n for (const destination of otlpDestinations) {\n if (!destinationSupportsSignal(destination, 'logs')) continue;\n\n const logExporter = createLogExporter(destination.protocol, {\n url: formatEndpointUrl(\n destination.endpoint,\n 'logs',\n destination.protocol,\n ),\n headers: destination.headers,\n });\n\n let processor: LogRecordProcessor = new BatchLogRecordProcessor(\n logExporter,\n );\n if (_stringRedactor) {\n processor = new RedactingLogRecordProcessor(processor, _stringRedactor);\n }\n if (!logRecordProcessors) {\n logRecordProcessors = [];\n }\n logRecordProcessors.push(processor);\n }\n\n if (\n otlpDestinations.some((destination) =>\n destinationSupportsSignal(destination, 'logs'),\n )\n ) {\n logger.info({}, '[autotel] OTLP log exporter configured');\n }\n }\n\n // PostHog OTLP logs integration\n const posthogProcessors = buildPostHogLogProcessors(\n mergedConfig.posthog,\n _stringRedactor,\n );\n if (posthogProcessors.length > 0) {\n if (!logRecordProcessors) {\n logRecordProcessors = [];\n }\n logRecordProcessors.push(...posthogProcessors);\n logger.info({}, '[autotel] PostHog OTLP logs configured');\n }\n\n // Handle instrumentations: merge manual instrumentations with auto-instrumentations\n let finalInstrumentations: NodeSDKConfiguration['instrumentations'] =\n mergedConfig.instrumentations ? [...mergedConfig.instrumentations] : [];\n\n if (\n mergedConfig.autoInstrumentations !== undefined &&\n mergedConfig.autoInstrumentations !== false\n ) {\n // Check for ESM mode and provide guidance\n const isESM = isESMMode();\n if (isESM) {\n logger.info(\n {},\n '[autotel] ESM mode detected. For auto-instrumentation to work:\\n' +\n ' 1. Install @opentelemetry/auto-instrumentations-node as a direct dependency\\n' +\n ' 2. Import autotel/register FIRST in your instrumentation file\\n' +\n ' 3. Use getNodeAutoInstrumentations() directly instead of autoInstrumentations\\n' +\n ' See: https://github.com/jagreehal/autotel#esm-setup',\n );\n }\n\n try {\n // Detect manual instrumentations to avoid conflicts\n const manualInstrumentationNames = getInstrumentationNames(\n mergedConfig.instrumentations ?? [],\n );\n\n // Warn if both autoInstrumentations and manual instrumentations are provided\n if (manualInstrumentationNames.size > 0) {\n const manualNames = [...manualInstrumentationNames].join(', ');\n logger.info(\n {},\n `[autotel] Detected manual instrumentations (${manualNames}). ` +\n 'These will take precedence over auto-instrumentations. ' +\n 'Tip: Set autoInstrumentations:false if you want full manual control, or remove manual configs to use auto-instrumentations.',\n );\n }\n\n const autoInstrumentations = getAutoInstrumentations(\n mergedConfig.autoInstrumentations,\n manualInstrumentationNames,\n );\n if (autoInstrumentations && autoInstrumentations.length > 0) {\n // Cast to proper type - getNodeAutoInstrumentations returns the correct type\n finalInstrumentations = [\n ...finalInstrumentations,\n ...(autoInstrumentations as NodeSDKConfiguration['instrumentations']),\n ];\n }\n } catch (error) {\n logger.warn(\n {},\n `[autotel] Failed to configure auto-instrumentations: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n const autotelSampler =\n mergedConfig.sampler ??\n (mergedConfig.sampling\n ? resolveSamplingPreset(mergedConfig.sampling)\n : undefined);\n if (autotelSampler) {\n mergedConfig.sampler = autotelSampler;\n }\n const sampler: OtelSampler = autotelSampler\n ? toOtelSampler(autotelSampler)\n : (envConfig.otelSampler ?? toOtelSampler(samplingPresets.production()));\n\n const sdkOptions: Partial<NodeSDKConfiguration> = {\n resource,\n sampler,\n instrumentations: finalInstrumentations,\n };\n\n if (spanProcessors.length > 0) {\n sdkOptions.spanProcessors = spanProcessors;\n }\n\n if (metricReaders.length > 0) {\n sdkOptions.metricReaders = metricReaders;\n }\n\n if (logRecordProcessors && logRecordProcessors.length > 0) {\n sdkOptions.logRecordProcessors = logRecordProcessors;\n }\n\n sdk = mergedConfig.sdkFactory\n ? mergedConfig.sdkFactory(sdkOptions)\n : new NodeSDK(sdkOptions);\n\n if (!sdk) {\n throw new Error('[autotel] sdkFactory must return a NodeSDK instance');\n }\n\n sdk.start();\n\n // Initialize OpenLLMetry if enabled (after SDK starts to reuse tracer provider)\n if (mergedConfig.openllmetry?.enabled) {\n const traceloop = _optionalRequire<{\n initialize?: (options?: Record<string, unknown>) => void;\n }>('@traceloop/node-server-sdk');\n\n if (traceloop) {\n const initOptions: Record<string, unknown> = {\n ...mergedConfig.openllmetry.options,\n };\n\n // Reuse autotel's tracer provider\n try {\n // Type assertion needed as getTracerProvider is not in the public NodeSDK interface\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const tracerProvider = (sdk as any).getTracerProvider();\n initOptions.tracerProvider = tracerProvider;\n } catch {\n // Ignore if tracer provider not available\n }\n\n // Pass span exporter to OpenLLMetry if provided\n if (configuredSpanExporters?.[0]) {\n initOptions.exporter = configuredSpanExporters[0];\n }\n\n if (typeof traceloop.initialize === 'function') {\n traceloop.initialize(initOptions);\n logger.info({}, '[autotel] OpenLLMetry initialized successfully');\n } else {\n logger.warn(\n {},\n '[autotel] OpenLLMetry initialize function not found. Check @traceloop/node-server-sdk version.',\n );\n }\n } else {\n logger.warn(\n {},\n '[autotel] OpenLLMetry enabled but @traceloop/node-server-sdk is not installed. ' +\n 'Install it as a peer dependency to use OpenLLMetry integration.',\n );\n }\n }\n\n initialized = true;\n}\n\n/**\n * Extract instrumentation class names from instrumentation instances\n * Used to detect duplicates between manual and auto instrumentations\n */\nfunction getInstrumentationNames(\n instrumentations: NodeSDKConfiguration['instrumentations'],\n): Set<string> {\n const names = new Set<string>();\n\n if (!instrumentations) return names;\n\n for (const instrumentation of instrumentations) {\n if (instrumentation && typeof instrumentation === 'object') {\n names.add(instrumentation.constructor.name);\n }\n }\n\n return names;\n}\n\n/**\n * Map common instrumentation class names to their package names\n * Used to disable auto-instrumentations when user provides manual configs\n */\nconst INSTRUMENTATION_CLASS_TO_PACKAGE: Record<string, string> = {\n HttpInstrumentation: '@opentelemetry/instrumentation-http',\n HttpsInstrumentation: '@opentelemetry/instrumentation-http',\n ExpressInstrumentation: '@opentelemetry/instrumentation-express',\n FastifyInstrumentation: '@opentelemetry/instrumentation-fastify',\n MongoDBInstrumentation: '@opentelemetry/instrumentation-mongodb',\n MongooseInstrumentation: '@opentelemetry/instrumentation-mongoose',\n PrismaInstrumentation: '@opentelemetry/instrumentation-prisma',\n PinoInstrumentation: '@opentelemetry/instrumentation-pino',\n WinstonInstrumentation: '@opentelemetry/instrumentation-winston',\n RedisInstrumentation: '@opentelemetry/instrumentation-redis',\n GraphQLInstrumentation: '@opentelemetry/instrumentation-graphql',\n GrpcInstrumentation: '@opentelemetry/instrumentation-grpc',\n IORedisInstrumentation: '@opentelemetry/instrumentation-ioredis',\n KnexInstrumentation: '@opentelemetry/instrumentation-knex',\n NestJsInstrumentation: '@opentelemetry/instrumentation-nestjs-core',\n PgInstrumentation: '@opentelemetry/instrumentation-pg',\n MySQLInstrumentation: '@opentelemetry/instrumentation-mysql',\n MySQL2Instrumentation: '@opentelemetry/instrumentation-mysql2',\n};\n\n/**\n * Type for the auto-instrumentations loader function\n * @internal Used for testing injection\n */\nexport type AutoInstrumentationsLoader = (\n config?: Record<string, { enabled?: boolean }>,\n) => unknown[];\n\n/**\n * Detect if we're running in ESM mode\n */\nfunction isESMMode(): boolean {\n // Check if we're in an ESM context by looking for common ESM indicators\n try {\n // In ESM, module.exports doesn't exist in the global scope the same way\n // Also check if the package.json type is \"module\"\n const fs = requireModule<typeof import('node:fs')>('node:fs');\n try {\n const pkg = JSON.parse(\n fs.readFileSync(`${process.cwd()}/package.json`, 'utf8'),\n );\n return pkg.type === 'module';\n } catch {\n return false;\n }\n } catch {\n return false;\n }\n}\n\n/**\n * Lazy-load auto-instrumentations (optional peer dependency)\n * Only loads when integrations config is truthy, avoiding ~40+ package imports at startup.\n */\nfunction loadNodeAutoInstrumentations(): AutoInstrumentationsLoader {\n try {\n const mod = requireModule<{\n getNodeAutoInstrumentations: AutoInstrumentationsLoader;\n }>('@opentelemetry/auto-instrumentations-node');\n return mod.getNodeAutoInstrumentations;\n } catch {\n const isESM = isESMMode();\n const baseMessage = '@opentelemetry/auto-instrumentations-node not found.';\n\n if (isESM) {\n throw new Error(\n `${baseMessage}\\n\\n` +\n 'ESM Setup Required:\\n' +\n '1. Install as a direct dependency: pnpm add @opentelemetry/auto-instrumentations-node\\n' +\n '2. Create instrumentation.mjs with:\\n' +\n \" import 'autotel/register'; // MUST be first!\\n\" +\n \" import { init } from 'autotel';\\n\" +\n \" import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';\\n\" +\n ' init({ service: \"my-app\", instrumentations: getNodeAutoInstrumentations() });\\n' +\n '3. Run with: tsx --import ./instrumentation.mjs src/index.ts\\n\\n' +\n 'See: https://github.com/jagreehal/autotel#esm-setup',\n );\n }\n\n throw new Error(\n `${baseMessage} Install it: pnpm add @opentelemetry/auto-instrumentations-node`,\n );\n }\n}\n\n/**\n * Injectable loader for testing. Set to override the default loader.\n * @internal\n */\nlet _autoInstrumentationsLoader: (() => AutoInstrumentationsLoader) | null =\n null;\n\n/**\n * @internal Set custom loader (for testing)\n */\nexport function _setAutoInstrumentationsLoader(\n loader: (() => AutoInstrumentationsLoader) | null,\n): void {\n _autoInstrumentationsLoader = loader;\n}\n\n/**\n * @internal Reset loader to default (for testing cleanup)\n */\nexport function _resetAutoInstrumentationsLoader(): void {\n _autoInstrumentationsLoader = null;\n}\n\n/**\n * Get auto-instrumentations based on simple integration names\n * Excludes instrumentations that are manually provided to avoid conflicts\n */\nfunction getAutoInstrumentations(\n integrations: string[] | boolean | Record<string, { enabled?: boolean }>,\n manualInstrumentationNames: Set<string> = new Set(),\n): unknown[] {\n if (integrations === false) {\n return [];\n }\n\n // Use injected loader if set (for testing), otherwise lazy-load\n const getNodeAutoInstrumentations = _autoInstrumentationsLoader\n ? _autoInstrumentationsLoader()\n : loadNodeAutoInstrumentations();\n\n // Build exclusion config for manual instrumentations\n const exclusionConfig: Record<string, { enabled: boolean }> = {};\n for (const className of manualInstrumentationNames) {\n const packageName = INSTRUMENTATION_CLASS_TO_PACKAGE[className];\n if (packageName) {\n exclusionConfig[packageName] = { enabled: false };\n }\n }\n\n if (integrations === true) {\n // If exclusions exist, pass them to getNodeAutoInstrumentations\n if (Object.keys(exclusionConfig).length > 0) {\n return getNodeAutoInstrumentations(exclusionConfig);\n }\n return getNodeAutoInstrumentations();\n }\n\n if (Array.isArray(integrations)) {\n const config: Record<string, { enabled: boolean }> = { ...exclusionConfig };\n for (const name of integrations) {\n const packageName = `@opentelemetry/instrumentation-${name}`;\n // Don't override exclusions\n if (!exclusionConfig[packageName]) {\n config[packageName] = { enabled: true };\n }\n }\n return getNodeAutoInstrumentations(config);\n }\n\n const config: Record<string, { enabled?: boolean }> = {\n ...exclusionConfig,\n ...integrations,\n };\n\n // Override any integrations that conflict with manual instrumentations\n for (const packageName of Object.keys(exclusionConfig)) {\n const integrationsKey = Object.keys(integrations).find((key) =>\n packageName.includes(key),\n );\n if (integrationsKey) {\n // Manual instrumentation takes precedence\n config[packageName] = { enabled: false };\n }\n }\n\n return getNodeAutoInstrumentations(config);\n}\n\n/**\n * Check if autotel has been initialized\n */\nexport function isInitialized(): boolean {\n return initialized;\n}\n\n/**\n * Get current config (internal use)\n */\nexport function getConfig(): AutotelConfig | null {\n return config;\n}\n\n/**\n * Get current logger (internal use)\n */\nexport function getLogger(): Logger {\n return logger;\n}\n\n/**\n * Get validation config (internal use)\n */\nexport function getValidationConfig(): Partial<ValidationConfig> | null {\n return validationConfig;\n}\n\n/**\n * Get events config (internal use)\n */\nexport function getEventsConfig(): EventsConfig | null {\n return eventsConfig;\n}\n\n/**\n * Warn once if not initialized (same behavior in all environments)\n */\nexport function warnIfNotInitialized(context: string): void {\n if (!initialized && !warnedOnce) {\n logger.warn(\n {},\n `[autotel] ${context} used before init() called. ` +\n 'Call init({ service: \"...\" }) first. See: https://docs.autotel.dev/quickstart',\n );\n warnedOnce = true;\n }\n}\n\n/**\n * Get default sampler\n */\nexport function getDefaultSampler(): Sampler {\n return config?.sampler || samplingPresets.production();\n}\n\n/**\n * Auto-detect version from package.json\n */\nfunction detectVersion(): string {\n try {\n // Try to read package.json from cwd using fs\n const fs = requireModule<typeof import('node:fs')>('node:fs');\n const pkg = JSON.parse(\n fs.readFileSync(`${process.cwd()}/package.json`, 'utf8'),\n );\n return pkg.version || '1.0.0';\n } catch {\n return '1.0.0';\n }\n}\n\n/**\n * Detect hostname for resource attributes.\n * Supports Datadog conventions (DD_HOSTNAME) and falls back to system hostname.\n *\n * Priority order:\n * 1. DD_HOSTNAME environment variable (Datadog convention)\n * 2. HOSTNAME environment variable (common Unix convention)\n * 3. os.hostname() (system hostname)\n *\n * @returns hostname string or undefined if detection fails\n */\nfunction detectHostname(): string | undefined {\n // Priority 1: DD_HOSTNAME (Datadog convention)\n if (process.env.DD_HOSTNAME) {\n return process.env.DD_HOSTNAME;\n }\n\n // Priority 2: HOSTNAME (common in containers and Unix systems)\n if (process.env.HOSTNAME) {\n return process.env.HOSTNAME;\n }\n\n // Priority 3: System hostname\n try {\n const os = requireModule<typeof import('node:os')>('node:os');\n return os.hostname();\n } catch {\n // os module not available (edge runtime, browser, etc.)\n return undefined;\n }\n}\n\n/**\n * Get the string redactor configured via init({ attributeRedactor }).\n * Returns null if no redactor was configured.\n */\nexport function getStringRedactor(): StringRedactor | null {\n return _stringRedactor;\n}\n\n/**\n * @internal Override optional require for deterministic tests.\n */\nexport function _setOptionalRequireForTesting(\n loader: typeof safeRequire,\n): void {\n _optionalRequire = loader;\n}\n\n/**\n * @internal Reset optional require override.\n */\nexport function _resetOptionalRequireForTesting(): void {\n _optionalRequire = safeRequire;\n}\n\n/**\n * @internal Close embedded devtools if running.\n */\nexport async function _closeEmbeddedDevtools(): Promise<void> {\n if (_devtoolsClose) {\n await _devtoolsClose();\n _devtoolsClose = null;\n }\n}\n\n/**\n * @internal Get embedded devtools close handle.\n */\nexport function _getEmbeddedDevtoolsCloseForTesting():\n | (() => Promise<void> | void)\n | null {\n return _devtoolsClose;\n}\n\n/**\n * Get SDK instance (for shutdown)\n */\nexport function getSdk(): NodeSDK | null {\n return sdk;\n}\n"],"mappings":"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"}
@@ -214,6 +214,28 @@ interface AutotelDevtoolsConfig {
214
214
  }
215
215
  //#endregion
216
216
  //#region src/init.d.ts
217
+ type OtlpSignal = 'traces' | 'metrics' | 'logs';
218
+ interface OtlpDestinationConfig {
219
+ /**
220
+ * Base OTLP endpoint for this destination.
221
+ * HTTP destinations may omit `/v1/{signal}`; autotel appends it automatically.
222
+ * gRPC destinations should point at the collector host:port.
223
+ */
224
+ endpoint: string;
225
+ /**
226
+ * Headers for this destination. Falls back to top-level `headers`.
227
+ */
228
+ headers?: Record<string, string> | string;
229
+ /**
230
+ * Protocol for this destination. Falls back to top-level `protocol`.
231
+ */
232
+ protocol?: 'http' | 'grpc';
233
+ /**
234
+ * Signals to send to this destination.
235
+ * Defaults to all signals supported by the current init() config.
236
+ */
237
+ signals?: OtlpSignal[];
238
+ }
217
239
  interface AutotelConfig {
218
240
  /** Service name (required) */
219
241
  service: string;
@@ -328,10 +350,43 @@ interface AutotelConfig {
328
350
  }>;
329
351
  /**
330
352
  * OTLP endpoint for traces/metrics/logs
353
+ * Single-destination shorthand. For multi-backend OTLP fan-out, use
354
+ * `destinations` instead.
331
355
  * Only used if you don't provide custom exporters/processors
332
356
  * @default process.env.OTLP_ENDPOINT || 'http://localhost:4318'
333
357
  */
334
358
  endpoint?: string;
359
+ /**
360
+ * Declarative OTLP multi-destination config.
361
+ * Each destination can override endpoint, headers, protocol, and signals.
362
+ *
363
+ * This is the high-level alternative to wiring `spanExporters`,
364
+ * `spanProcessors`, `metricReaders`, and `logRecordProcessors` manually when
365
+ * you want to fan telemetry out to multiple OTLP backends.
366
+ *
367
+ * When provided, `destinations` takes precedence over the single `endpoint`
368
+ * shorthand for built-in OTLP exporters/readers/processors.
369
+ *
370
+ * @example Grafana + Honeycomb for traces, Grafana only for metrics/logs
371
+ * ```typescript
372
+ * init({
373
+ * service: 'my-app',
374
+ * logs: true,
375
+ * destinations: [
376
+ * {
377
+ * endpoint: 'https://otlp-gateway-prod-eu-west-2.grafana.net/otlp',
378
+ * headers: { Authorization: 'Basic ...' },
379
+ * },
380
+ * {
381
+ * endpoint: 'https://api.honeycomb.io',
382
+ * headers: { 'x-honeycomb-team': '...' },
383
+ * signals: ['traces'],
384
+ * },
385
+ * ],
386
+ * })
387
+ * ```
388
+ */
389
+ destinations?: OtlpDestinationConfig[];
335
390
  /**
336
391
  * Custom span processors for traces (supports multiple processors)
337
392
  * Allows you to use any backend: Jaeger, Zipkin, Datadog, New Relic, etc.
@@ -1153,5 +1208,5 @@ declare function init(cfg: AutotelConfig): void;
1153
1208
  */
1154
1209
  declare function isInitialized(): boolean;
1155
1210
  //#endregion
1156
- export { lockLogger as a, isLoggerLocked as i, init as n, StringRedactor as o, isInitialized as r, createStringRedactor as s, AutotelConfig as t };
1157
- //# sourceMappingURL=init-CNp-ee80.d.cts.map
1211
+ export { isLoggerLocked as a, createStringRedactor as c, isInitialized as i, OtlpSignal as n, lockLogger as o, init as r, StringRedactor as s, AutotelConfig as t };
1212
+ //# sourceMappingURL=init-DSrRmVnz.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-DSrRmVnz.d.cts","names":[],"sources":["../src/validation.ts","../src/redact-values.ts","../src/events-config.ts","../src/devtools.ts","../src/init.ts"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_node_require = require('./node-require-DF5QBX6z.cjs');
3
- const require_init = require('./init-DvapOXCc.cjs');
3
+ const require_init = require('./init-BX7AmFRl.cjs');
4
4
  const require_tail_sampling_processor = require('./tail-sampling-processor.cjs');
5
5
  let _opentelemetry_sdk_node = require("@opentelemetry/sdk-node");
6
6
  let _opentelemetry_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
@@ -1,5 +1,5 @@
1
1
  import { t as requireModule } from "./node-require-Db1oDpLj.js";
2
- import { i as getLogger } from "./init-Ch6t7MNI.js";
2
+ import { i as getLogger } from "./init-D-jnNMix.js";
3
3
  import { TailSamplingSpanProcessor } from "./tail-sampling-processor.js";
4
4
  import { NodeSDK } from "@opentelemetry/sdk-node";
5
5
  import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";