autotel-adapters 0.2.20 → 0.3.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 (78) hide show
  1. package/dist/chunk-2YPL66HM.js +79 -0
  2. package/dist/chunk-2YPL66HM.js.map +1 -0
  3. package/dist/chunk-6TOW47TB.js +70 -0
  4. package/dist/chunk-6TOW47TB.js.map +1 -0
  5. package/dist/{chunk-GBSB7IX7.js → chunk-DJ2OU3S6.js} +26 -4
  6. package/dist/chunk-DJ2OU3S6.js.map +1 -0
  7. package/dist/{chunk-AD3QBS5J.js → chunk-FAHH33UI.js} +13 -4
  8. package/dist/chunk-FAHH33UI.js.map +1 -0
  9. package/dist/{chunk-GPWONOFN.js → chunk-HTZFHBTN.js} +13 -4
  10. package/dist/chunk-HTZFHBTN.js.map +1 -0
  11. package/dist/{chunk-UUDK5U3L.js → chunk-JH5ZTTLF.js} +3 -3
  12. package/dist/{chunk-UUDK5U3L.js.map → chunk-JH5ZTTLF.js.map} +1 -1
  13. package/dist/{chunk-JC3TNPQD.js → chunk-U3U4WH42.js} +3 -3
  14. package/dist/{chunk-JC3TNPQD.js.map → chunk-U3U4WH42.js.map} +1 -1
  15. package/dist/{chunk-CITNYQ2G.js → chunk-VJZDW2DS.js} +6 -3
  16. package/dist/chunk-VJZDW2DS.js.map +1 -0
  17. package/dist/cloudflare.cjs +3 -0
  18. package/dist/cloudflare.cjs.map +1 -1
  19. package/dist/cloudflare.d.cts +3 -0
  20. package/dist/cloudflare.d.ts +3 -0
  21. package/dist/cloudflare.js +2 -2
  22. package/dist/core.cjs +23 -0
  23. package/dist/core.cjs.map +1 -1
  24. package/dist/core.d.cts +16 -1
  25. package/dist/core.d.ts +16 -1
  26. package/dist/core.js +1 -1
  27. package/dist/express.cjs +146 -0
  28. package/dist/express.cjs.map +1 -0
  29. package/dist/express.d.cts +43 -0
  30. package/dist/express.d.ts +43 -0
  31. package/dist/express.js +4 -0
  32. package/dist/express.js.map +1 -0
  33. package/dist/fastify.cjs +137 -0
  34. package/dist/fastify.cjs.map +1 -0
  35. package/dist/fastify.d.cts +43 -0
  36. package/dist/fastify.d.ts +43 -0
  37. package/dist/fastify.js +4 -0
  38. package/dist/fastify.js.map +1 -0
  39. package/dist/hono.cjs.map +1 -1
  40. package/dist/hono.d.cts +1 -0
  41. package/dist/hono.d.ts +1 -0
  42. package/dist/hono.js +2 -2
  43. package/dist/index.cjs +174 -3
  44. package/dist/index.cjs.map +1 -1
  45. package/dist/index.d.cts +4 -1
  46. package/dist/index.d.ts +4 -1
  47. package/dist/index.js +8 -6
  48. package/dist/next.cjs +10 -1
  49. package/dist/next.cjs.map +1 -1
  50. package/dist/next.d.cts +3 -0
  51. package/dist/next.d.ts +3 -0
  52. package/dist/next.js +2 -2
  53. package/dist/nitro.cjs +10 -1
  54. package/dist/nitro.cjs.map +1 -1
  55. package/dist/nitro.d.cts +3 -0
  56. package/dist/nitro.d.ts +3 -0
  57. package/dist/nitro.js +2 -2
  58. package/dist/tanstack.cjs.map +1 -1
  59. package/dist/tanstack.d.cts +1 -0
  60. package/dist/tanstack.d.ts +1 -0
  61. package/dist/tanstack.js +2 -2
  62. package/package.json +12 -2
  63. package/src/cloudflare.test.ts +26 -1
  64. package/src/cloudflare.ts +5 -0
  65. package/src/core.ts +44 -0
  66. package/src/express.test.ts +85 -0
  67. package/src/express.ts +169 -0
  68. package/src/fastify.test.ts +79 -0
  69. package/src/fastify.ts +151 -0
  70. package/src/index.ts +8 -0
  71. package/src/next.test.ts +26 -1
  72. package/src/next.ts +11 -1
  73. package/src/nitro.test.ts +26 -1
  74. package/src/nitro.ts +11 -1
  75. package/dist/chunk-AD3QBS5J.js.map +0 -1
  76. package/dist/chunk-CITNYQ2G.js.map +0 -1
  77. package/dist/chunk-GBSB7IX7.js.map +0 -1
  78. package/dist/chunk-GPWONOFN.js.map +0 -1
@@ -0,0 +1,43 @@
1
+ import { AdapterToolkit } from './core.js';
2
+ import { RequestLoggerOptions, RequestLogger, ParsedError, StructuredErrorInput, StructuredError, DrainPipelineOptions, PipelineDrainFn } from 'autotel';
3
+ export { createDrainPipeline, createStructuredError, parseError } from 'autotel';
4
+ import 'node:async_hooks';
5
+
6
+ interface FastifyRequestLike {
7
+ method?: string;
8
+ url?: string;
9
+ routeOptions?: {
10
+ url?: string;
11
+ };
12
+ routerPath?: string;
13
+ id?: string;
14
+ headers?: Record<string, string | string[] | undefined>;
15
+ }
16
+ interface FastifyReplyLike {
17
+ statusCode?: number;
18
+ }
19
+ interface FastifyWithAutotelOptions {
20
+ spanName?: string | ((request: FastifyRequestLike) => string);
21
+ requestLoggerOptions?: RequestLoggerOptions;
22
+ enrich?: (request: FastifyRequestLike) => Record<string, unknown> | undefined;
23
+ /** Emit one wide event automatically when the handler settles. Default `true`. */
24
+ autoEmit?: boolean;
25
+ }
26
+ declare function useLogger(request?: FastifyRequestLike, requestLoggerOptions?: RequestLoggerOptions): RequestLogger;
27
+ /**
28
+ * Wrap a Fastify route handler. Each request opens a span, gets a
29
+ * request-scoped logger (via `useLogger(request)`), and emits one wide event
30
+ * when the handler settles. Thrown errors are recorded, then rethrown for
31
+ * Fastify's error handling.
32
+ */
33
+ declare function withAutotel<TReq extends FastifyRequestLike, TRes extends FastifyReplyLike, TReturn>(handler: (request: TReq, reply: TRes) => TReturn | Promise<TReturn>, options?: FastifyWithAutotelOptions): (request: TReq, reply: TRes) => Promise<TReturn>;
34
+ declare function createFastifyAdapter(options?: FastifyWithAutotelOptions): {
35
+ withAutotel: <TReq extends FastifyRequestLike, TRes extends FastifyReplyLike, TReturn>(handler: (request: TReq, reply: TRes) => TReturn | Promise<TReturn>) => (request: TReq, reply: TRes) => Promise<TReturn>;
36
+ useLogger: typeof useLogger;
37
+ parseError: (error: unknown) => ParsedError;
38
+ createStructuredError: (input: StructuredErrorInput) => StructuredError;
39
+ createDrainPipeline: <T = unknown>(drainOptions?: DrainPipelineOptions<T>) => ((batchDrain: (batch: T[]) => void | Promise<void>) => PipelineDrainFn<T>);
40
+ };
41
+ declare const fastifyToolkit: AdapterToolkit<FastifyRequestLike>;
42
+
43
+ export { type FastifyReplyLike, type FastifyRequestLike, type FastifyWithAutotelOptions, createFastifyAdapter, fastifyToolkit, useLogger, withAutotel };
@@ -0,0 +1,4 @@
1
+ export { createDrainPipeline, createFastifyAdapter, createStructuredError, fastifyToolkit, parseError, useLogger, withAutotel } from './chunk-6TOW47TB.js';
2
+ import './chunk-DJ2OU3S6.js';
3
+ //# sourceMappingURL=fastify.js.map
4
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"fastify.js"}
package/dist/hono.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core.ts","../src/hono.ts"],"names":["useLogger","getRequestLogger","parseError","createStructuredError","createDrainPipeline"],"mappings":";;;;;AAgCO,SAAS,gBACd,OAAA,EACA;AACA,EAAA,OAAO,SAASA,UAAAA,CACd,OAAA,EACA,oBAAA,EACe;AACf,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAASC,wBAAA,CAAiB,QAAW,oBAAoB,CAAA;AAAA,IAC3D,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,kBAAA,EAAqB,QAAQ,WAAW,CAAA,2GAAA;AAAA,OAE1C;AAAA,IACF;AAEA,IAAA,IAAI,OAAA,IAAW,QAAQ,MAAA,EAAQ;AAC7B,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA;AACpC,MAAA,IAAI,SAAS,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,CAAE,SAAS,CAAA,EAAG;AAC1C,QAAA,MAAA,CAAO,IAAI,KAAK,CAAA;AAAA,MAClB;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;AAEO,SAAS,qBACd,OAAA,EAC0B;AAC1B,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,gBAAgB,OAAO,CAAA;AAAA,gBAClCC,kBAAA;AAAA,2BACAC,6BAAA;AAAA,yBACAC;AAAA,GACF;AACF;;;AClEO,IAAM,YAAY,eAAA,CAAyB;AAAA,EAChD,WAAA,EAAa,MAAA;AAAA,EACb,MAAA,EAAQ,CAAC,CAAA,MAAO;AAAA,IACd,qBAAA,EAAuB,EAAE,GAAA,CAAI,MAAA;AAAA,IAC7B,UAAA,EAAY,EAAE,GAAA,CAAI,GAAA;AAAA,IAClB,YAAA,EAAc,EAAE,GAAA,CAAI;AAAA,GACtB;AACF,CAAC;AAEM,IAAM,cAAc,oBAAA,CAA8B;AAAA,EACvD,WAAA,EAAa,MAAA;AAAA,EACb,MAAA,EAAQ,CAAC,CAAA,MAAO;AAAA,IACd,qBAAA,EAAuB,EAAE,GAAA,CAAI,MAAA;AAAA,IAC7B,UAAA,EAAY,EAAE,GAAA,CAAI,GAAA;AAAA,IAClB,YAAA,EAAc,EAAE,GAAA,CAAI;AAAA,GACtB;AACF,CAAC","file":"hono.cjs","sourcesContent":["import {\n createDrainPipeline,\n createStructuredError,\n getRequestLogger,\n parseError,\n type ParsedError,\n type RequestLogger,\n type RequestLoggerOptions,\n type RequestLogSnapshot,\n type DrainPipelineOptions,\n type PipelineDrainFn,\n type StructuredError,\n type StructuredErrorInput,\n} from 'autotel';\n\nexport interface AdapterUseLoggerOptions<TContext> {\n adapterName: string;\n enrich?: (context: TContext) => Record<string, unknown> | undefined;\n}\n\nexport interface AdapterToolkit<TContext> {\n useLogger: (\n context?: TContext,\n options?: RequestLoggerOptions,\n ) => RequestLogger;\n parseError: (error: unknown) => ParsedError;\n createStructuredError: (input: StructuredErrorInput) => StructuredError;\n createDrainPipeline: <T = unknown>(\n options?: DrainPipelineOptions<T>,\n ) => (drain: (batch: T[]) => void | Promise<void>) => PipelineDrainFn<T>;\n}\n\nexport function createUseLogger<TContext = unknown>(\n options: AdapterUseLoggerOptions<TContext>,\n) {\n return function useLogger(\n context?: TContext,\n requestLoggerOptions?: RequestLoggerOptions,\n ): RequestLogger {\n let logger: RequestLogger;\n try {\n logger = getRequestLogger(undefined, requestLoggerOptions);\n } catch {\n throw new Error(\n `[autotel-adapters/${options.adapterName}] No active trace context. ` +\n `Wrap your handler with autotel trace instrumentation before calling useLogger().`,\n );\n }\n\n if (context && options.enrich) {\n const extra = options.enrich(context);\n if (extra && Object.keys(extra).length > 0) {\n logger.set(extra);\n }\n }\n\n return logger;\n };\n}\n\nexport function createAdapterToolkit<TContext = unknown>(\n options: AdapterUseLoggerOptions<TContext>,\n): AdapterToolkit<TContext> {\n return {\n useLogger: createUseLogger(options),\n parseError,\n createStructuredError,\n createDrainPipeline,\n };\n}\n\n/**\n * Description of a single adapter config field. `env` is the ordered list of\n * environment variables to fall back to.\n */\nexport interface ConfigField<T> {\n key: keyof T & string;\n env?: string[];\n}\n\nfunction resolveEnv(envKeys?: string[]): string | undefined {\n if (!envKeys) return undefined;\n for (const key of envKeys) {\n const value = process.env[key];\n if (value) return value;\n }\n return undefined;\n}\n\n/**\n * Returns true when at least one env-backed field is not provided via\n * `overrides`, meaning runtime config may still contribute and should be\n * probed to preserve precedence (`overrides > runtime > env`).\n *\n * @example\n * ```ts\n * const FIELDS: ConfigField<MyAdapterConfig>[] = [\n * { key: 'token', env: ['MY_ADAPTER_TOKEN'] },\n * { key: 'endpoint', env: ['MY_ADAPTER_URL'] },\n * ]\n *\n * if (shouldProbeRuntime(FIELDS, overrides)) {\n * runtimeConfig = await loadRuntimeConfig()\n * }\n * ```\n */\nexport function shouldProbeRuntime<T>(\n fields: ConfigField<T>[],\n overrides?: Partial<T>,\n): boolean {\n return fields.some(({ key, env }) => {\n if (!env || env.length === 0) return false;\n if (overrides?.[key] !== undefined) return false;\n return true;\n });\n}\n\n/**\n * Resolve adapter configuration with the standard priority chain:\n *\n * 1. `overrides` passed to the adapter factory\n * 2. `runtimeConfig.autotel.{namespace}.{key}` (if a probe was performed)\n * 3. `runtimeConfig.{namespace}.{key}` (if a probe was performed)\n * 4. `process.env[envKey]` for each env in `field.env`\n *\n * Pass an async `probe` to defer the runtime config lookup so it is only\n * invoked when runtime resolution is needed (i.e. at least one env-backed\n * field is not set by overrides). Adapters that have no probe target may pass\n * `() => Promise.resolve(undefined)`.\n */\nexport async function resolveAdapterConfig<T>(\n namespace: string,\n fields: ConfigField<T>[],\n overrides: Partial<T> | undefined,\n probe: () => Promise<Record<string, any> | undefined>,\n): Promise<Partial<T>> {\n const runtimeConfig = shouldProbeRuntime(fields, overrides)\n ? await probe()\n : undefined;\n const autotelNs = runtimeConfig?.autotel?.[namespace];\n const rootNs = runtimeConfig?.[namespace];\n\n const config: Record<string, unknown> = {};\n for (const { key, env } of fields) {\n config[key] =\n overrides?.[key] ??\n autotelNs?.[key] ??\n rootNs?.[key] ??\n resolveEnv(env);\n }\n\n return config as Partial<T>;\n}\n\nexport type HeadersLike =\n | { get(name: string): string | null }\n | Record<string, string | undefined>;\n\nexport function getHeader(\n headers: HeadersLike | undefined,\n name: string,\n): string | undefined {\n if (!headers) return undefined;\n if ('get' in headers && typeof headers.get === 'function') {\n return headers.get(name) ?? undefined;\n }\n const dictionary = headers as Record<string, string | undefined>;\n const value = dictionary[name] ?? dictionary[name.toLowerCase()];\n return typeof value === 'string' ? value : undefined;\n}\n\nexport type {\n RequestLogger,\n RequestLoggerOptions,\n RequestLogSnapshot,\n ParsedError,\n StructuredError,\n StructuredErrorInput,\n DrainPipelineOptions,\n PipelineDrainFn,\n};\n","import type { Context } from 'hono';\nimport { createUseLogger, createAdapterToolkit } from './core';\n\nexport const useLogger = createUseLogger<Context>({\n adapterName: 'hono',\n enrich: (c) => ({\n 'http.request.method': c.req.method,\n 'url.full': c.req.url,\n 'http.route': c.req.path,\n }),\n});\n\nexport const honoToolkit = createAdapterToolkit<Context>({\n adapterName: 'hono',\n enrich: (c) => ({\n 'http.request.method': c.req.method,\n 'url.full': c.req.url,\n 'http.route': c.req.path,\n }),\n});\n"]}
1
+ {"version":3,"sources":["../src/core.ts","../src/hono.ts"],"names":["useLogger","getRequestLogger","parseError","createStructuredError","createDrainPipeline"],"mappings":";;;;;AAkCO,SAAS,gBACd,OAAA,EACA;AACA,EAAA,OAAO,SAASA,UAAAA,CACd,OAAA,EACA,oBAAA,EACe;AACf,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAASC,wBAAA,CAAiB,QAAW,oBAAoB,CAAA;AAAA,IAC3D,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,kBAAA,EAAqB,QAAQ,WAAW,CAAA,2GAAA;AAAA,OAE1C;AAAA,IACF;AAEA,IAAA,IAAI,OAAA,IAAW,QAAQ,MAAA,EAAQ;AAC7B,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA;AACpC,MAAA,IAAI,SAAS,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,CAAE,SAAS,CAAA,EAAG;AAC1C,QAAA,MAAA,CAAO,IAAI,KAAK,CAAA;AAAA,MAClB;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;AA4CO,SAAS,qBACd,OAAA,EAC0B;AAC1B,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,gBAAgB,OAAO,CAAA;AAAA,gBAClCC,kBAAA;AAAA,2BACAC,6BAAA;AAAA,yBACAC;AAAA,GACF;AACF;;;AC9GO,IAAM,YAAY,eAAA,CAAyB;AAAA,EAChD,WAAA,EAAa,MAAA;AAAA,EACb,MAAA,EAAQ,CAAC,CAAA,MAAO;AAAA,IACd,qBAAA,EAAuB,EAAE,GAAA,CAAI,MAAA;AAAA,IAC7B,UAAA,EAAY,EAAE,GAAA,CAAI,GAAA;AAAA,IAClB,YAAA,EAAc,EAAE,GAAA,CAAI;AAAA,GACtB;AACF,CAAC;AAEM,IAAM,cAAc,oBAAA,CAA8B;AAAA,EACvD,WAAA,EAAa,MAAA;AAAA,EACb,MAAA,EAAQ,CAAC,CAAA,MAAO;AAAA,IACd,qBAAA,EAAuB,EAAE,GAAA,CAAI,MAAA;AAAA,IAC7B,UAAA,EAAY,EAAE,GAAA,CAAI,GAAA;AAAA,IAClB,YAAA,EAAc,EAAE,GAAA,CAAI;AAAA,GACtB;AACF,CAAC","file":"hono.cjs","sourcesContent":["import type { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n createDrainPipeline,\n createStructuredError,\n getRequestLogger,\n parseError,\n trace,\n type ParsedError,\n type RequestLogger,\n type RequestLoggerOptions,\n type RequestLogSnapshot,\n type DrainPipelineOptions,\n type PipelineDrainFn,\n type StructuredError,\n type StructuredErrorInput,\n} from 'autotel';\n\nexport interface AdapterUseLoggerOptions<TContext> {\n adapterName: string;\n enrich?: (context: TContext) => Record<string, unknown> | undefined;\n}\n\nexport interface AdapterToolkit<TContext> {\n useLogger: (\n context?: TContext,\n options?: RequestLoggerOptions,\n ) => RequestLogger;\n parseError: (error: unknown) => ParsedError;\n createStructuredError: (input: StructuredErrorInput) => StructuredError;\n createDrainPipeline: <T = unknown>(\n options?: DrainPipelineOptions<T>,\n ) => (drain: (batch: T[]) => void | Promise<void>) => PipelineDrainFn<T>;\n}\n\nexport function createUseLogger<TContext = unknown>(\n options: AdapterUseLoggerOptions<TContext>,\n) {\n return function useLogger(\n context?: TContext,\n requestLoggerOptions?: RequestLoggerOptions,\n ): RequestLogger {\n let logger: RequestLogger;\n try {\n logger = getRequestLogger(undefined, requestLoggerOptions);\n } catch {\n throw new Error(\n `[autotel-adapters/${options.adapterName}] No active trace context. ` +\n `Wrap your handler with autotel trace instrumentation before calling useLogger().`,\n );\n }\n\n if (context && options.enrich) {\n const extra = options.enrich(context);\n if (extra && Object.keys(extra).length > 0) {\n logger.set(extra);\n }\n }\n\n return logger;\n };\n}\n\nexport interface RequestRunnerOptions {\n requestLoggerOptions?: RequestLoggerOptions;\n /** Emit one wide event automatically when the handler settles. Default `true`. */\n autoEmit?: boolean;\n /** Fields merged into the wide event at emit time (e.g. response status). */\n finalize?: () => Record<string, unknown> | undefined;\n}\n\n/**\n * Build a request runner bound to one framework's logger storage. The returned\n * function opens a span, creates a request logger, runs `handler` inside the\n * storage so `useLogger()` resolves it, records thrown errors, and emits one\n * wide event when the handler settles (unless `autoEmit` is `false`).\n */\nexport function createRequestRunner(storage: AsyncLocalStorage<RequestLogger>) {\n return function runRequest<T>(\n spanName: string,\n enrich: (log: RequestLogger) => void,\n handler: () => T | Promise<T>,\n options?: RequestRunnerOptions,\n ): Promise<T> {\n const wrapped = trace(\n { name: spanName },\n (ctx) => async (): Promise<T> => {\n const log = getRequestLogger(ctx, options?.requestLoggerOptions);\n enrich(log);\n try {\n return await storage.run(log, () => handler());\n } catch (error) {\n log.error(error instanceof Error ? error : new Error(String(error)));\n throw error;\n } finally {\n if (options?.autoEmit !== false) {\n log.emitNow(options?.finalize?.());\n }\n }\n },\n );\n return wrapped();\n };\n}\n\nexport function createAdapterToolkit<TContext = unknown>(\n options: AdapterUseLoggerOptions<TContext>,\n): AdapterToolkit<TContext> {\n return {\n useLogger: createUseLogger(options),\n parseError,\n createStructuredError,\n createDrainPipeline,\n };\n}\n\n/**\n * Description of a single adapter config field. `env` is the ordered list of\n * environment variables to fall back to.\n */\nexport interface ConfigField<T> {\n key: keyof T & string;\n env?: string[];\n}\n\nfunction resolveEnv(envKeys?: string[]): string | undefined {\n if (!envKeys) return undefined;\n for (const key of envKeys) {\n const value = process.env[key];\n if (value) return value;\n }\n return undefined;\n}\n\n/**\n * Returns true when at least one env-backed field is not provided via\n * `overrides`, meaning runtime config may still contribute and should be\n * probed to preserve precedence (`overrides > runtime > env`).\n *\n * @example\n * ```ts\n * const FIELDS: ConfigField<MyAdapterConfig>[] = [\n * { key: 'token', env: ['MY_ADAPTER_TOKEN'] },\n * { key: 'endpoint', env: ['MY_ADAPTER_URL'] },\n * ]\n *\n * if (shouldProbeRuntime(FIELDS, overrides)) {\n * runtimeConfig = await loadRuntimeConfig()\n * }\n * ```\n */\nexport function shouldProbeRuntime<T>(\n fields: ConfigField<T>[],\n overrides?: Partial<T>,\n): boolean {\n return fields.some(({ key, env }) => {\n if (!env || env.length === 0) return false;\n if (overrides?.[key] !== undefined) return false;\n return true;\n });\n}\n\n/**\n * Resolve adapter configuration with the standard priority chain:\n *\n * 1. `overrides` passed to the adapter factory\n * 2. `runtimeConfig.autotel.{namespace}.{key}` (if a probe was performed)\n * 3. `runtimeConfig.{namespace}.{key}` (if a probe was performed)\n * 4. `process.env[envKey]` for each env in `field.env`\n *\n * Pass an async `probe` to defer the runtime config lookup so it is only\n * invoked when runtime resolution is needed (i.e. at least one env-backed\n * field is not set by overrides). Adapters that have no probe target may pass\n * `() => Promise.resolve(undefined)`.\n */\nexport async function resolveAdapterConfig<T>(\n namespace: string,\n fields: ConfigField<T>[],\n overrides: Partial<T> | undefined,\n probe: () => Promise<Record<string, any> | undefined>,\n): Promise<Partial<T>> {\n const runtimeConfig = shouldProbeRuntime(fields, overrides)\n ? await probe()\n : undefined;\n const autotelNs = runtimeConfig?.autotel?.[namespace];\n const rootNs = runtimeConfig?.[namespace];\n\n const config: Record<string, unknown> = {};\n for (const { key, env } of fields) {\n config[key] =\n overrides?.[key] ??\n autotelNs?.[key] ??\n rootNs?.[key] ??\n resolveEnv(env);\n }\n\n return config as Partial<T>;\n}\n\nexport type HeadersLike =\n | { get(name: string): string | null }\n | Record<string, string | undefined>;\n\nexport function getHeader(\n headers: HeadersLike | undefined,\n name: string,\n): string | undefined {\n if (!headers) return undefined;\n if ('get' in headers && typeof headers.get === 'function') {\n return headers.get(name) ?? undefined;\n }\n const dictionary = headers as Record<string, string | undefined>;\n const value = dictionary[name] ?? dictionary[name.toLowerCase()];\n return typeof value === 'string' ? value : undefined;\n}\n\nexport type {\n RequestLogger,\n RequestLoggerOptions,\n RequestLogSnapshot,\n ParsedError,\n StructuredError,\n StructuredErrorInput,\n DrainPipelineOptions,\n PipelineDrainFn,\n};\n","import type { Context } from 'hono';\nimport { createUseLogger, createAdapterToolkit } from './core';\n\nexport const useLogger = createUseLogger<Context>({\n adapterName: 'hono',\n enrich: (c) => ({\n 'http.request.method': c.req.method,\n 'url.full': c.req.url,\n 'http.route': c.req.path,\n }),\n});\n\nexport const honoToolkit = createAdapterToolkit<Context>({\n adapterName: 'hono',\n enrich: (c) => ({\n 'http.request.method': c.req.method,\n 'url.full': c.req.url,\n 'http.route': c.req.path,\n }),\n});\n"]}
package/dist/hono.d.cts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { AdapterToolkit } from './core.cjs';
2
2
  import * as autotel from 'autotel';
3
3
  import { Context } from 'hono';
4
+ import 'node:async_hooks';
4
5
 
5
6
  declare const useLogger: (context?: Context<any, any, {}> | undefined, requestLoggerOptions?: autotel.RequestLoggerOptions) => autotel.RequestLogger;
6
7
  declare const honoToolkit: AdapterToolkit<Context<any, any, {}>>;
package/dist/hono.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { AdapterToolkit } from './core.js';
2
2
  import * as autotel from 'autotel';
3
3
  import { Context } from 'hono';
4
+ import 'node:async_hooks';
4
5
 
5
6
  declare const useLogger: (context?: Context<any, any, {}> | undefined, requestLoggerOptions?: autotel.RequestLoggerOptions) => autotel.RequestLogger;
6
7
  declare const honoToolkit: AdapterToolkit<Context<any, any, {}>>;
package/dist/hono.js CHANGED
@@ -1,4 +1,4 @@
1
- export { honoToolkit, useLogger } from './chunk-UUDK5U3L.js';
2
- import './chunk-GBSB7IX7.js';
1
+ export { honoToolkit, useLogger } from './chunk-JH5ZTTLF.js';
2
+ import './chunk-DJ2OU3S6.js';
3
3
  //# sourceMappingURL=hono.js.map
4
4
  //# sourceMappingURL=hono.js.map
package/dist/index.cjs CHANGED
@@ -5,7 +5,7 @@ var async_hooks = require('async_hooks');
5
5
 
6
6
  // src/core.ts
7
7
  function createUseLogger(options) {
8
- return function useLogger6(context, requestLoggerOptions) {
8
+ return function useLogger8(context, requestLoggerOptions) {
9
9
  let logger;
10
10
  try {
11
11
  logger = autotel.getRequestLogger(void 0, requestLoggerOptions);
@@ -23,6 +23,28 @@ function createUseLogger(options) {
23
23
  return logger;
24
24
  };
25
25
  }
26
+ function createRequestRunner(storage) {
27
+ return function runRequest3(spanName, enrich, handler, options) {
28
+ const wrapped = autotel.trace(
29
+ { name: spanName },
30
+ (ctx) => async () => {
31
+ const log = autotel.getRequestLogger(ctx, options?.requestLoggerOptions);
32
+ enrich(log);
33
+ try {
34
+ return await storage.run(log, () => handler());
35
+ } catch (error) {
36
+ log.error(error instanceof Error ? error : new Error(String(error)));
37
+ throw error;
38
+ } finally {
39
+ if (options?.autoEmit !== false) {
40
+ log.emitNow(options?.finalize?.());
41
+ }
42
+ }
43
+ }
44
+ );
45
+ return wrapped();
46
+ };
47
+ }
26
48
  function createAdapterToolkit(options) {
27
49
  return {
28
50
  useLogger: createUseLogger(options),
@@ -110,7 +132,16 @@ function withAutotel(handler, options) {
110
132
  if (custom && Object.keys(custom).length > 0) {
111
133
  log.set(custom);
112
134
  }
113
- return await nextLoggerStorage.run(log, async () => handler(...innerArgs));
135
+ try {
136
+ return await nextLoggerStorage.run(
137
+ log,
138
+ async () => handler(...innerArgs)
139
+ );
140
+ } finally {
141
+ if (options?.autoEmit !== false) {
142
+ log.emitNow();
143
+ }
144
+ }
114
145
  }
115
146
  );
116
147
  return await wrapped(...args);
@@ -159,7 +190,16 @@ function withAutotelEventHandler(handler, options) {
159
190
  if (custom && Object.keys(custom).length > 0) {
160
191
  log.set(custom);
161
192
  }
162
- return await nitroLoggerStorage.run(log, async () => handler(innerEvent));
193
+ try {
194
+ return await nitroLoggerStorage.run(
195
+ log,
196
+ async () => handler(innerEvent)
197
+ );
198
+ } finally {
199
+ if (options?.autoEmit !== false) {
200
+ log.emitNow();
201
+ }
202
+ }
163
203
  });
164
204
  return await wrapped(event);
165
205
  };
@@ -236,6 +276,9 @@ function withAutotelFetch(handler, options) {
236
276
  try {
237
277
  return await handler(innerRequest, innerEnv, innerExecutionContext);
238
278
  } finally {
279
+ if (options?.autoEmit !== false) {
280
+ log.emitNow();
281
+ }
239
282
  requestLoggers.delete(innerRequest);
240
283
  }
241
284
  }
@@ -252,6 +295,129 @@ function createCloudflareAdapter(options) {
252
295
  createDrainPipeline: (drainOptions) => autotel.createDrainPipeline(drainOptions)
253
296
  };
254
297
  }
298
+ var expressLoggerStorage = new async_hooks.AsyncLocalStorage();
299
+ function headerValue(headers, name) {
300
+ if (!headers) return void 0;
301
+ const value = headers[name] ?? headers[name.toLowerCase()];
302
+ if (Array.isArray(value)) return value[0];
303
+ return typeof value === "string" ? value : void 0;
304
+ }
305
+ function enrichFromRequest3(request) {
306
+ if (!request) return void 0;
307
+ const url = request.originalUrl ?? request.url;
308
+ const route = request.route?.path ?? request.path ?? url;
309
+ const requestId = headerValue(request.headers, "x-request-id");
310
+ return {
311
+ ...request.method ? { "http.request.method": request.method } : {},
312
+ ...url ? { "url.full": url } : {},
313
+ ...route ? { "http.route": route } : {},
314
+ ...requestId ? { "http.request.id": requestId } : {}
315
+ };
316
+ }
317
+ var baseUseLogger4 = createUseLogger({
318
+ adapterName: "express",
319
+ enrich: enrichFromRequest3
320
+ });
321
+ function useLogger4(request, requestLoggerOptions) {
322
+ const stored = expressLoggerStorage.getStore();
323
+ if (stored) return stored;
324
+ return baseUseLogger4(request, requestLoggerOptions);
325
+ }
326
+ var runRequest = createRequestRunner(expressLoggerStorage);
327
+ function withAutotel2(handler, options) {
328
+ return async (req, res, next) => {
329
+ const spanName = typeof options?.spanName === "function" ? options.spanName(req) : options?.spanName ?? `express.${req.method ?? "request"}`;
330
+ try {
331
+ return await runRequest(
332
+ spanName,
333
+ (log) => {
334
+ const auto = enrichFromRequest3(req);
335
+ if (auto && Object.keys(auto).length > 0) log.set(auto);
336
+ const custom = options?.enrich?.(req);
337
+ if (custom && Object.keys(custom).length > 0) log.set(custom);
338
+ },
339
+ () => handler(req, res, next),
340
+ {
341
+ requestLoggerOptions: options?.requestLoggerOptions,
342
+ autoEmit: options?.autoEmit,
343
+ finalize: () => res.statusCode ? { "http.response.status_code": res.statusCode } : void 0
344
+ }
345
+ );
346
+ } catch (error) {
347
+ if (typeof next === "function") {
348
+ next(error);
349
+ return void 0;
350
+ }
351
+ throw error;
352
+ }
353
+ };
354
+ }
355
+ function createExpressAdapter(options) {
356
+ return {
357
+ withAutotel: (handler) => withAutotel2(handler, options),
358
+ useLogger: useLogger4,
359
+ parseError: (error) => autotel.parseError(error),
360
+ createStructuredError: (input) => autotel.createStructuredError(input),
361
+ createDrainPipeline: (drainOptions) => autotel.createDrainPipeline(drainOptions)
362
+ };
363
+ }
364
+ var fastifyLoggerStorage = new async_hooks.AsyncLocalStorage();
365
+ function headerValue2(headers, name) {
366
+ if (!headers) return void 0;
367
+ const value = headers[name] ?? headers[name.toLowerCase()];
368
+ if (Array.isArray(value)) return value[0];
369
+ return typeof value === "string" ? value : void 0;
370
+ }
371
+ function enrichFromRequest4(request) {
372
+ if (!request) return void 0;
373
+ const route = request.routeOptions?.url ?? request.routerPath ?? request.url;
374
+ const requestId = request.id ?? headerValue2(request.headers, "x-request-id");
375
+ return {
376
+ ...request.method ? { "http.request.method": request.method } : {},
377
+ ...request.url ? { "url.full": request.url } : {},
378
+ ...route ? { "http.route": route } : {},
379
+ ...requestId ? { "http.request.id": requestId } : {}
380
+ };
381
+ }
382
+ var baseUseLogger5 = createUseLogger({
383
+ adapterName: "fastify",
384
+ enrich: enrichFromRequest4
385
+ });
386
+ function useLogger5(request, requestLoggerOptions) {
387
+ const stored = fastifyLoggerStorage.getStore();
388
+ if (stored) return stored;
389
+ return baseUseLogger5(request, requestLoggerOptions);
390
+ }
391
+ var runRequest2 = createRequestRunner(fastifyLoggerStorage);
392
+ function withAutotel3(handler, options) {
393
+ return (request, reply) => {
394
+ const spanName = typeof options?.spanName === "function" ? options.spanName(request) : options?.spanName ?? `fastify.${request.method ?? "request"}`;
395
+ return runRequest2(
396
+ spanName,
397
+ (log) => {
398
+ const auto = enrichFromRequest4(request);
399
+ if (auto && Object.keys(auto).length > 0) log.set(auto);
400
+ const custom = options?.enrich?.(request);
401
+ if (custom && Object.keys(custom).length > 0) log.set(custom);
402
+ },
403
+ () => handler(request, reply),
404
+ {
405
+ requestLoggerOptions: options?.requestLoggerOptions,
406
+ autoEmit: options?.autoEmit,
407
+ finalize: () => reply.statusCode ? { "http.response.status_code": reply.statusCode } : void 0
408
+ }
409
+ );
410
+ };
411
+ }
412
+ function createFastifyAdapter(options) {
413
+ return {
414
+ withAutotel: (handler) => withAutotel3(handler, options),
415
+ useLogger: useLogger5,
416
+ parseError: (error) => autotel.parseError(error),
417
+ createStructuredError: (input) => autotel.createStructuredError(input),
418
+ createDrainPipeline: (drainOptions) => autotel.createDrainPipeline(drainOptions)
419
+ };
420
+ }
255
421
  var honoToolkit = createAdapterToolkit({
256
422
  adapterName: "hono",
257
423
  enrich: (c) => ({
@@ -270,8 +436,11 @@ var tanstackToolkit = createAdapterToolkit({
270
436
 
271
437
  exports.createAdapterToolkit = createAdapterToolkit;
272
438
  exports.createCloudflareAdapter = createCloudflareAdapter;
439
+ exports.createExpressAdapter = createExpressAdapter;
440
+ exports.createFastifyAdapter = createFastifyAdapter;
273
441
  exports.createNextAdapter = createNextAdapter;
274
442
  exports.createNitroAdapter = createNitroAdapter;
443
+ exports.createRequestRunner = createRequestRunner;
275
444
  exports.createUseLogger = createUseLogger;
276
445
  exports.getHeader = getHeader;
277
446
  exports.honoToolkit = honoToolkit;
@@ -280,6 +449,8 @@ exports.shouldProbeRuntime = shouldProbeRuntime;
280
449
  exports.tanstackToolkit = tanstackToolkit;
281
450
  exports.withAutotel = withAutotel;
282
451
  exports.withAutotelEventHandler = withAutotelEventHandler;
452
+ exports.withAutotelExpress = withAutotel2;
453
+ exports.withAutotelFastify = withAutotel3;
283
454
  exports.withAutotelFetch = withAutotelFetch;
284
455
  //# sourceMappingURL=index.cjs.map
285
456
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core.ts","../src/next.ts","../src/nitro.ts","../src/cloudflare.ts","../src/hono.ts","../src/tanstack.ts"],"names":["useLogger","getRequestLogger","parseError","createStructuredError","createDrainPipeline","AsyncLocalStorage","trace","baseUseLogger","enrichFromRequest"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n createDrainPipeline,\n createStructuredError,\n getRequestLogger,\n parseError,\n type ParsedError,\n type RequestLogger,\n type RequestLoggerOptions,\n type RequestLogSnapshot,\n type DrainPipelineOptions,\n type PipelineDrainFn,\n type StructuredError,\n type StructuredErrorInput,\n} from 'autotel';\n\nexport interface AdapterUseLoggerOptions<TContext> {\n adapterName: string;\n enrich?: (context: TContext) => Record<string, unknown> | undefined;\n}\n\nexport interface AdapterToolkit<TContext> {\n useLogger: (\n context?: TContext,\n options?: RequestLoggerOptions,\n ) => RequestLogger;\n parseError: (error: unknown) => ParsedError;\n createStructuredError: (input: StructuredErrorInput) => StructuredError;\n createDrainPipeline: <T = unknown>(\n options?: DrainPipelineOptions<T>,\n ) => (drain: (batch: T[]) => void | Promise<void>) => PipelineDrainFn<T>;\n}\n\nexport function createUseLogger<TContext = unknown>(\n options: AdapterUseLoggerOptions<TContext>,\n) {\n return function useLogger(\n context?: TContext,\n requestLoggerOptions?: RequestLoggerOptions,\n ): RequestLogger {\n let logger: RequestLogger;\n try {\n logger = getRequestLogger(undefined, requestLoggerOptions);\n } catch {\n throw new Error(\n `[autotel-adapters/${options.adapterName}] No active trace context. ` +\n `Wrap your handler with autotel trace instrumentation before calling useLogger().`,\n );\n }\n\n if (context && options.enrich) {\n const extra = options.enrich(context);\n if (extra && Object.keys(extra).length > 0) {\n logger.set(extra);\n }\n }\n\n return logger;\n };\n}\n\nexport function createAdapterToolkit<TContext = unknown>(\n options: AdapterUseLoggerOptions<TContext>,\n): AdapterToolkit<TContext> {\n return {\n useLogger: createUseLogger(options),\n parseError,\n createStructuredError,\n createDrainPipeline,\n };\n}\n\n/**\n * Description of a single adapter config field. `env` is the ordered list of\n * environment variables to fall back to.\n */\nexport interface ConfigField<T> {\n key: keyof T & string;\n env?: string[];\n}\n\nfunction resolveEnv(envKeys?: string[]): string | undefined {\n if (!envKeys) return undefined;\n for (const key of envKeys) {\n const value = process.env[key];\n if (value) return value;\n }\n return undefined;\n}\n\n/**\n * Returns true when at least one env-backed field is not provided via\n * `overrides`, meaning runtime config may still contribute and should be\n * probed to preserve precedence (`overrides > runtime > env`).\n *\n * @example\n * ```ts\n * const FIELDS: ConfigField<MyAdapterConfig>[] = [\n * { key: 'token', env: ['MY_ADAPTER_TOKEN'] },\n * { key: 'endpoint', env: ['MY_ADAPTER_URL'] },\n * ]\n *\n * if (shouldProbeRuntime(FIELDS, overrides)) {\n * runtimeConfig = await loadRuntimeConfig()\n * }\n * ```\n */\nexport function shouldProbeRuntime<T>(\n fields: ConfigField<T>[],\n overrides?: Partial<T>,\n): boolean {\n return fields.some(({ key, env }) => {\n if (!env || env.length === 0) return false;\n if (overrides?.[key] !== undefined) return false;\n return true;\n });\n}\n\n/**\n * Resolve adapter configuration with the standard priority chain:\n *\n * 1. `overrides` passed to the adapter factory\n * 2. `runtimeConfig.autotel.{namespace}.{key}` (if a probe was performed)\n * 3. `runtimeConfig.{namespace}.{key}` (if a probe was performed)\n * 4. `process.env[envKey]` for each env in `field.env`\n *\n * Pass an async `probe` to defer the runtime config lookup so it is only\n * invoked when runtime resolution is needed (i.e. at least one env-backed\n * field is not set by overrides). Adapters that have no probe target may pass\n * `() => Promise.resolve(undefined)`.\n */\nexport async function resolveAdapterConfig<T>(\n namespace: string,\n fields: ConfigField<T>[],\n overrides: Partial<T> | undefined,\n probe: () => Promise<Record<string, any> | undefined>,\n): Promise<Partial<T>> {\n const runtimeConfig = shouldProbeRuntime(fields, overrides)\n ? await probe()\n : undefined;\n const autotelNs = runtimeConfig?.autotel?.[namespace];\n const rootNs = runtimeConfig?.[namespace];\n\n const config: Record<string, unknown> = {};\n for (const { key, env } of fields) {\n config[key] =\n overrides?.[key] ??\n autotelNs?.[key] ??\n rootNs?.[key] ??\n resolveEnv(env);\n }\n\n return config as Partial<T>;\n}\n\nexport type HeadersLike =\n | { get(name: string): string | null }\n | Record<string, string | undefined>;\n\nexport function getHeader(\n headers: HeadersLike | undefined,\n name: string,\n): string | undefined {\n if (!headers) return undefined;\n if ('get' in headers && typeof headers.get === 'function') {\n return headers.get(name) ?? undefined;\n }\n const dictionary = headers as Record<string, string | undefined>;\n const value = dictionary[name] ?? dictionary[name.toLowerCase()];\n return typeof value === 'string' ? value : undefined;\n}\n\nexport type {\n RequestLogger,\n RequestLoggerOptions,\n RequestLogSnapshot,\n ParsedError,\n StructuredError,\n StructuredErrorInput,\n DrainPipelineOptions,\n PipelineDrainFn,\n};\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n createDrainPipeline,\n getRequestLogger,\n parseError,\n trace,\n createStructuredError,\n type RequestLogger,\n type RequestLoggerOptions,\n type ParsedError,\n type DrainPipelineOptions,\n type PipelineDrainFn,\n type StructuredError,\n type StructuredErrorInput,\n} from 'autotel';\nimport { createAdapterToolkit, createUseLogger, getHeader } from './core';\n\nexport interface NextRequestLike {\n method?: string;\n url?: string;\n headers?:\n | { get(name: string): string | null }\n | Record<string, string | undefined>;\n}\n\nexport interface NextWithAutotelOptions {\n spanName?: string | ((request?: NextRequestLike) => string);\n requestLoggerOptions?: RequestLoggerOptions;\n enrich?: (request?: NextRequestLike) => Record<string, unknown> | undefined;\n}\n\nconst nextLoggerStorage = new AsyncLocalStorage<RequestLogger>();\n\nfunction enrichFromRequest(\n request?: NextRequestLike,\n): Record<string, unknown> | undefined {\n if (!request) return undefined;\n\n let route = '/';\n if (request.url) {\n try {\n route = new URL(request.url).pathname;\n } catch {\n route = request.url;\n }\n }\n const requestId = getHeader(request.headers, 'x-request-id');\n\n return {\n ...(request.method ? { 'http.request.method': request.method } : {}),\n ...(request.url ? { 'url.full': request.url } : {}),\n ...(route ? { 'http.route': route } : {}),\n ...(requestId ? { 'http.request.header.x-request-id': requestId } : {}),\n };\n}\n\nconst baseUseLogger = createUseLogger<NextRequestLike>({\n adapterName: 'next',\n enrich: enrichFromRequest,\n});\n\nexport function useLogger(\n request?: NextRequestLike,\n requestLoggerOptions?: RequestLoggerOptions,\n): RequestLogger {\n const logger = nextLoggerStorage.getStore();\n if (logger) return logger;\n return baseUseLogger(request, requestLoggerOptions);\n}\n\nexport function withAutotel<TArgs extends unknown[], TReturn>(\n handler: (...args: TArgs) => TReturn | Promise<TReturn>,\n options?: NextWithAutotelOptions,\n): (...args: TArgs) => Promise<TReturn> {\n return async (...args: TArgs): Promise<TReturn> => {\n const request = args[0] as NextRequestLike | undefined;\n const spanName =\n typeof options?.spanName === 'function'\n ? options.spanName(request)\n : (options?.spanName ?? 'next.request');\n\n const wrapped = trace(\n { name: spanName },\n (ctx) => async (...innerArgs: TArgs) => {\n const innerRequest = innerArgs[0] as NextRequestLike | undefined;\n const log = getRequestLogger(ctx, options?.requestLoggerOptions);\n const auto = enrichFromRequest(innerRequest);\n if (auto && Object.keys(auto).length > 0) {\n log.set(auto);\n }\n const custom = options?.enrich?.(innerRequest);\n if (custom && Object.keys(custom).length > 0) {\n log.set(custom);\n }\n return await nextLoggerStorage.run(log, async () => handler(...innerArgs));\n },\n );\n return await wrapped(...args);\n };\n}\n\nexport function createNextAdapter(options?: NextWithAutotelOptions) {\n return {\n withAutotel: <TArgs extends unknown[], TReturn>(\n handler: (...args: TArgs) => TReturn | Promise<TReturn>,\n ) => withAutotel(handler, options),\n useLogger: (\n request?: NextRequestLike,\n requestLoggerOptions?: RequestLoggerOptions,\n ): RequestLogger => useLogger(request, requestLoggerOptions),\n parseError: (error: unknown): ParsedError => parseError(error),\n createStructuredError: (\n input: StructuredErrorInput,\n ): StructuredError => createStructuredError(input),\n createDrainPipeline: <T = unknown>(\n drainOptions?: DrainPipelineOptions<T>,\n ): ((batchDrain: (batch: T[]) => void | Promise<void>) => PipelineDrainFn<T>) =>\n createDrainPipeline(drainOptions),\n };\n}\n\nexport const nextToolkit = createAdapterToolkit<NextRequestLike>({\n adapterName: 'next',\n enrich: enrichFromRequest,\n});\n\nexport { parseError, createDrainPipeline, createStructuredError };\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n getRequestLogger,\n trace,\n type RequestLogger,\n type RequestLoggerOptions,\n} from 'autotel';\nimport { createAdapterToolkit, createUseLogger } from './core';\n\nexport interface NitroEventLike {\n method?: string;\n path?: string;\n context?: Record<string, unknown>;\n}\n\nexport interface NitroWithAutotelOptions {\n spanName?: string | ((event: NitroEventLike) => string);\n requestLoggerOptions?: RequestLoggerOptions;\n enrich?: (event: NitroEventLike) => Record<string, unknown> | undefined;\n}\n\nfunction enrichFromEvent(\n event?: NitroEventLike,\n): Record<string, unknown> | undefined {\n if (!event) return undefined;\n\n return {\n ...(event.method ? { 'http.request.method': event.method } : {}),\n ...(event.path ? { 'http.route': event.path } : {}),\n ...(typeof event.context?.requestId === 'string'\n ? { 'http.request.id': event.context.requestId }\n : {}),\n };\n}\n\nconst baseUseLogger = createUseLogger<NitroEventLike>({\n adapterName: 'nitro',\n enrich: enrichFromEvent,\n});\nconst nitroLoggerStorage = new AsyncLocalStorage<RequestLogger>();\n\nexport function useLogger(\n event?: NitroEventLike,\n serviceOrOptions?: string | RequestLoggerOptions,\n): RequestLogger {\n const stored = nitroLoggerStorage.getStore();\n const logger = stored ??\n (\n typeof serviceOrOptions === 'string'\n ? baseUseLogger(event)\n : baseUseLogger(event, serviceOrOptions)\n );\n\n if (typeof serviceOrOptions === 'string' && serviceOrOptions.length > 0) {\n logger.set({ service: serviceOrOptions });\n }\n\n return logger;\n}\n\nexport function withAutotelEventHandler<TEvent extends NitroEventLike, TReturn>(\n handler: (event: TEvent) => TReturn | Promise<TReturn>,\n options?: NitroWithAutotelOptions,\n): (event: TEvent) => Promise<TReturn> {\n return async (event: TEvent): Promise<TReturn> => {\n const spanName =\n typeof options?.spanName === 'function'\n ? options.spanName(event)\n : (options?.spanName ?? `nitro.${event.method ?? 'request'}`);\n\n const wrapped = trace({ name: spanName }, (ctx) => async (innerEvent: TEvent) => {\n const log = getRequestLogger(ctx, options?.requestLoggerOptions);\n const auto = enrichFromEvent(innerEvent);\n if (auto && Object.keys(auto).length > 0) {\n log.set(auto);\n }\n const custom = options?.enrich?.(innerEvent);\n if (custom && Object.keys(custom).length > 0) {\n log.set(custom);\n }\n return await nitroLoggerStorage.run(log, async () => handler(innerEvent));\n });\n\n return await wrapped(event);\n };\n}\n\nexport function createNitroAdapter(options?: NitroWithAutotelOptions) {\n const toolkit = createAdapterToolkit<NitroEventLike>({\n adapterName: 'nitro',\n enrich: (event) => ({\n ...enrichFromEvent(event),\n ...(options?.enrich?.(event) ?? {}),\n }),\n });\n\n return {\n withAutotelEventHandler: <TEvent extends NitroEventLike, TReturn>(\n handler: (event: TEvent) => TReturn | Promise<TReturn>,\n ) => withAutotelEventHandler(handler, options),\n useLogger,\n parseError: toolkit.parseError,\n createStructuredError: toolkit.createStructuredError,\n createDrainPipeline: toolkit.createDrainPipeline,\n };\n}\n\nexport const nitroToolkit = createAdapterToolkit<NitroEventLike>({\n adapterName: 'nitro',\n enrich: enrichFromEvent,\n});\n","import {\n createDrainPipeline,\n createStructuredError,\n getRequestLogger,\n parseError,\n trace,\n type DrainPipelineOptions,\n type ParsedError,\n type PipelineDrainFn,\n type RequestLogger,\n type RequestLoggerOptions,\n type StructuredError,\n type StructuredErrorInput,\n} from 'autotel';\nimport { createAdapterToolkit, createUseLogger, getHeader } from './core';\n\nexport interface CloudflareRequestLike {\n method?: string;\n url?: string;\n headers?:\n | { get(name: string): string | null }\n | Record<string, string | undefined>;\n cf?: Record<string, unknown>;\n}\n\nexport interface CloudflareExecutionContextLike {\n waitUntil?: (promise: Promise<unknown>) => void;\n passThroughOnException?: () => void;\n}\n\nexport interface CloudflareWithAutotelOptions<TEnv = unknown> {\n spanName?: string | ((request: CloudflareRequestLike, env: TEnv) => string);\n requestLoggerOptions?: RequestLoggerOptions;\n enrich?: (\n request: CloudflareRequestLike,\n env: TEnv,\n ctx: CloudflareExecutionContextLike,\n ) => Record<string, unknown> | undefined;\n}\n\nconst requestLoggers = new WeakMap<object, RequestLogger>();\n\nfunction enrichFromRequest(\n request?: CloudflareRequestLike,\n): Record<string, unknown> | undefined {\n if (!request) return undefined;\n\n let route = '/';\n if (request.url) {\n try {\n route = new URL(request.url).pathname;\n } catch {\n route = request.url;\n }\n }\n\n const requestId =\n getHeader(request.headers, 'x-request-id') ??\n getHeader(request.headers, 'cf-ray');\n\n return {\n ...(request.method ? { 'http.request.method': request.method } : {}),\n ...(request.url ? { 'url.full': request.url } : {}),\n ...(route ? { 'http.route': route } : {}),\n ...(requestId ? { 'http.request.id': requestId } : {}),\n ...(request.cf?.country ? { 'cloudflare.country': request.cf.country } : {}),\n ...(request.cf?.colo ? { 'cloudflare.colo': request.cf.colo } : {}),\n ...(request.cf?.city ? { 'cloudflare.city': request.cf.city } : {}),\n };\n}\n\nconst baseUseLogger = createUseLogger<CloudflareRequestLike>({\n adapterName: 'cloudflare',\n enrich: enrichFromRequest,\n});\n\nexport function useLogger(\n request?: CloudflareRequestLike,\n requestLoggerOptions?: RequestLoggerOptions,\n): RequestLogger {\n if (request) {\n const existing = requestLoggers.get(request as object);\n if (existing) return existing;\n }\n return baseUseLogger(request, requestLoggerOptions);\n}\n\nexport function withAutotelFetch<\n TEnv,\n TRequest extends CloudflareRequestLike,\n TContext extends CloudflareExecutionContextLike,\n TReturn,\n>(\n handler: (\n request: TRequest,\n env: TEnv,\n ctx: TContext,\n ) => TReturn | Promise<TReturn>,\n options?: CloudflareWithAutotelOptions<TEnv>,\n): (\n request: TRequest,\n env: TEnv,\n ctx: TContext,\n) => Promise<TReturn> {\n return async (\n request: TRequest,\n env: TEnv,\n executionContext: TContext,\n ): Promise<TReturn> => {\n const spanName =\n typeof options?.spanName === 'function'\n ? options.spanName(request, env)\n : (options?.spanName ?? `cloudflare.${request.method ?? 'request'}`);\n\n const wrapped = trace(\n { name: spanName },\n (ctx) => async (\n innerRequest: TRequest,\n innerEnv: TEnv,\n innerExecutionContext: TContext,\n ) => {\n const log = getRequestLogger(ctx, options?.requestLoggerOptions);\n const auto = enrichFromRequest(innerRequest);\n if (auto && Object.keys(auto).length > 0) {\n log.set(auto);\n }\n const custom = options?.enrich?.(\n innerRequest,\n innerEnv,\n innerExecutionContext,\n );\n if (custom && Object.keys(custom).length > 0) {\n log.set(custom);\n }\n\n requestLoggers.set(innerRequest as object, log);\n try {\n return await handler(innerRequest, innerEnv, innerExecutionContext);\n } finally {\n requestLoggers.delete(innerRequest as object);\n }\n },\n );\n\n return await wrapped(request, env, executionContext);\n };\n}\n\nexport function createCloudflareAdapter<TEnv = unknown>(\n options?: CloudflareWithAutotelOptions<TEnv>,\n) {\n return {\n withAutotelFetch: <\n TRequest extends CloudflareRequestLike,\n TContext extends CloudflareExecutionContextLike,\n TReturn,\n >(\n handler: (\n request: TRequest,\n env: TEnv,\n ctx: TContext,\n ) => TReturn | Promise<TReturn>,\n ) => withAutotelFetch(handler, options),\n useLogger,\n parseError: (error: unknown): ParsedError => parseError(error),\n createStructuredError: (\n input: StructuredErrorInput,\n ): StructuredError => createStructuredError(input),\n createDrainPipeline: <T = unknown>(\n drainOptions?: DrainPipelineOptions<T>,\n ): ((batchDrain: (batch: T[]) => void | Promise<void>) => PipelineDrainFn<T>) =>\n createDrainPipeline(drainOptions),\n };\n}\n\nexport const cloudflareToolkit = createAdapterToolkit<CloudflareRequestLike>({\n adapterName: 'cloudflare',\n enrich: enrichFromRequest,\n});\n\nexport { parseError, createDrainPipeline, createStructuredError };\n","import type { Context } from 'hono';\nimport { createUseLogger, createAdapterToolkit } from './core';\n\nexport const useLogger = createUseLogger<Context>({\n adapterName: 'hono',\n enrich: (c) => ({\n 'http.request.method': c.req.method,\n 'url.full': c.req.url,\n 'http.route': c.req.path,\n }),\n});\n\nexport const honoToolkit = createAdapterToolkit<Context>({\n adapterName: 'hono',\n enrich: (c) => ({\n 'http.request.method': c.req.method,\n 'url.full': c.req.url,\n 'http.route': c.req.path,\n }),\n});\n","import { createUseLogger, createAdapterToolkit } from './core';\n\nexport const useLogger = createUseLogger<{\n pathname?: string;\n method?: string;\n}>({\n adapterName: 'tanstack',\n enrich: (ctx) => ({\n ...(ctx.method ? { 'http.request.method': ctx.method } : {}),\n ...(ctx.pathname ? { 'http.route': ctx.pathname } : {}),\n }),\n});\n\nexport const tanstackToolkit = createAdapterToolkit<{\n pathname?: string;\n method?: string;\n}>({\n adapterName: 'tanstack',\n enrich: (ctx) => ({\n ...(ctx.method ? { 'http.request.method': ctx.method } : {}),\n ...(ctx.pathname ? { 'http.route': ctx.pathname } : {}),\n }),\n});\n"]}
1
+ {"version":3,"sources":["../src/core.ts","../src/next.ts","../src/nitro.ts","../src/cloudflare.ts","../src/express.ts","../src/fastify.ts","../src/hono.ts","../src/tanstack.ts"],"names":["useLogger","getRequestLogger","runRequest","trace","parseError","createStructuredError","createDrainPipeline","AsyncLocalStorage","baseUseLogger","enrichFromRequest","withAutotel","headerValue"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n createDrainPipeline,\n createStructuredError,\n getRequestLogger,\n parseError,\n trace,\n type ParsedError,\n type RequestLogger,\n type RequestLoggerOptions,\n type RequestLogSnapshot,\n type DrainPipelineOptions,\n type PipelineDrainFn,\n type StructuredError,\n type StructuredErrorInput,\n} from 'autotel';\n\nexport interface AdapterUseLoggerOptions<TContext> {\n adapterName: string;\n enrich?: (context: TContext) => Record<string, unknown> | undefined;\n}\n\nexport interface AdapterToolkit<TContext> {\n useLogger: (\n context?: TContext,\n options?: RequestLoggerOptions,\n ) => RequestLogger;\n parseError: (error: unknown) => ParsedError;\n createStructuredError: (input: StructuredErrorInput) => StructuredError;\n createDrainPipeline: <T = unknown>(\n options?: DrainPipelineOptions<T>,\n ) => (drain: (batch: T[]) => void | Promise<void>) => PipelineDrainFn<T>;\n}\n\nexport function createUseLogger<TContext = unknown>(\n options: AdapterUseLoggerOptions<TContext>,\n) {\n return function useLogger(\n context?: TContext,\n requestLoggerOptions?: RequestLoggerOptions,\n ): RequestLogger {\n let logger: RequestLogger;\n try {\n logger = getRequestLogger(undefined, requestLoggerOptions);\n } catch {\n throw new Error(\n `[autotel-adapters/${options.adapterName}] No active trace context. ` +\n `Wrap your handler with autotel trace instrumentation before calling useLogger().`,\n );\n }\n\n if (context && options.enrich) {\n const extra = options.enrich(context);\n if (extra && Object.keys(extra).length > 0) {\n logger.set(extra);\n }\n }\n\n return logger;\n };\n}\n\nexport interface RequestRunnerOptions {\n requestLoggerOptions?: RequestLoggerOptions;\n /** Emit one wide event automatically when the handler settles. Default `true`. */\n autoEmit?: boolean;\n /** Fields merged into the wide event at emit time (e.g. response status). */\n finalize?: () => Record<string, unknown> | undefined;\n}\n\n/**\n * Build a request runner bound to one framework's logger storage. The returned\n * function opens a span, creates a request logger, runs `handler` inside the\n * storage so `useLogger()` resolves it, records thrown errors, and emits one\n * wide event when the handler settles (unless `autoEmit` is `false`).\n */\nexport function createRequestRunner(storage: AsyncLocalStorage<RequestLogger>) {\n return function runRequest<T>(\n spanName: string,\n enrich: (log: RequestLogger) => void,\n handler: () => T | Promise<T>,\n options?: RequestRunnerOptions,\n ): Promise<T> {\n const wrapped = trace(\n { name: spanName },\n (ctx) => async (): Promise<T> => {\n const log = getRequestLogger(ctx, options?.requestLoggerOptions);\n enrich(log);\n try {\n return await storage.run(log, () => handler());\n } catch (error) {\n log.error(error instanceof Error ? error : new Error(String(error)));\n throw error;\n } finally {\n if (options?.autoEmit !== false) {\n log.emitNow(options?.finalize?.());\n }\n }\n },\n );\n return wrapped();\n };\n}\n\nexport function createAdapterToolkit<TContext = unknown>(\n options: AdapterUseLoggerOptions<TContext>,\n): AdapterToolkit<TContext> {\n return {\n useLogger: createUseLogger(options),\n parseError,\n createStructuredError,\n createDrainPipeline,\n };\n}\n\n/**\n * Description of a single adapter config field. `env` is the ordered list of\n * environment variables to fall back to.\n */\nexport interface ConfigField<T> {\n key: keyof T & string;\n env?: string[];\n}\n\nfunction resolveEnv(envKeys?: string[]): string | undefined {\n if (!envKeys) return undefined;\n for (const key of envKeys) {\n const value = process.env[key];\n if (value) return value;\n }\n return undefined;\n}\n\n/**\n * Returns true when at least one env-backed field is not provided via\n * `overrides`, meaning runtime config may still contribute and should be\n * probed to preserve precedence (`overrides > runtime > env`).\n *\n * @example\n * ```ts\n * const FIELDS: ConfigField<MyAdapterConfig>[] = [\n * { key: 'token', env: ['MY_ADAPTER_TOKEN'] },\n * { key: 'endpoint', env: ['MY_ADAPTER_URL'] },\n * ]\n *\n * if (shouldProbeRuntime(FIELDS, overrides)) {\n * runtimeConfig = await loadRuntimeConfig()\n * }\n * ```\n */\nexport function shouldProbeRuntime<T>(\n fields: ConfigField<T>[],\n overrides?: Partial<T>,\n): boolean {\n return fields.some(({ key, env }) => {\n if (!env || env.length === 0) return false;\n if (overrides?.[key] !== undefined) return false;\n return true;\n });\n}\n\n/**\n * Resolve adapter configuration with the standard priority chain:\n *\n * 1. `overrides` passed to the adapter factory\n * 2. `runtimeConfig.autotel.{namespace}.{key}` (if a probe was performed)\n * 3. `runtimeConfig.{namespace}.{key}` (if a probe was performed)\n * 4. `process.env[envKey]` for each env in `field.env`\n *\n * Pass an async `probe` to defer the runtime config lookup so it is only\n * invoked when runtime resolution is needed (i.e. at least one env-backed\n * field is not set by overrides). Adapters that have no probe target may pass\n * `() => Promise.resolve(undefined)`.\n */\nexport async function resolveAdapterConfig<T>(\n namespace: string,\n fields: ConfigField<T>[],\n overrides: Partial<T> | undefined,\n probe: () => Promise<Record<string, any> | undefined>,\n): Promise<Partial<T>> {\n const runtimeConfig = shouldProbeRuntime(fields, overrides)\n ? await probe()\n : undefined;\n const autotelNs = runtimeConfig?.autotel?.[namespace];\n const rootNs = runtimeConfig?.[namespace];\n\n const config: Record<string, unknown> = {};\n for (const { key, env } of fields) {\n config[key] =\n overrides?.[key] ??\n autotelNs?.[key] ??\n rootNs?.[key] ??\n resolveEnv(env);\n }\n\n return config as Partial<T>;\n}\n\nexport type HeadersLike =\n | { get(name: string): string | null }\n | Record<string, string | undefined>;\n\nexport function getHeader(\n headers: HeadersLike | undefined,\n name: string,\n): string | undefined {\n if (!headers) return undefined;\n if ('get' in headers && typeof headers.get === 'function') {\n return headers.get(name) ?? undefined;\n }\n const dictionary = headers as Record<string, string | undefined>;\n const value = dictionary[name] ?? dictionary[name.toLowerCase()];\n return typeof value === 'string' ? value : undefined;\n}\n\nexport type {\n RequestLogger,\n RequestLoggerOptions,\n RequestLogSnapshot,\n ParsedError,\n StructuredError,\n StructuredErrorInput,\n DrainPipelineOptions,\n PipelineDrainFn,\n};\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n createDrainPipeline,\n getRequestLogger,\n parseError,\n trace,\n createStructuredError,\n type RequestLogger,\n type RequestLoggerOptions,\n type ParsedError,\n type DrainPipelineOptions,\n type PipelineDrainFn,\n type StructuredError,\n type StructuredErrorInput,\n} from 'autotel';\nimport { createAdapterToolkit, createUseLogger, getHeader } from './core';\n\nexport interface NextRequestLike {\n method?: string;\n url?: string;\n headers?:\n | { get(name: string): string | null }\n | Record<string, string | undefined>;\n}\n\nexport interface NextWithAutotelOptions {\n spanName?: string | ((request?: NextRequestLike) => string);\n requestLoggerOptions?: RequestLoggerOptions;\n enrich?: (request?: NextRequestLike) => Record<string, unknown> | undefined;\n /** Emit one wide event automatically when the handler settles. Default `true`. */\n autoEmit?: boolean;\n}\n\nconst nextLoggerStorage = new AsyncLocalStorage<RequestLogger>();\n\nfunction enrichFromRequest(\n request?: NextRequestLike,\n): Record<string, unknown> | undefined {\n if (!request) return undefined;\n\n let route = '/';\n if (request.url) {\n try {\n route = new URL(request.url).pathname;\n } catch {\n route = request.url;\n }\n }\n const requestId = getHeader(request.headers, 'x-request-id');\n\n return {\n ...(request.method ? { 'http.request.method': request.method } : {}),\n ...(request.url ? { 'url.full': request.url } : {}),\n ...(route ? { 'http.route': route } : {}),\n ...(requestId ? { 'http.request.header.x-request-id': requestId } : {}),\n };\n}\n\nconst baseUseLogger = createUseLogger<NextRequestLike>({\n adapterName: 'next',\n enrich: enrichFromRequest,\n});\n\nexport function useLogger(\n request?: NextRequestLike,\n requestLoggerOptions?: RequestLoggerOptions,\n): RequestLogger {\n const logger = nextLoggerStorage.getStore();\n if (logger) return logger;\n return baseUseLogger(request, requestLoggerOptions);\n}\n\nexport function withAutotel<TArgs extends unknown[], TReturn>(\n handler: (...args: TArgs) => TReturn | Promise<TReturn>,\n options?: NextWithAutotelOptions,\n): (...args: TArgs) => Promise<TReturn> {\n return async (...args: TArgs): Promise<TReturn> => {\n const request = args[0] as NextRequestLike | undefined;\n const spanName =\n typeof options?.spanName === 'function'\n ? options.spanName(request)\n : (options?.spanName ?? 'next.request');\n\n const wrapped = trace(\n { name: spanName },\n (ctx) => async (...innerArgs: TArgs) => {\n const innerRequest = innerArgs[0] as NextRequestLike | undefined;\n const log = getRequestLogger(ctx, options?.requestLoggerOptions);\n const auto = enrichFromRequest(innerRequest);\n if (auto && Object.keys(auto).length > 0) {\n log.set(auto);\n }\n const custom = options?.enrich?.(innerRequest);\n if (custom && Object.keys(custom).length > 0) {\n log.set(custom);\n }\n try {\n return await nextLoggerStorage.run(log, async () =>\n handler(...innerArgs),\n );\n } finally {\n if (options?.autoEmit !== false) {\n log.emitNow();\n }\n }\n },\n );\n return await wrapped(...args);\n };\n}\n\nexport function createNextAdapter(options?: NextWithAutotelOptions) {\n return {\n withAutotel: <TArgs extends unknown[], TReturn>(\n handler: (...args: TArgs) => TReturn | Promise<TReturn>,\n ) => withAutotel(handler, options),\n useLogger: (\n request?: NextRequestLike,\n requestLoggerOptions?: RequestLoggerOptions,\n ): RequestLogger => useLogger(request, requestLoggerOptions),\n parseError: (error: unknown): ParsedError => parseError(error),\n createStructuredError: (\n input: StructuredErrorInput,\n ): StructuredError => createStructuredError(input),\n createDrainPipeline: <T = unknown>(\n drainOptions?: DrainPipelineOptions<T>,\n ): ((batchDrain: (batch: T[]) => void | Promise<void>) => PipelineDrainFn<T>) =>\n createDrainPipeline(drainOptions),\n };\n}\n\nexport const nextToolkit = createAdapterToolkit<NextRequestLike>({\n adapterName: 'next',\n enrich: enrichFromRequest,\n});\n\nexport { parseError, createDrainPipeline, createStructuredError };\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n getRequestLogger,\n trace,\n type RequestLogger,\n type RequestLoggerOptions,\n} from 'autotel';\nimport { createAdapterToolkit, createUseLogger } from './core';\n\nexport interface NitroEventLike {\n method?: string;\n path?: string;\n context?: Record<string, unknown>;\n}\n\nexport interface NitroWithAutotelOptions {\n spanName?: string | ((event: NitroEventLike) => string);\n requestLoggerOptions?: RequestLoggerOptions;\n enrich?: (event: NitroEventLike) => Record<string, unknown> | undefined;\n /** Emit one wide event automatically when the handler settles. Default `true`. */\n autoEmit?: boolean;\n}\n\nfunction enrichFromEvent(\n event?: NitroEventLike,\n): Record<string, unknown> | undefined {\n if (!event) return undefined;\n\n return {\n ...(event.method ? { 'http.request.method': event.method } : {}),\n ...(event.path ? { 'http.route': event.path } : {}),\n ...(typeof event.context?.requestId === 'string'\n ? { 'http.request.id': event.context.requestId }\n : {}),\n };\n}\n\nconst baseUseLogger = createUseLogger<NitroEventLike>({\n adapterName: 'nitro',\n enrich: enrichFromEvent,\n});\nconst nitroLoggerStorage = new AsyncLocalStorage<RequestLogger>();\n\nexport function useLogger(\n event?: NitroEventLike,\n serviceOrOptions?: string | RequestLoggerOptions,\n): RequestLogger {\n const stored = nitroLoggerStorage.getStore();\n const logger = stored ??\n (\n typeof serviceOrOptions === 'string'\n ? baseUseLogger(event)\n : baseUseLogger(event, serviceOrOptions)\n );\n\n if (typeof serviceOrOptions === 'string' && serviceOrOptions.length > 0) {\n logger.set({ service: serviceOrOptions });\n }\n\n return logger;\n}\n\nexport function withAutotelEventHandler<TEvent extends NitroEventLike, TReturn>(\n handler: (event: TEvent) => TReturn | Promise<TReturn>,\n options?: NitroWithAutotelOptions,\n): (event: TEvent) => Promise<TReturn> {\n return async (event: TEvent): Promise<TReturn> => {\n const spanName =\n typeof options?.spanName === 'function'\n ? options.spanName(event)\n : (options?.spanName ?? `nitro.${event.method ?? 'request'}`);\n\n const wrapped = trace({ name: spanName }, (ctx) => async (innerEvent: TEvent) => {\n const log = getRequestLogger(ctx, options?.requestLoggerOptions);\n const auto = enrichFromEvent(innerEvent);\n if (auto && Object.keys(auto).length > 0) {\n log.set(auto);\n }\n const custom = options?.enrich?.(innerEvent);\n if (custom && Object.keys(custom).length > 0) {\n log.set(custom);\n }\n try {\n return await nitroLoggerStorage.run(log, async () =>\n handler(innerEvent),\n );\n } finally {\n if (options?.autoEmit !== false) {\n log.emitNow();\n }\n }\n });\n\n return await wrapped(event);\n };\n}\n\nexport function createNitroAdapter(options?: NitroWithAutotelOptions) {\n const toolkit = createAdapterToolkit<NitroEventLike>({\n adapterName: 'nitro',\n enrich: (event) => ({\n ...enrichFromEvent(event),\n ...(options?.enrich?.(event) ?? {}),\n }),\n });\n\n return {\n withAutotelEventHandler: <TEvent extends NitroEventLike, TReturn>(\n handler: (event: TEvent) => TReturn | Promise<TReturn>,\n ) => withAutotelEventHandler(handler, options),\n useLogger,\n parseError: toolkit.parseError,\n createStructuredError: toolkit.createStructuredError,\n createDrainPipeline: toolkit.createDrainPipeline,\n };\n}\n\nexport const nitroToolkit = createAdapterToolkit<NitroEventLike>({\n adapterName: 'nitro',\n enrich: enrichFromEvent,\n});\n","import {\n createDrainPipeline,\n createStructuredError,\n getRequestLogger,\n parseError,\n trace,\n type DrainPipelineOptions,\n type ParsedError,\n type PipelineDrainFn,\n type RequestLogger,\n type RequestLoggerOptions,\n type StructuredError,\n type StructuredErrorInput,\n} from 'autotel';\nimport { createAdapterToolkit, createUseLogger, getHeader } from './core';\n\nexport interface CloudflareRequestLike {\n method?: string;\n url?: string;\n headers?:\n | { get(name: string): string | null }\n | Record<string, string | undefined>;\n cf?: Record<string, unknown>;\n}\n\nexport interface CloudflareExecutionContextLike {\n waitUntil?: (promise: Promise<unknown>) => void;\n passThroughOnException?: () => void;\n}\n\nexport interface CloudflareWithAutotelOptions<TEnv = unknown> {\n spanName?: string | ((request: CloudflareRequestLike, env: TEnv) => string);\n requestLoggerOptions?: RequestLoggerOptions;\n enrich?: (\n request: CloudflareRequestLike,\n env: TEnv,\n ctx: CloudflareExecutionContextLike,\n ) => Record<string, unknown> | undefined;\n /** Emit one wide event automatically when the handler settles. Default `true`. */\n autoEmit?: boolean;\n}\n\nconst requestLoggers = new WeakMap<object, RequestLogger>();\n\nfunction enrichFromRequest(\n request?: CloudflareRequestLike,\n): Record<string, unknown> | undefined {\n if (!request) return undefined;\n\n let route = '/';\n if (request.url) {\n try {\n route = new URL(request.url).pathname;\n } catch {\n route = request.url;\n }\n }\n\n const requestId =\n getHeader(request.headers, 'x-request-id') ??\n getHeader(request.headers, 'cf-ray');\n\n return {\n ...(request.method ? { 'http.request.method': request.method } : {}),\n ...(request.url ? { 'url.full': request.url } : {}),\n ...(route ? { 'http.route': route } : {}),\n ...(requestId ? { 'http.request.id': requestId } : {}),\n ...(request.cf?.country ? { 'cloudflare.country': request.cf.country } : {}),\n ...(request.cf?.colo ? { 'cloudflare.colo': request.cf.colo } : {}),\n ...(request.cf?.city ? { 'cloudflare.city': request.cf.city } : {}),\n };\n}\n\nconst baseUseLogger = createUseLogger<CloudflareRequestLike>({\n adapterName: 'cloudflare',\n enrich: enrichFromRequest,\n});\n\nexport function useLogger(\n request?: CloudflareRequestLike,\n requestLoggerOptions?: RequestLoggerOptions,\n): RequestLogger {\n if (request) {\n const existing = requestLoggers.get(request as object);\n if (existing) return existing;\n }\n return baseUseLogger(request, requestLoggerOptions);\n}\n\nexport function withAutotelFetch<\n TEnv,\n TRequest extends CloudflareRequestLike,\n TContext extends CloudflareExecutionContextLike,\n TReturn,\n>(\n handler: (\n request: TRequest,\n env: TEnv,\n ctx: TContext,\n ) => TReturn | Promise<TReturn>,\n options?: CloudflareWithAutotelOptions<TEnv>,\n): (\n request: TRequest,\n env: TEnv,\n ctx: TContext,\n) => Promise<TReturn> {\n return async (\n request: TRequest,\n env: TEnv,\n executionContext: TContext,\n ): Promise<TReturn> => {\n const spanName =\n typeof options?.spanName === 'function'\n ? options.spanName(request, env)\n : (options?.spanName ?? `cloudflare.${request.method ?? 'request'}`);\n\n const wrapped = trace(\n { name: spanName },\n (ctx) => async (\n innerRequest: TRequest,\n innerEnv: TEnv,\n innerExecutionContext: TContext,\n ) => {\n const log = getRequestLogger(ctx, options?.requestLoggerOptions);\n const auto = enrichFromRequest(innerRequest);\n if (auto && Object.keys(auto).length > 0) {\n log.set(auto);\n }\n const custom = options?.enrich?.(\n innerRequest,\n innerEnv,\n innerExecutionContext,\n );\n if (custom && Object.keys(custom).length > 0) {\n log.set(custom);\n }\n\n requestLoggers.set(innerRequest as object, log);\n try {\n return await handler(innerRequest, innerEnv, innerExecutionContext);\n } finally {\n if (options?.autoEmit !== false) {\n log.emitNow();\n }\n requestLoggers.delete(innerRequest as object);\n }\n },\n );\n\n return await wrapped(request, env, executionContext);\n };\n}\n\nexport function createCloudflareAdapter<TEnv = unknown>(\n options?: CloudflareWithAutotelOptions<TEnv>,\n) {\n return {\n withAutotelFetch: <\n TRequest extends CloudflareRequestLike,\n TContext extends CloudflareExecutionContextLike,\n TReturn,\n >(\n handler: (\n request: TRequest,\n env: TEnv,\n ctx: TContext,\n ) => TReturn | Promise<TReturn>,\n ) => withAutotelFetch(handler, options),\n useLogger,\n parseError: (error: unknown): ParsedError => parseError(error),\n createStructuredError: (\n input: StructuredErrorInput,\n ): StructuredError => createStructuredError(input),\n createDrainPipeline: <T = unknown>(\n drainOptions?: DrainPipelineOptions<T>,\n ): ((batchDrain: (batch: T[]) => void | Promise<void>) => PipelineDrainFn<T>) =>\n createDrainPipeline(drainOptions),\n };\n}\n\nexport const cloudflareToolkit = createAdapterToolkit<CloudflareRequestLike>({\n adapterName: 'cloudflare',\n enrich: enrichFromRequest,\n});\n\nexport { parseError, createDrainPipeline, createStructuredError };\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n createDrainPipeline,\n createStructuredError,\n parseError,\n type DrainPipelineOptions,\n type ParsedError,\n type PipelineDrainFn,\n type RequestLogger,\n type RequestLoggerOptions,\n type StructuredError,\n type StructuredErrorInput,\n} from 'autotel';\nimport {\n createAdapterToolkit,\n createRequestRunner,\n createUseLogger,\n} from './core';\n\nexport interface ExpressRequestLike {\n method?: string;\n originalUrl?: string;\n url?: string;\n path?: string;\n route?: { path?: string };\n headers?: Record<string, string | string[] | undefined>;\n}\n\nexport interface ExpressResponseLike {\n statusCode?: number;\n}\n\nexport type ExpressNext = (err?: unknown) => void;\n\nexport interface ExpressWithAutotelOptions {\n spanName?: string | ((request: ExpressRequestLike) => string);\n requestLoggerOptions?: RequestLoggerOptions;\n enrich?: (request: ExpressRequestLike) => Record<string, unknown> | undefined;\n /** Emit one wide event automatically when the handler settles. Default `true`. */\n autoEmit?: boolean;\n}\n\nconst expressLoggerStorage = new AsyncLocalStorage<RequestLogger>();\n\nfunction headerValue(\n headers: ExpressRequestLike['headers'],\n name: string,\n): string | undefined {\n if (!headers) return undefined;\n const value = headers[name] ?? headers[name.toLowerCase()];\n if (Array.isArray(value)) return value[0];\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction enrichFromRequest(\n request?: ExpressRequestLike,\n): Record<string, unknown> | undefined {\n if (!request) return undefined;\n\n const url = request.originalUrl ?? request.url;\n const route = request.route?.path ?? request.path ?? url;\n const requestId = headerValue(request.headers, 'x-request-id');\n\n return {\n ...(request.method ? { 'http.request.method': request.method } : {}),\n ...(url ? { 'url.full': url } : {}),\n ...(route ? { 'http.route': route } : {}),\n ...(requestId ? { 'http.request.id': requestId } : {}),\n };\n}\n\nconst baseUseLogger = createUseLogger<ExpressRequestLike>({\n adapterName: 'express',\n enrich: enrichFromRequest,\n});\n\nexport function useLogger(\n request?: ExpressRequestLike,\n requestLoggerOptions?: RequestLoggerOptions,\n): RequestLogger {\n const stored = expressLoggerStorage.getStore();\n if (stored) return stored;\n return baseUseLogger(request, requestLoggerOptions);\n}\n\nconst runRequest = createRequestRunner(expressLoggerStorage);\n\n/**\n * Wrap an Express route handler. Each request opens a span, gets a\n * request-scoped logger (via `useLogger(req)`), and emits one wide event when\n * the handler settles. Thrown errors are recorded and forwarded to `next`.\n */\nexport function withAutotel<\n TReq extends ExpressRequestLike,\n TRes extends ExpressResponseLike,\n TReturn,\n>(\n handler: (req: TReq, res: TRes, next?: ExpressNext) => TReturn | Promise<TReturn>,\n options?: ExpressWithAutotelOptions,\n): (req: TReq, res: TRes, next?: ExpressNext) => Promise<TReturn | undefined> {\n return async (\n req: TReq,\n res: TRes,\n next?: ExpressNext,\n ): Promise<TReturn | undefined> => {\n const spanName =\n typeof options?.spanName === 'function'\n ? options.spanName(req)\n : (options?.spanName ?? `express.${req.method ?? 'request'}`);\n\n try {\n return await runRequest<TReturn>(\n spanName,\n (log) => {\n const auto = enrichFromRequest(req);\n if (auto && Object.keys(auto).length > 0) log.set(auto);\n const custom = options?.enrich?.(req);\n if (custom && Object.keys(custom).length > 0) log.set(custom);\n },\n () => handler(req, res, next),\n {\n requestLoggerOptions: options?.requestLoggerOptions,\n autoEmit: options?.autoEmit,\n finalize: () =>\n res.statusCode\n ? { 'http.response.status_code': res.statusCode }\n : undefined,\n },\n );\n } catch (error) {\n if (typeof next === 'function') {\n next(error);\n return undefined;\n }\n throw error;\n }\n };\n}\n\nexport function createExpressAdapter(options?: ExpressWithAutotelOptions) {\n return {\n withAutotel: <\n TReq extends ExpressRequestLike,\n TRes extends ExpressResponseLike,\n TReturn,\n >(\n handler: (\n req: TReq,\n res: TRes,\n next?: ExpressNext,\n ) => TReturn | Promise<TReturn>,\n ) => withAutotel(handler, options),\n useLogger,\n parseError: (error: unknown): ParsedError => parseError(error),\n createStructuredError: (input: StructuredErrorInput): StructuredError =>\n createStructuredError(input),\n createDrainPipeline: <T = unknown>(\n drainOptions?: DrainPipelineOptions<T>,\n ): ((batchDrain: (batch: T[]) => void | Promise<void>) => PipelineDrainFn<T>) =>\n createDrainPipeline(drainOptions),\n };\n}\n\nexport const expressToolkit = createAdapterToolkit<ExpressRequestLike>({\n adapterName: 'express',\n enrich: enrichFromRequest,\n});\n\nexport { parseError, createDrainPipeline, createStructuredError };\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n createDrainPipeline,\n createStructuredError,\n parseError,\n type DrainPipelineOptions,\n type ParsedError,\n type PipelineDrainFn,\n type RequestLogger,\n type RequestLoggerOptions,\n type StructuredError,\n type StructuredErrorInput,\n} from 'autotel';\nimport {\n createAdapterToolkit,\n createRequestRunner,\n createUseLogger,\n} from './core';\n\nexport interface FastifyRequestLike {\n method?: string;\n url?: string;\n routeOptions?: { url?: string };\n routerPath?: string;\n id?: string;\n headers?: Record<string, string | string[] | undefined>;\n}\n\nexport interface FastifyReplyLike {\n statusCode?: number;\n}\n\nexport interface FastifyWithAutotelOptions {\n spanName?: string | ((request: FastifyRequestLike) => string);\n requestLoggerOptions?: RequestLoggerOptions;\n enrich?: (request: FastifyRequestLike) => Record<string, unknown> | undefined;\n /** Emit one wide event automatically when the handler settles. Default `true`. */\n autoEmit?: boolean;\n}\n\nconst fastifyLoggerStorage = new AsyncLocalStorage<RequestLogger>();\n\nfunction headerValue(\n headers: FastifyRequestLike['headers'],\n name: string,\n): string | undefined {\n if (!headers) return undefined;\n const value = headers[name] ?? headers[name.toLowerCase()];\n if (Array.isArray(value)) return value[0];\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction enrichFromRequest(\n request?: FastifyRequestLike,\n): Record<string, unknown> | undefined {\n if (!request) return undefined;\n\n const route = request.routeOptions?.url ?? request.routerPath ?? request.url;\n const requestId = request.id ?? headerValue(request.headers, 'x-request-id');\n\n return {\n ...(request.method ? { 'http.request.method': request.method } : {}),\n ...(request.url ? { 'url.full': request.url } : {}),\n ...(route ? { 'http.route': route } : {}),\n ...(requestId ? { 'http.request.id': requestId } : {}),\n };\n}\n\nconst baseUseLogger = createUseLogger<FastifyRequestLike>({\n adapterName: 'fastify',\n enrich: enrichFromRequest,\n});\n\nexport function useLogger(\n request?: FastifyRequestLike,\n requestLoggerOptions?: RequestLoggerOptions,\n): RequestLogger {\n const stored = fastifyLoggerStorage.getStore();\n if (stored) return stored;\n return baseUseLogger(request, requestLoggerOptions);\n}\n\nconst runRequest = createRequestRunner(fastifyLoggerStorage);\n\n/**\n * Wrap a Fastify route handler. Each request opens a span, gets a\n * request-scoped logger (via `useLogger(request)`), and emits one wide event\n * when the handler settles. Thrown errors are recorded, then rethrown for\n * Fastify's error handling.\n */\nexport function withAutotel<\n TReq extends FastifyRequestLike,\n TRes extends FastifyReplyLike,\n TReturn,\n>(\n handler: (request: TReq, reply: TRes) => TReturn | Promise<TReturn>,\n options?: FastifyWithAutotelOptions,\n): (request: TReq, reply: TRes) => Promise<TReturn> {\n return (request: TReq, reply: TRes): Promise<TReturn> => {\n const spanName =\n typeof options?.spanName === 'function'\n ? options.spanName(request)\n : (options?.spanName ?? `fastify.${request.method ?? 'request'}`);\n\n return runRequest<TReturn>(\n spanName,\n (log) => {\n const auto = enrichFromRequest(request);\n if (auto && Object.keys(auto).length > 0) log.set(auto);\n const custom = options?.enrich?.(request);\n if (custom && Object.keys(custom).length > 0) log.set(custom);\n },\n () => handler(request, reply),\n {\n requestLoggerOptions: options?.requestLoggerOptions,\n autoEmit: options?.autoEmit,\n finalize: () =>\n reply.statusCode\n ? { 'http.response.status_code': reply.statusCode }\n : undefined,\n },\n );\n };\n}\n\nexport function createFastifyAdapter(options?: FastifyWithAutotelOptions) {\n return {\n withAutotel: <\n TReq extends FastifyRequestLike,\n TRes extends FastifyReplyLike,\n TReturn,\n >(\n handler: (request: TReq, reply: TRes) => TReturn | Promise<TReturn>,\n ) => withAutotel(handler, options),\n useLogger,\n parseError: (error: unknown): ParsedError => parseError(error),\n createStructuredError: (input: StructuredErrorInput): StructuredError =>\n createStructuredError(input),\n createDrainPipeline: <T = unknown>(\n drainOptions?: DrainPipelineOptions<T>,\n ): ((batchDrain: (batch: T[]) => void | Promise<void>) => PipelineDrainFn<T>) =>\n createDrainPipeline(drainOptions),\n };\n}\n\nexport const fastifyToolkit = createAdapterToolkit<FastifyRequestLike>({\n adapterName: 'fastify',\n enrich: enrichFromRequest,\n});\n\nexport { parseError, createDrainPipeline, createStructuredError };\n","import type { Context } from 'hono';\nimport { createUseLogger, createAdapterToolkit } from './core';\n\nexport const useLogger = createUseLogger<Context>({\n adapterName: 'hono',\n enrich: (c) => ({\n 'http.request.method': c.req.method,\n 'url.full': c.req.url,\n 'http.route': c.req.path,\n }),\n});\n\nexport const honoToolkit = createAdapterToolkit<Context>({\n adapterName: 'hono',\n enrich: (c) => ({\n 'http.request.method': c.req.method,\n 'url.full': c.req.url,\n 'http.route': c.req.path,\n }),\n});\n","import { createUseLogger, createAdapterToolkit } from './core';\n\nexport const useLogger = createUseLogger<{\n pathname?: string;\n method?: string;\n}>({\n adapterName: 'tanstack',\n enrich: (ctx) => ({\n ...(ctx.method ? { 'http.request.method': ctx.method } : {}),\n ...(ctx.pathname ? { 'http.route': ctx.pathname } : {}),\n }),\n});\n\nexport const tanstackToolkit = createAdapterToolkit<{\n pathname?: string;\n method?: string;\n}>({\n adapterName: 'tanstack',\n enrich: (ctx) => ({\n ...(ctx.method ? { 'http.request.method': ctx.method } : {}),\n ...(ctx.pathname ? { 'http.route': ctx.pathname } : {}),\n }),\n});\n"]}
package/dist/index.d.cts CHANGED
@@ -1,8 +1,11 @@
1
- export { AdapterToolkit, AdapterUseLoggerOptions, ConfigField, HeadersLike, createAdapterToolkit, createUseLogger, getHeader, resolveAdapterConfig, shouldProbeRuntime } from './core.cjs';
1
+ export { AdapterToolkit, AdapterUseLoggerOptions, ConfigField, HeadersLike, RequestRunnerOptions, createAdapterToolkit, createRequestRunner, createUseLogger, getHeader, resolveAdapterConfig, shouldProbeRuntime } from './core.cjs';
2
2
  export { createNextAdapter, withAutotel } from './next.cjs';
3
3
  export { createNitroAdapter, withAutotelEventHandler } from './nitro.cjs';
4
4
  export { createCloudflareAdapter, withAutotelFetch } from './cloudflare.cjs';
5
+ export { createExpressAdapter, withAutotel as withAutotelExpress } from './express.cjs';
6
+ export { createFastifyAdapter, withAutotel as withAutotelFastify } from './fastify.cjs';
5
7
  export { honoToolkit } from './hono.cjs';
6
8
  export { tanstackToolkit } from './tanstack.cjs';
7
9
  export { DrainPipelineOptions, ParsedError, PipelineDrainFn, RequestLogSnapshot, RequestLogger, RequestLoggerOptions, StructuredError, StructuredErrorInput } from 'autotel';
10
+ import 'node:async_hooks';
8
11
  import 'hono';
package/dist/index.d.ts CHANGED
@@ -1,8 +1,11 @@
1
- export { AdapterToolkit, AdapterUseLoggerOptions, ConfigField, HeadersLike, createAdapterToolkit, createUseLogger, getHeader, resolveAdapterConfig, shouldProbeRuntime } from './core.js';
1
+ export { AdapterToolkit, AdapterUseLoggerOptions, ConfigField, HeadersLike, RequestRunnerOptions, createAdapterToolkit, createRequestRunner, createUseLogger, getHeader, resolveAdapterConfig, shouldProbeRuntime } from './core.js';
2
2
  export { createNextAdapter, withAutotel } from './next.js';
3
3
  export { createNitroAdapter, withAutotelEventHandler } from './nitro.js';
4
4
  export { createCloudflareAdapter, withAutotelFetch } from './cloudflare.js';
5
+ export { createExpressAdapter, withAutotel as withAutotelExpress } from './express.js';
6
+ export { createFastifyAdapter, withAutotel as withAutotelFastify } from './fastify.js';
5
7
  export { honoToolkit } from './hono.js';
6
8
  export { tanstackToolkit } from './tanstack.js';
7
9
  export { DrainPipelineOptions, ParsedError, PipelineDrainFn, RequestLogSnapshot, RequestLogger, RequestLoggerOptions, StructuredError, StructuredErrorInput } from 'autotel';
10
+ import 'node:async_hooks';
8
11
  import 'hono';
package/dist/index.js CHANGED
@@ -1,8 +1,10 @@
1
- export { honoToolkit } from './chunk-UUDK5U3L.js';
2
- export { tanstackToolkit } from './chunk-JC3TNPQD.js';
3
- export { createNextAdapter, withAutotel } from './chunk-GPWONOFN.js';
4
- export { createNitroAdapter, withAutotelEventHandler } from './chunk-AD3QBS5J.js';
5
- export { createCloudflareAdapter, withAutotelFetch } from './chunk-CITNYQ2G.js';
6
- export { createAdapterToolkit, createUseLogger, getHeader, resolveAdapterConfig, shouldProbeRuntime } from './chunk-GBSB7IX7.js';
1
+ export { createFastifyAdapter, withAutotel as withAutotelFastify } from './chunk-6TOW47TB.js';
2
+ export { honoToolkit } from './chunk-JH5ZTTLF.js';
3
+ export { tanstackToolkit } from './chunk-U3U4WH42.js';
4
+ export { createNextAdapter, withAutotel } from './chunk-HTZFHBTN.js';
5
+ export { createNitroAdapter, withAutotelEventHandler } from './chunk-FAHH33UI.js';
6
+ export { createCloudflareAdapter, withAutotelFetch } from './chunk-VJZDW2DS.js';
7
+ export { createExpressAdapter, withAutotel as withAutotelExpress } from './chunk-2YPL66HM.js';
8
+ export { createAdapterToolkit, createRequestRunner, createUseLogger, getHeader, resolveAdapterConfig, shouldProbeRuntime } from './chunk-DJ2OU3S6.js';
7
9
  //# sourceMappingURL=index.js.map
8
10
  //# sourceMappingURL=index.js.map
package/dist/next.cjs CHANGED
@@ -87,7 +87,16 @@ function withAutotel(handler, options) {
87
87
  if (custom && Object.keys(custom).length > 0) {
88
88
  log.set(custom);
89
89
  }
90
- return await nextLoggerStorage.run(log, async () => handler(...innerArgs));
90
+ try {
91
+ return await nextLoggerStorage.run(
92
+ log,
93
+ async () => handler(...innerArgs)
94
+ );
95
+ } finally {
96
+ if (options?.autoEmit !== false) {
97
+ log.emitNow();
98
+ }
99
+ }
91
100
  }
92
101
  );
93
102
  return await wrapped(...args);