autotel 2.18.0 → 2.19.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 (67) hide show
  1. package/dist/attributes.cjs +21 -20
  2. package/dist/attributes.js +2 -1
  3. package/dist/chunk-2ZKEORFN.cjs +14 -0
  4. package/dist/chunk-2ZKEORFN.cjs.map +1 -0
  5. package/dist/chunk-4A53YIAX.js +180 -0
  6. package/dist/chunk-4A53YIAX.js.map +1 -0
  7. package/dist/{chunk-QKVQWGTF.js → chunk-5JLXDCL2.js} +3 -3
  8. package/dist/{chunk-QKVQWGTF.js.map → chunk-5JLXDCL2.js.map} +1 -1
  9. package/dist/chunk-7552UTQW.js +11 -0
  10. package/dist/chunk-7552UTQW.js.map +1 -0
  11. package/dist/{chunk-NWT5SYOX.cjs → chunk-BEVIAKTB.cjs} +5 -5
  12. package/dist/{chunk-NWT5SYOX.cjs.map → chunk-BEVIAKTB.cjs.map} +1 -1
  13. package/dist/chunk-ESMHTKLJ.cjs +206 -0
  14. package/dist/chunk-ESMHTKLJ.cjs.map +1 -0
  15. package/dist/{chunk-QP5LVD4L.js → chunk-G47ZCJGW.js} +25 -3
  16. package/dist/{chunk-QP5LVD4L.js.map → chunk-G47ZCJGW.js.map} +1 -1
  17. package/dist/{chunk-WC2AMGBX.js → chunk-LCMARHLX.js} +3 -3
  18. package/dist/{chunk-WC2AMGBX.js.map → chunk-LCMARHLX.js.map} +1 -1
  19. package/dist/{chunk-HZ23L5KR.cjs → chunk-LGT7XA5O.cjs} +5 -5
  20. package/dist/{chunk-HZ23L5KR.cjs.map → chunk-LGT7XA5O.cjs.map} +1 -1
  21. package/dist/{chunk-4HPWUYCV.js → chunk-M4US3P4K.js} +3 -170
  22. package/dist/chunk-M4US3P4K.js.map +1 -0
  23. package/dist/{chunk-FMPBL2NF.js → chunk-XBVB3AFF.js} +3 -3
  24. package/dist/{chunk-FMPBL2NF.js.map → chunk-XBVB3AFF.js.map} +1 -1
  25. package/dist/{chunk-DWRTSOGR.cjs → chunk-XI5WPVR5.cjs} +25 -3
  26. package/dist/chunk-XI5WPVR5.cjs.map +1 -0
  27. package/dist/{chunk-74L5DOB4.cjs → chunk-XNBTEFRZ.cjs} +7 -7
  28. package/dist/{chunk-74L5DOB4.cjs.map → chunk-XNBTEFRZ.cjs.map} +1 -1
  29. package/dist/chunk-XRBP4RYL.cjs +764 -0
  30. package/dist/chunk-XRBP4RYL.cjs.map +1 -0
  31. package/dist/decorators.cjs +1 -1
  32. package/dist/decorators.js +1 -1
  33. package/dist/functional.cjs +8 -8
  34. package/dist/functional.js +1 -1
  35. package/dist/index.cjs +65 -43
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.cts +1 -0
  38. package/dist/index.d.ts +1 -0
  39. package/dist/index.js +8 -6
  40. package/dist/index.js.map +1 -1
  41. package/dist/messaging.cjs +5 -5
  42. package/dist/messaging.js +2 -2
  43. package/dist/semantic-conventions.cjs +30 -0
  44. package/dist/semantic-conventions.cjs.map +1 -0
  45. package/dist/semantic-conventions.d.cts +29 -0
  46. package/dist/semantic-conventions.d.ts +29 -0
  47. package/dist/semantic-conventions.js +5 -0
  48. package/dist/semantic-conventions.js.map +1 -0
  49. package/dist/semantic-helpers.cjs +6 -6
  50. package/dist/semantic-helpers.js +2 -2
  51. package/dist/webhook.cjs +2 -2
  52. package/dist/webhook.js +1 -1
  53. package/dist/workflow-distributed.cjs +3 -3
  54. package/dist/workflow-distributed.js +1 -1
  55. package/dist/workflow.cjs +6 -6
  56. package/dist/workflow.js +2 -2
  57. package/package.json +16 -11
  58. package/src/decorators.test.ts +22 -72
  59. package/src/functional.test.ts +24 -6
  60. package/src/functional.ts +37 -2
  61. package/src/index.ts +9 -0
  62. package/src/init.openllmetry.test.ts +76 -76
  63. package/src/semantic-conventions.ts +15 -0
  64. package/dist/chunk-4HPWUYCV.js.map +0 -1
  65. package/dist/chunk-7F4PDILZ.cjs +0 -931
  66. package/dist/chunk-7F4PDILZ.cjs.map +0 -1
  67. package/dist/chunk-DWRTSOGR.cjs.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shutdown.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Graceful shutdown with flush and cleanup\n */\n\nimport { getSdk, getLogger } from './init';\nimport { getEventQueue, resetEventQueue } from './track';\nimport { resetEvents } from './event';\nimport { resetMetrics } from './metric';\n\n/**\n * Flush all pending telemetry\n *\n * Flushes both events events and OpenTelemetry spans to their destinations.\n * Includes timeout protection to prevent hanging in serverless environments.\n *\n * Safe to call multiple times.\n *\n * @param options - Optional configuration\n * @param options.timeout - Timeout in milliseconds (default: 2000ms)\n * @param options.forShutdown - If true, permanently disables the events queue after flush (used internally by shutdown())\n *\n * @example Manual flush in serverless\n * ```typescript\n * import { flush } from 'autotel';\n *\n * export const handler = async (event) => {\n * // ... process event\n * await flush(); // Flush before function returns\n * return result;\n * };\n * ```\n *\n * @example With custom timeout\n * ```typescript\n * await flush({ timeout: 5000 }); // 5 second timeout\n * ```\n */\nexport async function flush(options?: {\n timeout?: number;\n forShutdown?: boolean;\n}): Promise<void> {\n const timeout = options?.timeout ?? 2000;\n const forShutdown = options?.forShutdown ?? false;\n\n const doFlush = async () => {\n // Flush events queue (or shutdown queue when tearing down)\n const eventsQueue = getEventQueue();\n if (eventsQueue) {\n if (forShutdown) {\n await eventsQueue.shutdown();\n } else {\n await eventsQueue.flush();\n }\n }\n\n // Flush OpenTelemetry spans\n // This ensures spans are exported immediately, critical for serverless\n const sdk = getSdk();\n if (sdk) {\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 sdkAny = sdk as any;\n if (typeof sdkAny.getTracerProvider === 'function') {\n const tracerProvider = sdkAny.getTracerProvider();\n if (\n tracerProvider &&\n typeof tracerProvider.forceFlush === 'function'\n ) {\n await tracerProvider.forceFlush();\n }\n }\n } catch {\n // Ignore errors when accessing tracer provider (may not be available in test mocks)\n }\n }\n };\n\n // Add timeout protection to prevent hanging\n let timeoutHandle: NodeJS.Timeout | undefined;\n try {\n await Promise.race([\n doFlush().finally(() => {\n // Clear timeout as soon as flush completes\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }),\n new Promise<void>((_, reject) => {\n timeoutHandle = setTimeout(\n () => reject(new Error('Flush timeout')),\n timeout,\n );\n // Use unref() to allow Node to exit if flush completes first\n // This prevents the 2s delay in serverless when flush succeeds immediately\n timeoutHandle.unref();\n }),\n ]);\n } catch (error) {\n // Clear timeout on error too\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n const logger = getLogger();\n logger.error(\n {\n err: error instanceof Error ? error : new Error(String(error)),\n },\n '[autotel] Flush error',\n );\n throw error;\n }\n}\n\n/**\n * Shutdown telemetry and cleanup resources\n *\n * - Flushes all pending data\n * - Shuts down OpenTelemetry SDK\n * - Cleans up resources\n *\n * Call this before process exit.\n *\n * Always performs cleanup even if flush fails, preventing resource leaks\n * in serverless handlers or tests.\n *\n * @example Express server\n * ```typescript\n * const server = app.listen(3000)\n *\n * process.on('SIGTERM', async () => {\n * await server.close()\n * await shutdown()\n * process.exit(0)\n * })\n * ```\n */\nexport async function shutdown(): Promise<void> {\n const logger = getLogger();\n let shutdownError: Error | null = null;\n\n // Attempt to flush (with queue shutdown so new events are rejected), but continue with cleanup even if it fails\n try {\n await flush({ forShutdown: true });\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n shutdownError = err;\n logger.error(\n {\n err,\n },\n '[autotel] Flush failed during shutdown, continuing cleanup',\n );\n }\n\n // Always shutdown SDK and clean up resources\n try {\n // Shutdown OpenTelemetry SDK\n const sdk = getSdk();\n if (sdk) {\n await sdk.shutdown();\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n\n // Ignore ECONNREFUSED errors - this happens when no OTLP endpoint was configured\n // The SDK tries to flush exporters that don't exist, which is harmless\n const isConnectionRefused =\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n error.code === 'ECONNREFUSED';\n\n if (!isConnectionRefused) {\n // Only store/log non-connection errors\n if (!shutdownError) {\n shutdownError = err;\n }\n logger.error({ err }, '[autotel] SDK shutdown failed');\n }\n } finally {\n // Clean up singleton Maps and queues to prevent memory leaks\n // This runs even if SDK shutdown fails\n const eventsQueue = getEventQueue();\n if (eventsQueue && typeof eventsQueue.cleanup === 'function') {\n eventsQueue.cleanup();\n }\n resetEvents();\n resetMetrics();\n resetEventQueue();\n }\n\n // Rethrow first error after cleanup completes\n // This allows tests and CI to detect failures while still ensuring cleanup\n if (shutdownError) {\n throw shutdownError;\n }\n}\n\n/**\n * Register automatic shutdown hooks for common signals\n *\n * Handles:\n * - SIGTERM (Docker/K8s graceful shutdown)\n * - SIGINT (Ctrl+C)\n *\n * @internal Called automatically on module load\n */\nfunction registerShutdownHooks(): void {\n if (typeof process === 'undefined') return; // Not in Node.js\n\n const signals: NodeJS.Signals[] = ['SIGTERM', 'SIGINT'];\n let shuttingDown = false;\n\n for (const signal of signals) {\n process.on(signal, async () => {\n if (shuttingDown) return; // Prevent double shutdown\n shuttingDown = true;\n\n if (process.env.NODE_ENV !== 'test') {\n getLogger().info(\n {},\n `[autotel] Received ${signal}, flushing telemetry...`,\n );\n }\n\n try {\n await shutdown();\n } catch (error) {\n getLogger().error(\n {\n err: error instanceof Error ? error : undefined,\n },\n '[autotel] Error during shutdown',\n );\n } finally {\n process.exit(0);\n }\n });\n }\n}\n\n// Auto-register shutdown hooks\nregisterShutdownHooks();\n"]}
1
+ {"version":3,"sources":["../src/shutdown.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,eAAsB,MAAM,OAAA,EAGV;AAChB,EAAA,MAAM,OAAA,GAAU,SAAS,OAAA,IAAW,GAAA;AACpC,EAAA,MAAM,WAAA,GAAc,SAAS,WAAA,IAAe,KAAA;AAE5C,EAAA,MAAM,UAAU,YAAY;AAE1B,IAAA,MAAM,cAAc,aAAA,EAAc;AAClC,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,YAAY,QAAA,EAAS;AAAA,MAC7B,CAAA,MAAO;AACL,QAAA,MAAM,YAAY,KAAA,EAAM;AAAA,MAC1B;AAAA,IACF;AAIA,IAAA,MAAM,MAAM,MAAA,EAAO;AACnB,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,IAAI;AAGF,QAAA,MAAM,MAAA,GAAS,GAAA;AACf,QAAA,IAAI,OAAO,MAAA,CAAO,iBAAA,KAAsB,UAAA,EAAY;AAClD,UAAA,MAAM,cAAA,GAAiB,OAAO,iBAAA,EAAkB;AAChD,UAAA,IACE,cAAA,IACA,OAAO,cAAA,CAAe,UAAA,KAAe,UAAA,EACrC;AACA,YAAA,MAAM,eAAe,UAAA,EAAW;AAAA,UAClC;AAAA,QACF;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,CAAA;AAGA,EAAA,IAAI,aAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAM,QAAQ,IAAA,CAAK;AAAA,MACjB,OAAA,EAAQ,CAAE,OAAA,CAAQ,MAAM;AAEtB,QAAA,IAAI,aAAA,EAAe;AACjB,UAAA,YAAA,CAAa,aAAa,CAAA;AAAA,QAC5B;AAAA,MACF,CAAC,CAAA;AAAA,MACD,IAAI,OAAA,CAAc,CAAC,CAAA,EAAG,MAAA,KAAW;AAC/B,QAAA,aAAA,GAAgB,UAAA;AAAA,UACd,MAAM,MAAA,CAAO,IAAI,KAAA,CAAM,eAAe,CAAC,CAAA;AAAA,UACvC;AAAA,SACF;AAGA,QAAA,aAAA,CAAc,KAAA,EAAM;AAAA,MACtB,CAAC;AAAA,KACF,CAAA;AAAA,EACH,SAAS,KAAA,EAAO;AAEd,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,YAAA,CAAa,aAAa,CAAA;AAAA,IAC5B;AACA,IAAA,MAAM,SAAS,SAAA,EAAU;AACzB,IAAA,MAAA,CAAO,KAAA;AAAA,MACL;AAAA,QACE,GAAA,EAAK,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC;AAAA,OAC/D;AAAA,MACA;AAAA,KACF;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AACF;AAyBA,eAAsB,QAAA,GAA0B;AAC9C,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,aAAA,GAA8B,IAAA;AAGlC,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,CAAM,EAAE,WAAA,EAAa,IAAA,EAAM,CAAA;AAAA,EACnC,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,GAAA,GAAM,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AACpE,IAAA,aAAA,GAAgB,GAAA;AAChB,IAAA,MAAA,CAAO,KAAA;AAAA,MACL;AAAA,QACE;AAAA,OACF;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAGA,EAAA,IAAI;AAEF,IAAA,MAAM,MAAM,MAAA,EAAO;AACnB,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,MAAM,IAAI,QAAA,EAAS;AAAA,IACrB;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,GAAA,GAAM,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AAIpE,IAAA,MAAM,mBAAA,GACJ,OAAO,KAAA,KAAU,QAAA,IACjB,UAAU,IAAA,IACV,MAAA,IAAU,KAAA,IACV,KAAA,CAAM,IAAA,KAAS,cAAA;AAEjB,IAAA,IAAI,CAAC,mBAAA,EAAqB;AAExB,MAAA,IAAI,CAAC,aAAA,EAAe;AAClB,QAAA,aAAA,GAAgB,GAAA;AAAA,MAClB;AACA,MAAA,MAAA,CAAO,KAAA,CAAM,EAAE,GAAA,EAAI,EAAG,+BAA+B,CAAA;AAAA,IACvD;AAAA,EACF,CAAA,SAAE;AAGA,IAAA,MAAM,cAAc,aAAA,EAAc;AAClC,IAAA,IAAI,WAAA,IAAe,OAAO,WAAA,CAAY,OAAA,KAAY,UAAA,EAAY;AAC5D,MAAA,WAAA,CAAY,OAAA,EAAQ;AAAA,IACtB;AACA,IAAA,WAAA,EAAY;AACZ,IAAA,YAAA,EAAa;AACb,IAAA,eAAA,EAAgB;AAAA,EAClB;AAIA,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA,MAAM,aAAA;AAAA,EACR;AACF;AAWA,SAAS,qBAAA,GAA8B;AACrC,EAAA,IAAI,OAAO,YAAY,WAAA,EAAa;AAEpC,EAAA,MAAM,OAAA,GAA4B,CAAC,SAAA,EAAW,QAAQ,CAAA;AACtD,EAAA,IAAI,YAAA,GAAe,KAAA;AAEnB,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,OAAA,CAAQ,EAAA,CAAG,QAAQ,YAAY;AAC7B,MAAA,IAAI,YAAA,EAAc;AAClB,MAAA,YAAA,GAAe,IAAA;AAEf,MAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,MAAA,EAAQ;AACnC,QAAA,SAAA,EAAU,CAAE,IAAA;AAAA,UACV,EAAC;AAAA,UACD,sBAAsB,MAAM,CAAA,uBAAA;AAAA,SAC9B;AAAA,MACF;AAEA,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,EAAS;AAAA,MACjB,SAAS,KAAA,EAAO;AACd,QAAA,SAAA,EAAU,CAAE,KAAA;AAAA,UACV;AAAA,YACE,GAAA,EAAK,KAAA,YAAiB,KAAA,GAAQ,KAAA,GAAQ;AAAA,WACxC;AAAA,UACA;AAAA,SACF;AAAA,MACF,CAAA,SAAE;AACA,QAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,MAChB;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AACF;AAGA,qBAAA,EAAsB","file":"index.js","sourcesContent":["/**\n * Graceful shutdown with flush and cleanup\n */\n\nimport { getSdk, getLogger } from './init';\nimport { getEventQueue, resetEventQueue } from './track';\nimport { resetEvents } from './event';\nimport { resetMetrics } from './metric';\n\n/**\n * Flush all pending telemetry\n *\n * Flushes both events events and OpenTelemetry spans to their destinations.\n * Includes timeout protection to prevent hanging in serverless environments.\n *\n * Safe to call multiple times.\n *\n * @param options - Optional configuration\n * @param options.timeout - Timeout in milliseconds (default: 2000ms)\n * @param options.forShutdown - If true, permanently disables the events queue after flush (used internally by shutdown())\n *\n * @example Manual flush in serverless\n * ```typescript\n * import { flush } from 'autotel';\n *\n * export const handler = async (event) => {\n * // ... process event\n * await flush(); // Flush before function returns\n * return result;\n * };\n * ```\n *\n * @example With custom timeout\n * ```typescript\n * await flush({ timeout: 5000 }); // 5 second timeout\n * ```\n */\nexport async function flush(options?: {\n timeout?: number;\n forShutdown?: boolean;\n}): Promise<void> {\n const timeout = options?.timeout ?? 2000;\n const forShutdown = options?.forShutdown ?? false;\n\n const doFlush = async () => {\n // Flush events queue (or shutdown queue when tearing down)\n const eventsQueue = getEventQueue();\n if (eventsQueue) {\n if (forShutdown) {\n await eventsQueue.shutdown();\n } else {\n await eventsQueue.flush();\n }\n }\n\n // Flush OpenTelemetry spans\n // This ensures spans are exported immediately, critical for serverless\n const sdk = getSdk();\n if (sdk) {\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 sdkAny = sdk as any;\n if (typeof sdkAny.getTracerProvider === 'function') {\n const tracerProvider = sdkAny.getTracerProvider();\n if (\n tracerProvider &&\n typeof tracerProvider.forceFlush === 'function'\n ) {\n await tracerProvider.forceFlush();\n }\n }\n } catch {\n // Ignore errors when accessing tracer provider (may not be available in test mocks)\n }\n }\n };\n\n // Add timeout protection to prevent hanging\n let timeoutHandle: NodeJS.Timeout | undefined;\n try {\n await Promise.race([\n doFlush().finally(() => {\n // Clear timeout as soon as flush completes\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }),\n new Promise<void>((_, reject) => {\n timeoutHandle = setTimeout(\n () => reject(new Error('Flush timeout')),\n timeout,\n );\n // Use unref() to allow Node to exit if flush completes first\n // This prevents the 2s delay in serverless when flush succeeds immediately\n timeoutHandle.unref();\n }),\n ]);\n } catch (error) {\n // Clear timeout on error too\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n const logger = getLogger();\n logger.error(\n {\n err: error instanceof Error ? error : new Error(String(error)),\n },\n '[autotel] Flush error',\n );\n throw error;\n }\n}\n\n/**\n * Shutdown telemetry and cleanup resources\n *\n * - Flushes all pending data\n * - Shuts down OpenTelemetry SDK\n * - Cleans up resources\n *\n * Call this before process exit.\n *\n * Always performs cleanup even if flush fails, preventing resource leaks\n * in serverless handlers or tests.\n *\n * @example Express server\n * ```typescript\n * const server = app.listen(3000)\n *\n * process.on('SIGTERM', async () => {\n * await server.close()\n * await shutdown()\n * process.exit(0)\n * })\n * ```\n */\nexport async function shutdown(): Promise<void> {\n const logger = getLogger();\n let shutdownError: Error | null = null;\n\n // Attempt to flush (with queue shutdown so new events are rejected), but continue with cleanup even if it fails\n try {\n await flush({ forShutdown: true });\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n shutdownError = err;\n logger.error(\n {\n err,\n },\n '[autotel] Flush failed during shutdown, continuing cleanup',\n );\n }\n\n // Always shutdown SDK and clean up resources\n try {\n // Shutdown OpenTelemetry SDK\n const sdk = getSdk();\n if (sdk) {\n await sdk.shutdown();\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n\n // Ignore ECONNREFUSED errors - this happens when no OTLP endpoint was configured\n // The SDK tries to flush exporters that don't exist, which is harmless\n const isConnectionRefused =\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n error.code === 'ECONNREFUSED';\n\n if (!isConnectionRefused) {\n // Only store/log non-connection errors\n if (!shutdownError) {\n shutdownError = err;\n }\n logger.error({ err }, '[autotel] SDK shutdown failed');\n }\n } finally {\n // Clean up singleton Maps and queues to prevent memory leaks\n // This runs even if SDK shutdown fails\n const eventsQueue = getEventQueue();\n if (eventsQueue && typeof eventsQueue.cleanup === 'function') {\n eventsQueue.cleanup();\n }\n resetEvents();\n resetMetrics();\n resetEventQueue();\n }\n\n // Rethrow first error after cleanup completes\n // This allows tests and CI to detect failures while still ensuring cleanup\n if (shutdownError) {\n throw shutdownError;\n }\n}\n\n/**\n * Register automatic shutdown hooks for common signals\n *\n * Handles:\n * - SIGTERM (Docker/K8s graceful shutdown)\n * - SIGINT (Ctrl+C)\n *\n * @internal Called automatically on module load\n */\nfunction registerShutdownHooks(): void {\n if (typeof process === 'undefined') return; // Not in Node.js\n\n const signals: NodeJS.Signals[] = ['SIGTERM', 'SIGINT'];\n let shuttingDown = false;\n\n for (const signal of signals) {\n process.on(signal, async () => {\n if (shuttingDown) return; // Prevent double shutdown\n shuttingDown = true;\n\n if (process.env.NODE_ENV !== 'test') {\n getLogger().info(\n {},\n `[autotel] Received ${signal}, flushing telemetry...`,\n );\n }\n\n try {\n await shutdown();\n } catch (error) {\n getLogger().error(\n {\n err: error instanceof Error ? error : undefined,\n },\n '[autotel] Error during shutdown',\n );\n } finally {\n process.exit(0);\n }\n });\n }\n}\n\n// Auto-register shutdown hooks\nregisterShutdownHooks();\n"]}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkNWT5SYOX_cjs = require('./chunk-NWT5SYOX.cjs');
4
- require('./chunk-DWRTSOGR.cjs');
3
+ var chunkBEVIAKTB_cjs = require('./chunk-BEVIAKTB.cjs');
4
+ require('./chunk-XI5WPVR5.cjs');
5
5
  require('./chunk-W4EUTSB2.cjs');
6
6
  require('./chunk-5PZZHX4Y.cjs');
7
7
  require('./chunk-D5LMF53P.cjs');
@@ -25,15 +25,15 @@ require('./chunk-JEQ2X3Z6.cjs');
25
25
 
26
26
  Object.defineProperty(exports, "clearOrderingState", {
27
27
  enumerable: true,
28
- get: function () { return chunkNWT5SYOX_cjs.clearOrderingState; }
28
+ get: function () { return chunkBEVIAKTB_cjs.clearOrderingState; }
29
29
  });
30
30
  Object.defineProperty(exports, "traceConsumer", {
31
31
  enumerable: true,
32
- get: function () { return chunkNWT5SYOX_cjs.traceConsumer; }
32
+ get: function () { return chunkBEVIAKTB_cjs.traceConsumer; }
33
33
  });
34
34
  Object.defineProperty(exports, "traceProducer", {
35
35
  enumerable: true,
36
- get: function () { return chunkNWT5SYOX_cjs.traceProducer; }
36
+ get: function () { return chunkBEVIAKTB_cjs.traceProducer; }
37
37
  });
38
38
  //# sourceMappingURL=messaging.cjs.map
39
39
  //# sourceMappingURL=messaging.cjs.map
package/dist/messaging.js CHANGED
@@ -1,5 +1,5 @@
1
- export { clearOrderingState, traceConsumer, traceProducer } from './chunk-FMPBL2NF.js';
2
- import './chunk-QP5LVD4L.js';
1
+ export { clearOrderingState, traceConsumer, traceProducer } from './chunk-XBVB3AFF.js';
2
+ import './chunk-G47ZCJGW.js';
3
3
  import './chunk-SR35DG5A.js';
4
4
  import './chunk-HJPXNUZR.js';
5
5
  import './chunk-WD4RP6IV.js';
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var chunk2ZKEORFN_cjs = require('./chunk-2ZKEORFN.cjs');
4
+ var chunkESMHTKLJ_cjs = require('./chunk-ESMHTKLJ.cjs');
5
+ require('./chunk-JEQ2X3Z6.cjs');
6
+
7
+
8
+
9
+ Object.defineProperty(exports, "httpRequestHeaderAttribute", {
10
+ enumerable: true,
11
+ get: function () { return chunk2ZKEORFN_cjs.httpRequestHeaderAttribute; }
12
+ });
13
+ Object.defineProperty(exports, "httpResponseHeaderAttribute", {
14
+ enumerable: true,
15
+ get: function () { return chunk2ZKEORFN_cjs.httpResponseHeaderAttribute; }
16
+ });
17
+ Object.defineProperty(exports, "HTTPAttributes", {
18
+ enumerable: true,
19
+ get: function () { return chunkESMHTKLJ_cjs.HTTPAttributes; }
20
+ });
21
+ Object.defineProperty(exports, "ServiceAttributes", {
22
+ enumerable: true,
23
+ get: function () { return chunkESMHTKLJ_cjs.ServiceAttributes; }
24
+ });
25
+ Object.defineProperty(exports, "URLAttributes", {
26
+ enumerable: true,
27
+ get: function () { return chunkESMHTKLJ_cjs.URLAttributes; }
28
+ });
29
+ //# sourceMappingURL=semantic-conventions.cjs.map
30
+ //# sourceMappingURL=semantic-conventions.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"semantic-conventions.cjs"}
@@ -0,0 +1,29 @@
1
+ declare const HTTPAttributes: {
2
+ readonly connectionState: "http.connection.state";
3
+ readonly requestMethod: "http.request.method";
4
+ readonly requestMethodOriginal: "http.request.method_original";
5
+ readonly requestResendCount: "http.request.resend_count";
6
+ readonly requestSize: "http.request.size";
7
+ readonly requestBodySize: "http.request.body.size";
8
+ readonly responseSize: "http.response.size";
9
+ readonly responseBodySize: "http.response.body.size";
10
+ readonly responseStatusCode: "http.response.status_code";
11
+ readonly route: "http.route";
12
+ };
13
+ declare const ServiceAttributes: {
14
+ readonly name: "service.name";
15
+ readonly instance: "service.instance.id";
16
+ readonly version: "service.version";
17
+ };
18
+ declare const URLAttributes: {
19
+ readonly scheme: "url.scheme";
20
+ readonly full: "url.full";
21
+ readonly path: "url.path";
22
+ readonly query: "url.query";
23
+ readonly fragment: "url.fragment";
24
+ };
25
+
26
+ declare function httpRequestHeaderAttribute(name: string): string;
27
+ declare function httpResponseHeaderAttribute(name: string): string;
28
+
29
+ export { HTTPAttributes, ServiceAttributes, URLAttributes, httpRequestHeaderAttribute, httpResponseHeaderAttribute };
@@ -0,0 +1,29 @@
1
+ declare const HTTPAttributes: {
2
+ readonly connectionState: "http.connection.state";
3
+ readonly requestMethod: "http.request.method";
4
+ readonly requestMethodOriginal: "http.request.method_original";
5
+ readonly requestResendCount: "http.request.resend_count";
6
+ readonly requestSize: "http.request.size";
7
+ readonly requestBodySize: "http.request.body.size";
8
+ readonly responseSize: "http.response.size";
9
+ readonly responseBodySize: "http.response.body.size";
10
+ readonly responseStatusCode: "http.response.status_code";
11
+ readonly route: "http.route";
12
+ };
13
+ declare const ServiceAttributes: {
14
+ readonly name: "service.name";
15
+ readonly instance: "service.instance.id";
16
+ readonly version: "service.version";
17
+ };
18
+ declare const URLAttributes: {
19
+ readonly scheme: "url.scheme";
20
+ readonly full: "url.full";
21
+ readonly path: "url.path";
22
+ readonly query: "url.query";
23
+ readonly fragment: "url.fragment";
24
+ };
25
+
26
+ declare function httpRequestHeaderAttribute(name: string): string;
27
+ declare function httpResponseHeaderAttribute(name: string): string;
28
+
29
+ export { HTTPAttributes, ServiceAttributes, URLAttributes, httpRequestHeaderAttribute, httpResponseHeaderAttribute };
@@ -0,0 +1,5 @@
1
+ export { httpRequestHeaderAttribute, httpResponseHeaderAttribute } from './chunk-7552UTQW.js';
2
+ export { HTTPAttributes, ServiceAttributes, URLAttributes } from './chunk-4A53YIAX.js';
3
+ import './chunk-DGUM43GV.js';
4
+ //# sourceMappingURL=semantic-conventions.js.map
5
+ //# sourceMappingURL=semantic-conventions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"semantic-conventions.js"}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk74L5DOB4_cjs = require('./chunk-74L5DOB4.cjs');
4
- require('./chunk-DWRTSOGR.cjs');
3
+ var chunkXNBTEFRZ_cjs = require('./chunk-XNBTEFRZ.cjs');
4
+ require('./chunk-XI5WPVR5.cjs');
5
5
  require('./chunk-W4EUTSB2.cjs');
6
6
  require('./chunk-5PZZHX4Y.cjs');
7
7
  require('./chunk-D5LMF53P.cjs');
@@ -25,19 +25,19 @@ require('./chunk-JEQ2X3Z6.cjs');
25
25
 
26
26
  Object.defineProperty(exports, "traceDB", {
27
27
  enumerable: true,
28
- get: function () { return chunk74L5DOB4_cjs.traceDB; }
28
+ get: function () { return chunkXNBTEFRZ_cjs.traceDB; }
29
29
  });
30
30
  Object.defineProperty(exports, "traceHTTP", {
31
31
  enumerable: true,
32
- get: function () { return chunk74L5DOB4_cjs.traceHTTP; }
32
+ get: function () { return chunkXNBTEFRZ_cjs.traceHTTP; }
33
33
  });
34
34
  Object.defineProperty(exports, "traceLLM", {
35
35
  enumerable: true,
36
- get: function () { return chunk74L5DOB4_cjs.traceLLM; }
36
+ get: function () { return chunkXNBTEFRZ_cjs.traceLLM; }
37
37
  });
38
38
  Object.defineProperty(exports, "traceMessaging", {
39
39
  enumerable: true,
40
- get: function () { return chunk74L5DOB4_cjs.traceMessaging; }
40
+ get: function () { return chunkXNBTEFRZ_cjs.traceMessaging; }
41
41
  });
42
42
  //# sourceMappingURL=semantic-helpers.cjs.map
43
43
  //# sourceMappingURL=semantic-helpers.cjs.map
@@ -1,5 +1,5 @@
1
- export { traceDB, traceHTTP, traceLLM, traceMessaging } from './chunk-QKVQWGTF.js';
2
- import './chunk-QP5LVD4L.js';
1
+ export { traceDB, traceHTTP, traceLLM, traceMessaging } from './chunk-5JLXDCL2.js';
2
+ import './chunk-G47ZCJGW.js';
3
3
  import './chunk-SR35DG5A.js';
4
4
  import './chunk-HJPXNUZR.js';
5
5
  import './chunk-WD4RP6IV.js';
package/dist/webhook.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkDWRTSOGR_cjs = require('./chunk-DWRTSOGR.cjs');
3
+ var chunkXI5WPVR5_cjs = require('./chunk-XI5WPVR5.cjs');
4
4
  require('./chunk-W4EUTSB2.cjs');
5
5
  require('./chunk-5PZZHX4Y.cjs');
6
6
  require('./chunk-D5LMF53P.cjs');
@@ -148,7 +148,7 @@ function createParkingLot(config) {
148
148
  },
149
149
  traceCallback(callbackConfig) {
150
150
  return (fnFactory) => {
151
- return chunkDWRTSOGR_cjs.trace(
151
+ return chunkXI5WPVR5_cjs.trace(
152
152
  {
153
153
  name: callbackConfig.name,
154
154
  spanKind: api.SpanKind.SERVER
package/dist/webhook.js CHANGED
@@ -1,4 +1,4 @@
1
- import { trace } from './chunk-QP5LVD4L.js';
1
+ import { trace } from './chunk-G47ZCJGW.js';
2
2
  import './chunk-SR35DG5A.js';
3
3
  import './chunk-HJPXNUZR.js';
4
4
  import './chunk-WD4RP6IV.js';
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkINJD3G4K_cjs = require('./chunk-INJD3G4K.cjs');
4
- var chunkDWRTSOGR_cjs = require('./chunk-DWRTSOGR.cjs');
4
+ var chunkXI5WPVR5_cjs = require('./chunk-XI5WPVR5.cjs');
5
5
  require('./chunk-W4EUTSB2.cjs');
6
6
  require('./chunk-5PZZHX4Y.cjs');
7
7
  require('./chunk-D5LMF53P.cjs');
@@ -59,7 +59,7 @@ var WorkflowBaggage = chunkINJD3G4K_cjs.createSafeBaggageSchema(workflowBaggageF
59
59
  function traceDistributedWorkflow(config) {
60
60
  const spanName = `workflow.${config.name}`;
61
61
  return (fnFactory) => {
62
- return chunkDWRTSOGR_cjs.trace(
62
+ return chunkXI5WPVR5_cjs.trace(
63
63
  { name: spanName, spanKind: api.SpanKind.INTERNAL },
64
64
  (baseCtx) => {
65
65
  return async (...args) => {
@@ -158,7 +158,7 @@ function traceDistributedWorkflow(config) {
158
158
  function traceDistributedStep(config) {
159
159
  const spanName = `workflow.step.${config.name}`;
160
160
  return (fnFactory) => {
161
- return chunkDWRTSOGR_cjs.trace(
161
+ return chunkXI5WPVR5_cjs.trace(
162
162
  { name: spanName, spanKind: api.SpanKind.INTERNAL },
163
163
  (baseCtx) => {
164
164
  return async (...args) => {
@@ -1,5 +1,5 @@
1
1
  import { createSafeBaggageSchema } from './chunk-4IFSYQVX.js';
2
- import { trace } from './chunk-QP5LVD4L.js';
2
+ import { trace } from './chunk-G47ZCJGW.js';
3
3
  import './chunk-SR35DG5A.js';
4
4
  import './chunk-HJPXNUZR.js';
5
5
  import './chunk-WD4RP6IV.js';
package/dist/workflow.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkHZ23L5KR_cjs = require('./chunk-HZ23L5KR.cjs');
4
- require('./chunk-DWRTSOGR.cjs');
3
+ var chunkLGT7XA5O_cjs = require('./chunk-LGT7XA5O.cjs');
4
+ require('./chunk-XI5WPVR5.cjs');
5
5
  require('./chunk-W4EUTSB2.cjs');
6
6
  require('./chunk-5PZZHX4Y.cjs');
7
7
  require('./chunk-D5LMF53P.cjs');
@@ -25,19 +25,19 @@ require('./chunk-JEQ2X3Z6.cjs');
25
25
 
26
26
  Object.defineProperty(exports, "getCurrentWorkflowContext", {
27
27
  enumerable: true,
28
- get: function () { return chunkHZ23L5KR_cjs.getCurrentWorkflowContext; }
28
+ get: function () { return chunkLGT7XA5O_cjs.getCurrentWorkflowContext; }
29
29
  });
30
30
  Object.defineProperty(exports, "isInWorkflow", {
31
31
  enumerable: true,
32
- get: function () { return chunkHZ23L5KR_cjs.isInWorkflow; }
32
+ get: function () { return chunkLGT7XA5O_cjs.isInWorkflow; }
33
33
  });
34
34
  Object.defineProperty(exports, "traceStep", {
35
35
  enumerable: true,
36
- get: function () { return chunkHZ23L5KR_cjs.traceStep; }
36
+ get: function () { return chunkLGT7XA5O_cjs.traceStep; }
37
37
  });
38
38
  Object.defineProperty(exports, "traceWorkflow", {
39
39
  enumerable: true,
40
- get: function () { return chunkHZ23L5KR_cjs.traceWorkflow; }
40
+ get: function () { return chunkLGT7XA5O_cjs.traceWorkflow; }
41
41
  });
42
42
  //# sourceMappingURL=workflow.cjs.map
43
43
  //# sourceMappingURL=workflow.cjs.map
package/dist/workflow.js CHANGED
@@ -1,5 +1,5 @@
1
- export { getCurrentWorkflowContext, isInWorkflow, traceStep, traceWorkflow } from './chunk-WC2AMGBX.js';
2
- import './chunk-QP5LVD4L.js';
1
+ export { getCurrentWorkflowContext, isInWorkflow, traceStep, traceWorkflow } from './chunk-LCMARHLX.js';
2
+ import './chunk-G47ZCJGW.js';
3
3
  import './chunk-SR35DG5A.js';
4
4
  import './chunk-HJPXNUZR.js';
5
5
  import './chunk-WD4RP6IV.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autotel",
3
- "version": "2.18.0",
3
+ "version": "2.19.0",
4
4
  "description": "Write Once, Observe Anywhere",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -188,6 +188,11 @@
188
188
  "import": "./dist/workflow-distributed.js",
189
189
  "require": "./dist/workflow-distributed.cjs"
190
190
  },
191
+ "./semantic-conventions": {
192
+ "types": "./dist/semantic-conventions.d.ts",
193
+ "import": "./dist/semantic-conventions.js",
194
+ "require": "./dist/semantic-conventions.cjs"
195
+ },
191
196
  "./correlation-id": {
192
197
  "types": "./dist/correlation-id.d.ts",
193
198
  "import": "./dist/correlation-id.js",
@@ -229,7 +234,7 @@
229
234
  "@opentelemetry/sdk-node": "^0.211.0",
230
235
  "@opentelemetry/sdk-trace-base": "^2.5.0",
231
236
  "@opentelemetry/semantic-conventions": "^1.39.0",
232
- "import-in-the-middle": "^2.0.6"
237
+ "import-in-the-middle": "^3.0.0"
233
238
  },
234
239
  "peerDependencies": {
235
240
  "@opentelemetry/auto-instrumentations-node": "^0.69.0",
@@ -242,8 +247,8 @@
242
247
  "@opentelemetry/resource-detector-gcp": "^0.46.0",
243
248
  "@opentelemetry/sdk-logs": "^0.211.0",
244
249
  "@opentelemetry/sdk-trace-node": "^2.5.0",
245
- "@traceloop/node-server-sdk": "^0.22.6",
246
- "pino": "^10.3.0",
250
+ "@traceloop/node-server-sdk": "^0.22.7",
251
+ "pino": "^10.3.1",
247
252
  "pino-pretty": "^13.1.3",
248
253
  "yaml": "^2.8.2"
249
254
  },
@@ -308,19 +313,19 @@
308
313
  "@total-typescript/ts-reset": "^0.6.1",
309
314
  "@total-typescript/tsconfig": "^1.0.4",
310
315
  "@types/eslint-config-prettier": "^6.11.3",
311
- "@types/node": "^25.1.0",
312
- "@typescript-eslint/eslint-plugin": "^8.54.0",
313
- "@typescript-eslint/parser": "^8.54.0",
316
+ "@types/node": "^25.2.3",
317
+ "@typescript-eslint/eslint-plugin": "^8.55.0",
318
+ "@typescript-eslint/parser": "^8.55.0",
314
319
  "eslint-config-prettier": "^10.1.8",
315
- "eslint-plugin-unicorn": "^62.0.0",
316
- "pino": "^10.3.0",
320
+ "eslint-plugin-unicorn": "^63.0.0",
321
+ "pino": "^10.3.1",
317
322
  "prettier": "^3.8.1",
318
323
  "rimraf": "^6.1.2",
319
324
  "tsup": "^8.5.1",
320
325
  "tsx": "^4.21.0",
321
326
  "typescript": "^5.9.3",
322
- "typescript-eslint": "^8.54.0",
323
- "vite-tsconfig-paths": "^6.0.5",
327
+ "typescript-eslint": "^8.55.0",
328
+ "vite-tsconfig-paths": "^6.1.0",
324
329
  "vitest": "^4.0.18",
325
330
  "vitest-mock-extended": "^3.1.0",
326
331
  "winston": "^3.19.0",
@@ -1,47 +1,33 @@
1
- import { describe, it, expect, beforeEach } from 'vitest';
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
2
  import { Trace } from './decorators';
3
- import { init } from './init';
4
3
  import { configure, resetConfig } from './config';
5
- import { InMemorySpanExporter } from './exporters';
6
- import { SimpleSpanProcessor } from './processors';
7
- import { trace as otelTrace } from '@opentelemetry/api';
8
- import { flush } from './shutdown';
9
-
10
- // Skipped: TypeScript 5+ decorators have limitations in vitest/esbuild/tsx test environments.
11
- // The decorators work correctly when compiled with tsc (verified in production), but
12
- // the test infrastructure doesn't properly export spans to InMemorySpanExporter.
13
- // Attempts to fix this have been unsuccessful - spans are not exported even with
14
- // proper tracer configuration, flushing, and SDK initialization delays.
15
- // Root cause: Decorator metadata/metadata reflection may not work correctly in the
16
- // test environment's transpilation pipeline, preventing spans from being created/exported.
17
- describe.skip('Decorators', () => {
4
+ import { trace as otelTrace, SpanStatusCode } from '@opentelemetry/api';
5
+ import {
6
+ BasicTracerProvider,
7
+ InMemorySpanExporter,
8
+ SimpleSpanProcessor,
9
+ } from '@opentelemetry/sdk-trace-base';
10
+
11
+ describe('Decorators', () => {
18
12
  let exporter: InMemorySpanExporter;
13
+ let provider: BasicTracerProvider;
19
14
 
20
- beforeEach(async () => {
21
- // Reset config to ensure clean state
15
+ beforeEach(() => {
22
16
  resetConfig();
23
17
 
24
- // Clear any existing spans
25
18
  exporter = new InMemorySpanExporter();
26
-
27
- // Initialize with in-memory exporter for testing
28
- init({
29
- service: 'test-decorators',
19
+ provider = new BasicTracerProvider({
30
20
  spanProcessors: [new SimpleSpanProcessor(exporter)],
31
- metrics: false,
32
21
  });
33
22
 
34
- // Wait a tick to ensure SDK is fully initialized
35
- await new Promise((resolve) => setTimeout(resolve, 10));
23
+ otelTrace.setGlobalTracerProvider(provider);
24
+ const tracer = provider.getTracer('test-decorators');
25
+ configure({ tracer });
26
+ });
36
27
 
37
- // Configure the tracer that decorators will use - get it from the global tracer provider
38
- // This ensures decorators use the same tracer that's connected to our exporter
39
- // After init(), the SDK registers itself as the global tracer provider
40
- const tracerProvider = otelTrace.getTracerProvider();
41
- const tracer = tracerProvider.getTracer('test-decorators', '1.0.0');
42
- configure({
43
- tracer,
44
- });
28
+ afterEach(() => {
29
+ exporter.reset();
30
+ otelTrace.setGlobalTracerProvider(undefined as any);
45
31
  });
46
32
 
47
33
  describe('@Trace method decorator', () => {
@@ -58,9 +44,6 @@ describe.skip('Decorators', () => {
58
44
 
59
45
  expect(result).toEqual({ data: 'test' });
60
46
 
61
- // Flush spans to ensure they're exported
62
- await flush();
63
-
64
47
  const spans = exporter.getFinishedSpans();
65
48
  expect(spans).toHaveLength(1);
66
49
  expect(spans[0]?.name).toBe('getData');
@@ -77,8 +60,6 @@ describe.skip('Decorators', () => {
77
60
  const service = new TestService();
78
61
  await service.processData();
79
62
 
80
- await flush();
81
-
82
63
  const spans = exporter.getFinishedSpans();
83
64
  expect(spans[0]?.name).toBe('custom.operation');
84
65
  });
@@ -94,8 +75,6 @@ describe.skip('Decorators', () => {
94
75
  const service = new TestService();
95
76
  await service.execute();
96
77
 
97
- await flush();
98
-
99
78
  const spans = exporter.getFinishedSpans();
100
79
  expect(spans[0]?.name).toBe('test.method');
101
80
  });
@@ -109,7 +88,6 @@ describe.skip('Decorators', () => {
109
88
  // @ts-expect-error - Decorator type resolution issue in test environment, works in production
110
89
  @Trace()
111
90
  async createUser(data: { id: string }) {
112
- // Access ctx via this.ctx
113
91
  const ctx = (this as unknown as WithTraceContext).ctx;
114
92
  if (ctx) {
115
93
  ctx.setAttribute('user.id', data.id);
@@ -121,8 +99,6 @@ describe.skip('Decorators', () => {
121
99
  const service = new TestService();
122
100
  await service.createUser({ id: '123' });
123
101
 
124
- await flush();
125
-
126
102
  const spans = exporter.getFinishedSpans();
127
103
  expect(spans[0]?.attributes['user.id']).toBe('123');
128
104
  });
@@ -131,7 +107,6 @@ describe.skip('Decorators', () => {
131
107
  class TestService {
132
108
  @Trace()
133
109
  async simpleMethod() {
134
- // No ctx access
135
110
  return 'result';
136
111
  }
137
112
  }
@@ -140,9 +115,6 @@ describe.skip('Decorators', () => {
140
115
  const result = await service.simpleMethod();
141
116
 
142
117
  expect(result).toBe('result');
143
-
144
- await flush();
145
-
146
118
  expect(exporter.getFinishedSpans()).toHaveLength(1);
147
119
  });
148
120
 
@@ -171,33 +143,11 @@ describe.skip('Decorators', () => {
171
143
 
172
144
  const service = new TestService();
173
145
 
174
- try {
175
- await service.failingMethod();
176
- expect.fail('Should have thrown an error');
177
- } catch (error) {
178
- expect(error).toBeInstanceOf(Error);
179
- expect((error as Error).message).toBe('Test error');
180
- }
181
-
182
- // Wait a bit for span to be processed
183
- await new Promise((resolve) => setTimeout(resolve, 100));
184
- await flush();
146
+ await expect(service.failingMethod()).rejects.toThrow('Test error');
185
147
 
186
148
  const spans = exporter.getFinishedSpans();
187
- // For error cases, the span should still be created and exported
188
- // If no spans are exported, the decorator might not be handling errors correctly
189
- if (spans.length === 0) {
190
- // This is a known limitation - decorators may not export spans for error cases in test environment
191
- // The decorators work correctly in production (compiled with tsc)
192
- expect(spans.length).toBeGreaterThanOrEqual(0); // Allow this test to pass for now
193
- } else {
194
- expect(spans).toHaveLength(1);
195
- // Check status - OpenTelemetry status has code property
196
- const status = spans[0]?.status;
197
- expect(status).toBeDefined();
198
- // Status code 2 = ERROR in OpenTelemetry
199
- expect((status as { code: number }).code).toBe(2);
200
- }
149
+ expect(spans).toHaveLength(1);
150
+ expect(spans[0]?.status.code).toBe(SpanStatusCode.ERROR);
201
151
  });
202
152
  });
203
153
  });
@@ -1025,12 +1025,7 @@ describe('Functional API', () => {
1025
1025
  expect(collector.getSpans()).toHaveLength(1);
1026
1026
  });
1027
1027
 
1028
- // TODO: Fix baggage propagation to nested trace() calls
1029
- // The inner trace creates a new span that doesn't properly inherit baggage
1030
- // from withBaggage() due to context storage synchronization issues.
1031
- // This was a false-positive before - the inner function wasn't being called
1032
- // because childCtx wasn't detected as a factory parameter.
1033
- it.skip('withBaggage should set baggage for child spans', async () => {
1028
+ it('withBaggage should set baggage for child spans', async () => {
1034
1029
  const collector = createTraceCollector();
1035
1030
 
1036
1031
  await trace((ctx) => async () => {
@@ -1107,6 +1102,29 @@ describe('Functional API', () => {
1107
1102
  expect(collector.getSpans()).toHaveLength(1);
1108
1103
  });
1109
1104
 
1105
+ it('withBaggage should not leak baggage after callback completes', async () => {
1106
+ const collector = createTraceCollector();
1107
+
1108
+ await trace((ctx) => async () => {
1109
+ expect(ctx.getBaggage('tenant.id')).toBeUndefined();
1110
+
1111
+ await withBaggage({
1112
+ baggage: { 'tenant.id': 'tenant-456' },
1113
+ fn: async () => {
1114
+ expect(ctx.getBaggage('tenant.id')).toBe('tenant-456');
1115
+ },
1116
+ });
1117
+
1118
+ // Child spans created after withBaggage must not inherit scoped baggage.
1119
+ // (Same-ctx after await may still see baggage due to async context propagation.)
1120
+ await trace((childCtx) => async () => {
1121
+ expect(childCtx.getBaggage('tenant.id')).toBeUndefined();
1122
+ })();
1123
+ })();
1124
+
1125
+ expect(collector.getSpans()).toHaveLength(2);
1126
+ });
1127
+
1110
1128
  it('ctx.getAllBaggage should return all baggage entries', async () => {
1111
1129
  const collector = createTraceCollector();
1112
1130
  const { context, propagation } = await import('@opentelemetry/api');