autotel 2.22.0 → 2.23.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 (110) hide show
  1. package/README.md +112 -6
  2. package/dist/auto.cjs +3 -3
  3. package/dist/auto.js +2 -2
  4. package/dist/{chunk-EWH2542B.js → chunk-3AMR5XLZ.js} +3 -3
  5. package/dist/{chunk-EWH2542B.js.map → chunk-3AMR5XLZ.js.map} +1 -1
  6. package/dist/chunk-3QXBFGKP.js +344 -0
  7. package/dist/chunk-3QXBFGKP.js.map +1 -0
  8. package/dist/{chunk-VQFF2WMP.cjs → chunk-3ZFDJJWZ.cjs} +37 -29
  9. package/dist/chunk-3ZFDJJWZ.cjs.map +1 -0
  10. package/dist/{chunk-CQC6RVLR.cjs → chunk-4RZ4JUBY.cjs} +5 -5
  11. package/dist/{chunk-CQC6RVLR.cjs.map → chunk-4RZ4JUBY.cjs.map} +1 -1
  12. package/dist/{chunk-PAVYKPCQ.js → chunk-5XUEHX7J.js} +3 -3
  13. package/dist/{chunk-PAVYKPCQ.js.map → chunk-5XUEHX7J.js.map} +1 -1
  14. package/dist/chunk-6S5RUKU3.cjs +347 -0
  15. package/dist/chunk-6S5RUKU3.cjs.map +1 -0
  16. package/dist/{chunk-BS757SL2.js → chunk-724XLWR3.js} +9 -4
  17. package/dist/chunk-724XLWR3.js.map +1 -0
  18. package/dist/chunk-7EQ4G4SI.cjs +146 -0
  19. package/dist/chunk-7EQ4G4SI.cjs.map +1 -0
  20. package/dist/{chunk-CQP5SQT4.cjs → chunk-AXFWWJF3.cjs} +7 -7
  21. package/dist/{chunk-CQP5SQT4.cjs.map → chunk-AXFWWJF3.cjs.map} +1 -1
  22. package/dist/{chunk-7NH625MS.cjs → chunk-BSZP4URK.cjs} +5 -5
  23. package/dist/{chunk-7NH625MS.cjs.map → chunk-BSZP4URK.cjs.map} +1 -1
  24. package/dist/{chunk-GZFH6P5U.js → chunk-GY4CRZSV.js} +14 -6
  25. package/dist/chunk-GY4CRZSV.js.map +1 -0
  26. package/dist/{chunk-QKUGUDXJ.cjs → chunk-HSEIUH7F.cjs} +10 -5
  27. package/dist/chunk-HSEIUH7F.cjs.map +1 -0
  28. package/dist/{chunk-DTW3WB7Z.js → chunk-IPKXURBW.js} +3 -3
  29. package/dist/{chunk-DTW3WB7Z.js.map → chunk-IPKXURBW.js.map} +1 -1
  30. package/dist/chunk-J7VGRIAJ.js +64 -0
  31. package/dist/chunk-J7VGRIAJ.js.map +1 -0
  32. package/dist/chunk-KFOHQK7X.js +144 -0
  33. package/dist/chunk-KFOHQK7X.js.map +1 -0
  34. package/dist/{chunk-4UYR46UP.cjs → chunk-MSUHW2I4.cjs} +13 -13
  35. package/dist/{chunk-4UYR46UP.cjs.map → chunk-MSUHW2I4.cjs.map} +1 -1
  36. package/dist/chunk-T4B5LB6E.cjs +66 -0
  37. package/dist/chunk-T4B5LB6E.cjs.map +1 -0
  38. package/dist/{chunk-QHT4MUED.js → chunk-WCIIFRGL.js} +3 -3
  39. package/dist/{chunk-QHT4MUED.js.map → chunk-WCIIFRGL.js.map} +1 -1
  40. package/dist/decorators.cjs +3 -3
  41. package/dist/decorators.js +3 -3
  42. package/dist/drain-pipeline.cjs +13 -0
  43. package/dist/drain-pipeline.cjs.map +1 -0
  44. package/dist/drain-pipeline.d.cts +37 -0
  45. package/dist/drain-pipeline.d.ts +37 -0
  46. package/dist/drain-pipeline.js +4 -0
  47. package/dist/drain-pipeline.js.map +1 -0
  48. package/dist/event.cjs +6 -6
  49. package/dist/event.js +3 -3
  50. package/dist/functional.cjs +10 -10
  51. package/dist/functional.js +3 -3
  52. package/dist/index.cjs +256 -41
  53. package/dist/index.cjs.map +1 -1
  54. package/dist/index.d.cts +72 -3
  55. package/dist/index.d.ts +72 -3
  56. package/dist/index.js +210 -11
  57. package/dist/index.js.map +1 -1
  58. package/dist/{init-BMiXSJNM.d.cts → init-BC5aN8bh.d.cts} +18 -0
  59. package/dist/{init-ByRbNTRo.d.ts → init-_FG4IbhF.d.ts} +18 -0
  60. package/dist/instrumentation.cjs +9 -9
  61. package/dist/instrumentation.js +2 -2
  62. package/dist/messaging.cjs +7 -7
  63. package/dist/messaging.js +4 -4
  64. package/dist/parse-error.cjs +13 -0
  65. package/dist/parse-error.cjs.map +1 -0
  66. package/dist/parse-error.d.cts +13 -0
  67. package/dist/parse-error.d.ts +13 -0
  68. package/dist/parse-error.js +4 -0
  69. package/dist/parse-error.js.map +1 -0
  70. package/dist/processors.cjs +2 -2
  71. package/dist/processors.d.cts +40 -4
  72. package/dist/processors.d.ts +40 -4
  73. package/dist/processors.js +1 -1
  74. package/dist/semantic-helpers.cjs +8 -8
  75. package/dist/semantic-helpers.js +4 -4
  76. package/dist/webhook.cjs +4 -4
  77. package/dist/webhook.js +3 -3
  78. package/dist/workflow-distributed.cjs +5 -5
  79. package/dist/workflow-distributed.js +3 -3
  80. package/dist/workflow.cjs +8 -8
  81. package/dist/workflow.js +4 -4
  82. package/dist/yaml-config.d.cts +2 -1
  83. package/dist/yaml-config.d.ts +2 -1
  84. package/package.json +11 -1
  85. package/src/drain-pipeline.test.ts +68 -0
  86. package/src/drain-pipeline.ts +199 -0
  87. package/src/flatten-attributes.test.ts +76 -0
  88. package/src/flatten-attributes.ts +80 -0
  89. package/src/functional.test.ts +63 -0
  90. package/src/functional.ts +11 -3
  91. package/src/index.ts +33 -0
  92. package/src/init.ts +22 -0
  93. package/src/parse-error.test.ts +73 -0
  94. package/src/parse-error.ts +112 -0
  95. package/src/pretty-log-formatter.test.ts +123 -0
  96. package/src/pretty-log-formatter.ts +210 -0
  97. package/src/processors/canonical-log-line-processor.test.ts +81 -25
  98. package/src/processors/canonical-log-line-processor.ts +130 -42
  99. package/src/request-logger.test.ts +124 -0
  100. package/src/request-logger.ts +140 -0
  101. package/src/structured-error.test.ts +76 -0
  102. package/src/structured-error.ts +86 -0
  103. package/dist/chunk-2RQDNGV3.js +0 -126
  104. package/dist/chunk-2RQDNGV3.js.map +0 -1
  105. package/dist/chunk-BS757SL2.js.map +0 -1
  106. package/dist/chunk-GZFH6P5U.js.map +0 -1
  107. package/dist/chunk-ONK2Y22L.cjs +0 -128
  108. package/dist/chunk-ONK2Y22L.cjs.map +0 -1
  109. package/dist/chunk-QKUGUDXJ.cjs.map +0 -1
  110. package/dist/chunk-VQFF2WMP.cjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,31 +1,33 @@
1
1
  'use strict';
2
2
 
3
- var chunk7NH625MS_cjs = require('./chunk-7NH625MS.cjs');
3
+ var chunk7EQ4G4SI_cjs = require('./chunk-7EQ4G4SI.cjs');
4
+ var chunkBSZP4URK_cjs = require('./chunk-BSZP4URK.cjs');
4
5
  var chunkXRBP4RYL_cjs = require('./chunk-XRBP4RYL.cjs');
5
6
  var chunk2ZKEORFN_cjs = require('./chunk-2ZKEORFN.cjs');
6
7
  var chunkESMHTKLJ_cjs = require('./chunk-ESMHTKLJ.cjs');
7
- var chunkCQC6RVLR_cjs = require('./chunk-CQC6RVLR.cjs');
8
+ var chunkT4B5LB6E_cjs = require('./chunk-T4B5LB6E.cjs');
9
+ var chunk4RZ4JUBY_cjs = require('./chunk-4RZ4JUBY.cjs');
8
10
  var chunkINJD3G4K_cjs = require('./chunk-INJD3G4K.cjs');
9
11
  var chunkTC5ZPWM4_cjs = require('./chunk-TC5ZPWM4.cjs');
10
12
  require('./chunk-YTXEZ4SD.cjs');
11
13
  var chunkWJH6IYU2_cjs = require('./chunk-WJH6IYU2.cjs');
12
- var chunkCQP5SQT4_cjs = require('./chunk-CQP5SQT4.cjs');
13
- var chunkVQFF2WMP_cjs = require('./chunk-VQFF2WMP.cjs');
14
+ var chunkAXFWWJF3_cjs = require('./chunk-AXFWWJF3.cjs');
15
+ var chunk3ZFDJJWZ_cjs = require('./chunk-3ZFDJJWZ.cjs');
14
16
  var chunkW4EUTSB2_cjs = require('./chunk-W4EUTSB2.cjs');
15
17
  var chunkGML3FBOT_cjs = require('./chunk-GML3FBOT.cjs');
16
- var chunk4UYR46UP_cjs = require('./chunk-4UYR46UP.cjs');
18
+ var chunkMSUHW2I4_cjs = require('./chunk-MSUHW2I4.cjs');
17
19
  require('./chunk-NZ72VDNY.cjs');
18
20
  require('./chunk-UY3UYPBZ.cjs');
19
21
  var chunkD5LMF53P_cjs = require('./chunk-D5LMF53P.cjs');
20
22
  var chunkXRKAL7WJ_cjs = require('./chunk-XRKAL7WJ.cjs');
21
- var chunkQKUGUDXJ_cjs = require('./chunk-QKUGUDXJ.cjs');
23
+ var chunkHSEIUH7F_cjs = require('./chunk-HSEIUH7F.cjs');
22
24
  require('./chunk-6YIDHH2S.cjs');
23
25
  require('./chunk-GVLK7YUU.cjs');
24
26
  var chunkZNMBW67B_cjs = require('./chunk-ZNMBW67B.cjs');
25
27
  var chunkIOYFAFHJ_cjs = require('./chunk-IOYFAFHJ.cjs');
26
28
  var chunkELW34S4C_cjs = require('./chunk-ELW34S4C.cjs');
27
29
  require('./chunk-CU6IDACR.cjs');
28
- require('./chunk-ONK2Y22L.cjs');
30
+ var chunk6S5RUKU3_cjs = require('./chunk-6S5RUKU3.cjs');
29
31
  require('./chunk-YS6C2YJE.cjs');
30
32
  var chunkBGVKKL2N_cjs = require('./chunk-BGVKKL2N.cjs');
31
33
  require('./chunk-AZ24DJAG.cjs');
@@ -39,7 +41,7 @@ async function flush(options) {
39
41
  const timeout = options?.timeout ?? 2e3;
40
42
  const forShutdown = options?.forShutdown ?? false;
41
43
  const doFlush = async () => {
42
- const eventsQueue = chunkVQFF2WMP_cjs.getEventQueue();
44
+ const eventsQueue = chunk3ZFDJJWZ_cjs.getEventQueue();
43
45
  if (eventsQueue) {
44
46
  if (forShutdown) {
45
47
  await eventsQueue.shutdown();
@@ -47,7 +49,7 @@ async function flush(options) {
47
49
  await eventsQueue.flush();
48
50
  }
49
51
  }
50
- const sdk = chunkQKUGUDXJ_cjs.getSdk();
52
+ const sdk = chunkHSEIUH7F_cjs.getSdk();
51
53
  if (sdk) {
52
54
  try {
53
55
  const sdkAny = sdk;
@@ -81,7 +83,7 @@ async function flush(options) {
81
83
  if (timeoutHandle) {
82
84
  clearTimeout(timeoutHandle);
83
85
  }
84
- const logger = chunkQKUGUDXJ_cjs.getLogger();
86
+ const logger = chunkHSEIUH7F_cjs.getLogger();
85
87
  logger.error(
86
88
  {
87
89
  err: error instanceof Error ? error : new Error(String(error))
@@ -92,7 +94,7 @@ async function flush(options) {
92
94
  }
93
95
  }
94
96
  async function shutdown() {
95
- const logger = chunkQKUGUDXJ_cjs.getLogger();
97
+ const logger = chunkHSEIUH7F_cjs.getLogger();
96
98
  let shutdownError = null;
97
99
  try {
98
100
  await flush({ forShutdown: true });
@@ -107,7 +109,7 @@ async function shutdown() {
107
109
  );
108
110
  }
109
111
  try {
110
- const sdk = chunkQKUGUDXJ_cjs.getSdk();
112
+ const sdk = chunkHSEIUH7F_cjs.getSdk();
111
113
  if (sdk) {
112
114
  await sdk.shutdown();
113
115
  }
@@ -121,13 +123,13 @@ async function shutdown() {
121
123
  logger.error({ err }, "[autotel] SDK shutdown failed");
122
124
  }
123
125
  } finally {
124
- const eventsQueue = chunkVQFF2WMP_cjs.getEventQueue();
126
+ const eventsQueue = chunk3ZFDJJWZ_cjs.getEventQueue();
125
127
  if (eventsQueue && typeof eventsQueue.cleanup === "function") {
126
128
  eventsQueue.cleanup();
127
129
  }
128
- chunk4UYR46UP_cjs.resetEvents();
130
+ chunkMSUHW2I4_cjs.resetEvents();
129
131
  chunkTC5ZPWM4_cjs.resetMetrics();
130
- chunkVQFF2WMP_cjs.resetEventQueue();
132
+ chunk3ZFDJJWZ_cjs.resetEventQueue();
131
133
  }
132
134
  if (shutdownError) {
133
135
  throw shutdownError;
@@ -142,7 +144,7 @@ function registerShutdownHooks() {
142
144
  if (shuttingDown) return;
143
145
  shuttingDown = true;
144
146
  if (process.env.NODE_ENV !== "test") {
145
- chunkQKUGUDXJ_cjs.getLogger().info(
147
+ chunkHSEIUH7F_cjs.getLogger().info(
146
148
  {},
147
149
  `[autotel] Received ${signal}, flushing telemetry...`
148
150
  );
@@ -150,7 +152,7 @@ function registerShutdownHooks() {
150
152
  try {
151
153
  await shutdown();
152
154
  } catch (error) {
153
- chunkQKUGUDXJ_cjs.getLogger().error(
155
+ chunkHSEIUH7F_cjs.getLogger().error(
154
156
  {
155
157
  err: error instanceof Error ? error : void 0
156
158
  },
@@ -164,21 +166,220 @@ function registerShutdownHooks() {
164
166
  }
165
167
  registerShutdownHooks();
166
168
 
169
+ // src/flatten-attributes.ts
170
+ function toAttributeValue(value) {
171
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
172
+ return value;
173
+ }
174
+ if (Array.isArray(value)) {
175
+ if (value.every((v) => typeof v === "string") || value.every((v) => typeof v === "number") || value.every((v) => typeof v === "boolean")) {
176
+ return value;
177
+ }
178
+ try {
179
+ return JSON.stringify(value);
180
+ } catch {
181
+ return "<serialization-failed>";
182
+ }
183
+ }
184
+ if (value instanceof Date) {
185
+ return value.toISOString();
186
+ }
187
+ if (value instanceof Error) {
188
+ return value.message;
189
+ }
190
+ return void 0;
191
+ }
192
+ function flattenToAttributes(fields, prefix = "") {
193
+ const out = {};
194
+ const seen = /* @__PURE__ */ new WeakSet();
195
+ function flatten(obj, currentPrefix) {
196
+ for (const [key, value] of Object.entries(obj)) {
197
+ if (value == null) continue;
198
+ const nextKey = currentPrefix ? `${currentPrefix}.${key}` : key;
199
+ const attr = toAttributeValue(value);
200
+ if (attr !== void 0) {
201
+ out[nextKey] = attr;
202
+ continue;
203
+ }
204
+ if (typeof value === "object" && value.constructor === Object) {
205
+ if (seen.has(value)) {
206
+ out[nextKey] = "<circular-reference>";
207
+ continue;
208
+ }
209
+ seen.add(value);
210
+ flatten(value, nextKey);
211
+ continue;
212
+ }
213
+ try {
214
+ out[nextKey] = JSON.stringify(value);
215
+ } catch {
216
+ out[nextKey] = "<serialization-failed>";
217
+ }
218
+ }
219
+ }
220
+ flatten(fields, prefix);
221
+ return out;
222
+ }
223
+
224
+ // src/structured-error.ts
225
+ function createStructuredError(input) {
226
+ const error = new Error(input.message, {
227
+ cause: input.cause
228
+ });
229
+ error.name = input.name ?? "StructuredError";
230
+ if (input.why !== void 0) error.why = input.why;
231
+ if (input.fix !== void 0) error.fix = input.fix;
232
+ if (input.link !== void 0) error.link = input.link;
233
+ if (input.code !== void 0) error.code = input.code;
234
+ if (input.status !== void 0) error.status = input.status;
235
+ if (input.details !== void 0) error.details = input.details;
236
+ return error;
237
+ }
238
+ function getStructuredErrorAttributes(error) {
239
+ const structured = error;
240
+ const attributes = {
241
+ "error.type": error.name || "Error",
242
+ "error.message": error.message
243
+ };
244
+ if (error.stack) attributes["error.stack"] = error.stack;
245
+ if (structured.why) attributes["error.why"] = structured.why;
246
+ if (structured.fix) attributes["error.fix"] = structured.fix;
247
+ if (structured.link) attributes["error.link"] = structured.link;
248
+ if (structured.code !== void 0) {
249
+ attributes["error.code"] = typeof structured.code === "string" ? structured.code : String(structured.code);
250
+ }
251
+ if (structured.status !== void 0) {
252
+ attributes["error.status"] = structured.status;
253
+ }
254
+ if (structured.details) {
255
+ Object.assign(
256
+ attributes,
257
+ flattenToAttributes(structured.details, "error.details")
258
+ );
259
+ }
260
+ return attributes;
261
+ }
262
+ function recordStructuredError(ctx2, error) {
263
+ ctx2.recordException(error);
264
+ ctx2.setStatus({
265
+ code: api.SpanStatusCode.ERROR,
266
+ message: error.message
267
+ });
268
+ ctx2.setAttributes(getStructuredErrorAttributes(error));
269
+ }
270
+
271
+ // src/request-logger.ts
272
+ function resolveContext(ctx2) {
273
+ if (ctx2) return ctx2;
274
+ const span2 = api.trace.getActiveSpan();
275
+ if (!span2) {
276
+ throw new Error(
277
+ "[autotel] getRequestLogger() requires an active span. Wrap your handler with trace()."
278
+ );
279
+ }
280
+ return chunkW4EUTSB2_cjs.createTraceContext(span2);
281
+ }
282
+ function getRequestLogger(ctx2, options) {
283
+ const activeContext = resolveContext(ctx2);
284
+ let contextState = {};
285
+ const addLogEvent = (level, message, fields) => {
286
+ const attrs2 = fields ? flattenToAttributes(fields) : void 0;
287
+ activeContext.addEvent(`log.${level}`, {
288
+ message,
289
+ ...attrs2
290
+ });
291
+ };
292
+ return {
293
+ set(fields) {
294
+ contextState = {
295
+ ...contextState,
296
+ ...fields
297
+ };
298
+ activeContext.setAttributes(flattenToAttributes(fields));
299
+ },
300
+ info(message, fields) {
301
+ addLogEvent("info", message, fields);
302
+ if (fields) {
303
+ contextState = {
304
+ ...contextState,
305
+ ...fields
306
+ };
307
+ activeContext.setAttributes(flattenToAttributes(fields));
308
+ }
309
+ },
310
+ warn(message, fields) {
311
+ addLogEvent("warn", message, fields);
312
+ activeContext.setAttribute("autotel.log.level", "warn");
313
+ if (fields) {
314
+ contextState = {
315
+ ...contextState,
316
+ ...fields
317
+ };
318
+ activeContext.setAttributes(flattenToAttributes(fields));
319
+ }
320
+ },
321
+ error(error, fields) {
322
+ const err = typeof error === "string" ? new Error(error) : error;
323
+ recordStructuredError(activeContext, err);
324
+ addLogEvent("error", err.message, fields);
325
+ if (fields) {
326
+ contextState = {
327
+ ...contextState,
328
+ ...fields
329
+ };
330
+ activeContext.setAttributes(flattenToAttributes(fields));
331
+ }
332
+ activeContext.setAttribute("autotel.log.level", "error");
333
+ },
334
+ getContext() {
335
+ return { ...contextState };
336
+ },
337
+ emitNow(overrides) {
338
+ const mergedContext = {
339
+ ...contextState,
340
+ ...overrides ?? {}
341
+ };
342
+ const flattened = flattenToAttributes(mergedContext);
343
+ activeContext.setAttributes(flattened);
344
+ const snapshot = {
345
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
346
+ traceId: activeContext.traceId,
347
+ spanId: activeContext.spanId,
348
+ correlationId: activeContext.correlationId,
349
+ context: mergedContext
350
+ };
351
+ activeContext.addEvent("log.emit.manual", {
352
+ ...flattened
353
+ });
354
+ if (options?.onEmit) {
355
+ Promise.resolve(options.onEmit(snapshot)).catch((error) => {
356
+ console.warn("[autotel] request logger onEmit failed:", error);
357
+ });
358
+ }
359
+ return snapshot;
360
+ }
361
+ };
362
+ }
363
+
364
+ Object.defineProperty(exports, "createDrainPipeline", {
365
+ enumerable: true,
366
+ get: function () { return chunk7EQ4G4SI_cjs.createDrainPipeline; }
367
+ });
167
368
  Object.defineProperty(exports, "getCurrentWorkflowContext", {
168
369
  enumerable: true,
169
- get: function () { return chunk7NH625MS_cjs.getCurrentWorkflowContext; }
370
+ get: function () { return chunkBSZP4URK_cjs.getCurrentWorkflowContext; }
170
371
  });
171
372
  Object.defineProperty(exports, "isInWorkflow", {
172
373
  enumerable: true,
173
- get: function () { return chunk7NH625MS_cjs.isInWorkflow; }
374
+ get: function () { return chunkBSZP4URK_cjs.isInWorkflow; }
174
375
  });
175
376
  Object.defineProperty(exports, "traceStep", {
176
377
  enumerable: true,
177
- get: function () { return chunk7NH625MS_cjs.traceStep; }
378
+ get: function () { return chunkBSZP4URK_cjs.traceStep; }
178
379
  });
179
380
  Object.defineProperty(exports, "traceWorkflow", {
180
381
  enumerable: true,
181
- get: function () { return chunk7NH625MS_cjs.traceWorkflow; }
382
+ get: function () { return chunkBSZP4URK_cjs.traceWorkflow; }
182
383
  });
183
384
  Object.defineProperty(exports, "attrs", {
184
385
  enumerable: true,
@@ -264,13 +465,17 @@ Object.defineProperty(exports, "URLAttributes", {
264
465
  enumerable: true,
265
466
  get: function () { return chunkESMHTKLJ_cjs.URLAttributes; }
266
467
  });
468
+ Object.defineProperty(exports, "parseError", {
469
+ enumerable: true,
470
+ get: function () { return chunkT4B5LB6E_cjs.parseError; }
471
+ });
267
472
  Object.defineProperty(exports, "traceConsumer", {
268
473
  enumerable: true,
269
- get: function () { return chunkCQC6RVLR_cjs.traceConsumer; }
474
+ get: function () { return chunk4RZ4JUBY_cjs.traceConsumer; }
270
475
  });
271
476
  Object.defineProperty(exports, "traceProducer", {
272
477
  enumerable: true,
273
- get: function () { return chunkCQC6RVLR_cjs.traceProducer; }
478
+ get: function () { return chunk4RZ4JUBY_cjs.traceProducer; }
274
479
  });
275
480
  Object.defineProperty(exports, "BusinessBaggage", {
276
481
  enumerable: true,
@@ -314,55 +519,55 @@ Object.defineProperty(exports, "getMeter", {
314
519
  });
315
520
  Object.defineProperty(exports, "traceDB", {
316
521
  enumerable: true,
317
- get: function () { return chunkCQP5SQT4_cjs.traceDB; }
522
+ get: function () { return chunkAXFWWJF3_cjs.traceDB; }
318
523
  });
319
524
  Object.defineProperty(exports, "traceHTTP", {
320
525
  enumerable: true,
321
- get: function () { return chunkCQP5SQT4_cjs.traceHTTP; }
526
+ get: function () { return chunkAXFWWJF3_cjs.traceHTTP; }
322
527
  });
323
528
  Object.defineProperty(exports, "traceLLM", {
324
529
  enumerable: true,
325
- get: function () { return chunkCQP5SQT4_cjs.traceLLM; }
530
+ get: function () { return chunkAXFWWJF3_cjs.traceLLM; }
326
531
  });
327
532
  Object.defineProperty(exports, "traceMessaging", {
328
533
  enumerable: true,
329
- get: function () { return chunkCQP5SQT4_cjs.traceMessaging; }
534
+ get: function () { return chunkAXFWWJF3_cjs.traceMessaging; }
330
535
  });
331
536
  Object.defineProperty(exports, "ctx", {
332
537
  enumerable: true,
333
- get: function () { return chunkVQFF2WMP_cjs.ctx; }
538
+ get: function () { return chunk3ZFDJJWZ_cjs.ctx; }
334
539
  });
335
540
  Object.defineProperty(exports, "getEventQueue", {
336
541
  enumerable: true,
337
- get: function () { return chunkVQFF2WMP_cjs.getEventQueue; }
542
+ get: function () { return chunk3ZFDJJWZ_cjs.getEventQueue; }
338
543
  });
339
544
  Object.defineProperty(exports, "instrument", {
340
545
  enumerable: true,
341
- get: function () { return chunkVQFF2WMP_cjs.instrument; }
546
+ get: function () { return chunk3ZFDJJWZ_cjs.instrument; }
342
547
  });
343
548
  Object.defineProperty(exports, "span", {
344
549
  enumerable: true,
345
- get: function () { return chunkVQFF2WMP_cjs.span; }
550
+ get: function () { return chunk3ZFDJJWZ_cjs.span; }
346
551
  });
347
552
  Object.defineProperty(exports, "trace", {
348
553
  enumerable: true,
349
- get: function () { return chunkVQFF2WMP_cjs.trace; }
554
+ get: function () { return chunk3ZFDJJWZ_cjs.trace; }
350
555
  });
351
556
  Object.defineProperty(exports, "track", {
352
557
  enumerable: true,
353
- get: function () { return chunkVQFF2WMP_cjs.track; }
558
+ get: function () { return chunk3ZFDJJWZ_cjs.track; }
354
559
  });
355
560
  Object.defineProperty(exports, "withBaggage", {
356
561
  enumerable: true,
357
- get: function () { return chunkVQFF2WMP_cjs.withBaggage; }
562
+ get: function () { return chunk3ZFDJJWZ_cjs.withBaggage; }
358
563
  });
359
564
  Object.defineProperty(exports, "withNewContext", {
360
565
  enumerable: true,
361
- get: function () { return chunkVQFF2WMP_cjs.withNewContext; }
566
+ get: function () { return chunk3ZFDJJWZ_cjs.withNewContext; }
362
567
  });
363
568
  Object.defineProperty(exports, "withTracing", {
364
569
  enumerable: true,
365
- get: function () { return chunkVQFF2WMP_cjs.withTracing; }
570
+ get: function () { return chunk3ZFDJJWZ_cjs.withTracing; }
366
571
  });
367
572
  Object.defineProperty(exports, "defineBaggageSchema", {
368
573
  enumerable: true,
@@ -414,15 +619,15 @@ Object.defineProperty(exports, "runWithSpan", {
414
619
  });
415
620
  Object.defineProperty(exports, "Event", {
416
621
  enumerable: true,
417
- get: function () { return chunk4UYR46UP_cjs.Event; }
622
+ get: function () { return chunkMSUHW2I4_cjs.Event; }
418
623
  });
419
624
  Object.defineProperty(exports, "getEvents", {
420
625
  enumerable: true,
421
- get: function () { return chunk4UYR46UP_cjs.getEvents; }
626
+ get: function () { return chunkMSUHW2I4_cjs.getEvents; }
422
627
  });
423
628
  Object.defineProperty(exports, "resetEvents", {
424
629
  enumerable: true,
425
- get: function () { return chunk4UYR46UP_cjs.resetEvents; }
630
+ get: function () { return chunkMSUHW2I4_cjs.resetEvents; }
426
631
  });
427
632
  Object.defineProperty(exports, "getOperationContext", {
428
633
  enumerable: true,
@@ -462,11 +667,11 @@ Object.defineProperty(exports, "setCorrelationIdInBaggage", {
462
667
  });
463
668
  Object.defineProperty(exports, "BaggageSpanProcessor", {
464
669
  enumerable: true,
465
- get: function () { return chunkQKUGUDXJ_cjs.BaggageSpanProcessor; }
670
+ get: function () { return chunkHSEIUH7F_cjs.BaggageSpanProcessor; }
466
671
  });
467
672
  Object.defineProperty(exports, "init", {
468
673
  enumerable: true,
469
- get: function () { return chunkQKUGUDXJ_cjs.init; }
674
+ get: function () { return chunkHSEIUH7F_cjs.init; }
470
675
  });
471
676
  Object.defineProperty(exports, "FilteringSpanProcessor", {
472
677
  enumerable: true,
@@ -500,6 +705,10 @@ Object.defineProperty(exports, "createRedactedSpan", {
500
705
  enumerable: true,
501
706
  get: function () { return chunkELW34S4C_cjs.createRedactedSpan; }
502
707
  });
708
+ Object.defineProperty(exports, "formatDuration", {
709
+ enumerable: true,
710
+ get: function () { return chunk6S5RUKU3_cjs.formatDuration; }
711
+ });
503
712
  Object.defineProperty(exports, "AdaptiveSampler", {
504
713
  enumerable: true,
505
714
  get: function () { return chunkBGVKKL2N_cjs.AdaptiveSampler; }
@@ -564,7 +773,13 @@ Object.defineProperty(exports, "propagation", {
564
773
  enumerable: true,
565
774
  get: function () { return api.propagation; }
566
775
  });
776
+ exports.createStructuredError = createStructuredError;
777
+ exports.flattenToAttributes = flattenToAttributes;
567
778
  exports.flush = flush;
779
+ exports.getRequestLogger = getRequestLogger;
780
+ exports.getStructuredErrorAttributes = getStructuredErrorAttributes;
781
+ exports.recordStructuredError = recordStructuredError;
568
782
  exports.shutdown = shutdown;
783
+ exports.toAttributeValue = toAttributeValue;
569
784
  //# sourceMappingURL=index.cjs.map
570
785
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shutdown.ts"],"names":["getEventQueue","getSdk","getLogger","resetEvents","resetMetrics","resetEventQueue"],"mappings":"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","file":"index.cjs","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","../src/flatten-attributes.ts","../src/structured-error.ts","../src/request-logger.ts"],"names":["getEventQueue","getSdk","getLogger","resetEvents","resetMetrics","resetEventQueue","ctx","SpanStatusCode","span","otelTrace","createTraceContext","attrs"],"mappings":"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","file":"index.cjs","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","import type { AttributeValue } from './trace-context';\n\n/**\n * Convert an unknown value to an OTel-compatible AttributeValue.\n * Returns undefined when the value cannot be represented.\n */\nexport function toAttributeValue(value: unknown): AttributeValue | undefined {\n if (\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ) {\n return value;\n }\n if (Array.isArray(value)) {\n if (\n value.every((v) => typeof v === 'string') ||\n value.every((v) => typeof v === 'number') ||\n value.every((v) => typeof v === 'boolean')\n ) {\n return value as AttributeValue;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return '<serialization-failed>';\n }\n }\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (value instanceof Error) {\n return value.message;\n }\n return undefined;\n}\n\n/**\n * Recursively flatten a nested object into dot-notation OTel attributes.\n * Includes circular reference protection via WeakSet.\n */\nexport function flattenToAttributes(\n fields: Record<string, unknown>,\n prefix = '',\n): Record<string, AttributeValue> {\n const out: Record<string, AttributeValue> = {};\n const seen = new WeakSet<object>();\n\n function flatten(obj: Record<string, unknown>, currentPrefix: string): void {\n for (const [key, value] of Object.entries(obj)) {\n if (value == null) continue;\n const nextKey = currentPrefix ? `${currentPrefix}.${key}` : key;\n\n const attr = toAttributeValue(value);\n if (attr !== undefined) {\n out[nextKey] = attr;\n continue;\n }\n\n if (typeof value === 'object' && value.constructor === Object) {\n if (seen.has(value)) {\n out[nextKey] = '<circular-reference>';\n continue;\n }\n seen.add(value);\n flatten(value as Record<string, unknown>, nextKey);\n continue;\n }\n\n try {\n out[nextKey] = JSON.stringify(value);\n } catch {\n out[nextKey] = '<serialization-failed>';\n }\n }\n }\n\n flatten(fields, prefix);\n return out;\n}\n","import { SpanStatusCode } from '@opentelemetry/api';\nimport type { AttributeValue, TraceContext } from './trace-context';\nimport { flattenToAttributes } from './flatten-attributes';\n\nexport interface StructuredErrorInput {\n message: string;\n why?: string;\n fix?: string;\n link?: string;\n code?: string | number;\n status?: number;\n cause?: unknown;\n details?: Record<string, unknown>;\n name?: string;\n}\n\nexport interface StructuredError extends Error {\n why?: string;\n fix?: string;\n link?: string;\n code?: string | number;\n status?: number;\n details?: Record<string, unknown>;\n}\n\nexport function createStructuredError(\n input: StructuredErrorInput,\n): StructuredError {\n const error = new Error(input.message, {\n cause: input.cause,\n }) as StructuredError;\n\n error.name = input.name ?? 'StructuredError';\n if (input.why !== undefined) error.why = input.why;\n if (input.fix !== undefined) error.fix = input.fix;\n if (input.link !== undefined) error.link = input.link;\n if (input.code !== undefined) error.code = input.code;\n if (input.status !== undefined) error.status = input.status;\n if (input.details !== undefined) error.details = input.details;\n\n return error;\n}\n\nexport function getStructuredErrorAttributes(\n error: Error,\n): Record<string, AttributeValue> {\n const structured = error as StructuredError;\n const attributes: Record<string, AttributeValue> = {\n 'error.type': error.name || 'Error',\n 'error.message': error.message,\n };\n\n if (error.stack) attributes['error.stack'] = error.stack;\n if (structured.why) attributes['error.why'] = structured.why;\n if (structured.fix) attributes['error.fix'] = structured.fix;\n if (structured.link) attributes['error.link'] = structured.link;\n if (structured.code !== undefined) {\n attributes['error.code'] =\n typeof structured.code === 'string'\n ? structured.code\n : String(structured.code);\n }\n if (structured.status !== undefined) {\n attributes['error.status'] = structured.status;\n }\n if (structured.details) {\n Object.assign(\n attributes,\n flattenToAttributes(structured.details, 'error.details'),\n );\n }\n\n return attributes;\n}\n\nexport function recordStructuredError(\n ctx: Pick<TraceContext, 'recordException' | 'setAttributes' | 'setStatus'>,\n error: Error,\n): void {\n ctx.recordException(error);\n ctx.setStatus({\n code: SpanStatusCode.ERROR,\n message: error.message,\n });\n ctx.setAttributes(getStructuredErrorAttributes(error));\n}\n","import { trace as otelTrace } from '@opentelemetry/api';\nimport type { TraceContext } from './trace-context';\nimport { createTraceContext } from './trace-context';\nimport { recordStructuredError } from './structured-error';\nimport { flattenToAttributes } from './flatten-attributes';\n\nexport interface RequestLogger {\n set(fields: Record<string, unknown>): void;\n info(message: string, fields?: Record<string, unknown>): void;\n warn(message: string, fields?: Record<string, unknown>): void;\n error(error: Error | string, fields?: Record<string, unknown>): void;\n getContext(): Record<string, unknown>;\n emitNow(overrides?: Record<string, unknown>): RequestLogSnapshot;\n}\n\nexport interface RequestLogSnapshot {\n timestamp: string;\n traceId: string;\n spanId: string;\n correlationId: string;\n context: Record<string, unknown>;\n}\n\nexport interface RequestLoggerOptions {\n /** Callback invoked by emitNow() for manual fan-out. */\n onEmit?: (snapshot: RequestLogSnapshot) => void | Promise<void>;\n}\n\nfunction resolveContext(ctx?: TraceContext): TraceContext {\n if (ctx) return ctx;\n\n const span = otelTrace.getActiveSpan();\n if (!span) {\n throw new Error(\n '[autotel] getRequestLogger() requires an active span. Wrap your handler with trace().',\n );\n }\n return createTraceContext(span);\n}\n\nexport function getRequestLogger(\n ctx?: TraceContext,\n options?: RequestLoggerOptions,\n): RequestLogger {\n const activeContext = resolveContext(ctx);\n let contextState: Record<string, unknown> = {};\n\n const addLogEvent = (\n level: 'info' | 'warn' | 'error',\n message: string,\n fields?: Record<string, unknown>,\n ) => {\n const attrs = fields ? flattenToAttributes(fields) : undefined;\n activeContext.addEvent(`log.${level}`, {\n message,\n ...attrs,\n });\n };\n\n return {\n set(fields: Record<string, unknown>) {\n contextState = {\n ...contextState,\n ...fields,\n };\n activeContext.setAttributes(flattenToAttributes(fields));\n },\n\n info(message: string, fields?: Record<string, unknown>) {\n addLogEvent('info', message, fields);\n if (fields) {\n contextState = {\n ...contextState,\n ...fields,\n };\n activeContext.setAttributes(flattenToAttributes(fields));\n }\n },\n\n warn(message: string, fields?: Record<string, unknown>) {\n addLogEvent('warn', message, fields);\n activeContext.setAttribute('autotel.log.level', 'warn');\n if (fields) {\n contextState = {\n ...contextState,\n ...fields,\n };\n activeContext.setAttributes(flattenToAttributes(fields));\n }\n },\n\n error(error: Error | string, fields?: Record<string, unknown>) {\n const err = typeof error === 'string' ? new Error(error) : error;\n recordStructuredError(activeContext, err);\n addLogEvent('error', err.message, fields);\n\n if (fields) {\n contextState = {\n ...contextState,\n ...fields,\n };\n activeContext.setAttributes(flattenToAttributes(fields));\n }\n activeContext.setAttribute('autotel.log.level', 'error');\n },\n\n getContext() {\n return { ...contextState };\n },\n\n emitNow(overrides?: Record<string, unknown>): RequestLogSnapshot {\n const mergedContext = {\n ...contextState,\n ...(overrides ?? {}),\n };\n const flattened = flattenToAttributes(mergedContext);\n activeContext.setAttributes(flattened);\n\n const snapshot: RequestLogSnapshot = {\n timestamp: new Date().toISOString(),\n traceId: activeContext.traceId,\n spanId: activeContext.spanId,\n correlationId: activeContext.correlationId,\n context: mergedContext,\n };\n\n activeContext.addEvent('log.emit.manual', {\n ...flattened,\n });\n\n if (options?.onEmit) {\n Promise.resolve(options.onEmit(snapshot)).catch((error) => {\n console.warn('[autotel] request logger onEmit failed:', error);\n });\n }\n\n return snapshot;\n },\n };\n}\n"]}