autotel 2.26.3 → 3.0.3

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 (191) hide show
  1. package/README.md +50 -23
  2. package/dist/attribute-redacting-processor.cjs +8 -8
  3. package/dist/attribute-redacting-processor.d.cts +10 -1
  4. package/dist/attribute-redacting-processor.d.ts +10 -1
  5. package/dist/attribute-redacting-processor.js +1 -1
  6. package/dist/attributes.cjs +21 -21
  7. package/dist/attributes.d.cts +3 -3
  8. package/dist/attributes.d.ts +3 -3
  9. package/dist/attributes.js +2 -2
  10. package/dist/auto.cjs +3 -3
  11. package/dist/auto.js +2 -2
  12. package/dist/business-baggage.d.cts +1 -1
  13. package/dist/business-baggage.d.ts +1 -1
  14. package/dist/chunk-4P6ZOARG.cjs +33 -0
  15. package/dist/chunk-4P6ZOARG.cjs.map +1 -0
  16. package/dist/{chunk-U54FTVFH.js → chunk-52PUSFC2.js} +3 -3
  17. package/dist/{chunk-U54FTVFH.js.map → chunk-52PUSFC2.js.map} +1 -1
  18. package/dist/{chunk-YEVCD6DR.cjs → chunk-7SMNC4LS.cjs} +7 -7
  19. package/dist/{chunk-YEVCD6DR.cjs.map → chunk-7SMNC4LS.cjs.map} +1 -1
  20. package/dist/{chunk-563EL6O6.cjs → chunk-BPO2PQ3T.cjs} +12 -8
  21. package/dist/chunk-BPO2PQ3T.cjs.map +1 -0
  22. package/dist/{chunk-WZOKY3PW.cjs → chunk-DAZ7EGR4.cjs} +19 -19
  23. package/dist/{chunk-WZOKY3PW.cjs.map → chunk-DAZ7EGR4.cjs.map} +1 -1
  24. package/dist/{chunk-ER43K7ES.js → chunk-DDXIUZEG.js} +3 -3
  25. package/dist/{chunk-ER43K7ES.js.map → chunk-DDXIUZEG.js.map} +1 -1
  26. package/dist/{chunk-JKIMEPI2.cjs → chunk-DQ2SUROF.cjs} +4 -4
  27. package/dist/{chunk-JKIMEPI2.cjs.map → chunk-DQ2SUROF.cjs.map} +1 -1
  28. package/dist/{chunk-B3ZHLLMP.js → chunk-DSMSIVTG.js} +2 -2
  29. package/dist/chunk-DSMSIVTG.js.map +1 -0
  30. package/dist/{chunk-OBWXM4NN.cjs → chunk-HKZHUGGN.cjs} +15 -14
  31. package/dist/chunk-HKZHUGGN.cjs.map +1 -0
  32. package/dist/{chunk-TDNKIHKT.js → chunk-JVWJDHDB.js} +13 -4
  33. package/dist/chunk-JVWJDHDB.js.map +1 -0
  34. package/dist/{chunk-YN7USLHW.js → chunk-K7HSRLP5.js} +11 -10
  35. package/dist/chunk-K7HSRLP5.js.map +1 -0
  36. package/dist/chunk-KIL5CUN6.js +31 -0
  37. package/dist/chunk-KIL5CUN6.js.map +1 -0
  38. package/dist/chunk-KKGM42RQ.cjs +1207 -0
  39. package/dist/chunk-KKGM42RQ.cjs.map +1 -0
  40. package/dist/{chunk-6YGUN7IY.cjs → chunk-MOO75VE4.cjs} +18 -17
  41. package/dist/chunk-MOO75VE4.cjs.map +1 -0
  42. package/dist/{chunk-GML3FBOT.cjs → chunk-NCSMD3TK.cjs} +2 -2
  43. package/dist/chunk-NCSMD3TK.cjs.map +1 -0
  44. package/dist/{chunk-CMNGGTQL.cjs → chunk-NXLRY2CE.cjs} +13 -4
  45. package/dist/chunk-NXLRY2CE.cjs.map +1 -0
  46. package/dist/{chunk-BJ2XPN77.js → chunk-OM4OSBOP.js} +5 -5
  47. package/dist/{chunk-BJ2XPN77.js.map → chunk-OM4OSBOP.js.map} +1 -1
  48. package/dist/{chunk-HPUGKUMZ.js → chunk-PMRWMRXY.js} +13 -640
  49. package/dist/chunk-PMRWMRXY.js.map +1 -0
  50. package/dist/{chunk-UTZR7P7E.cjs → chunk-QPH5ZKP5.cjs} +43 -673
  51. package/dist/chunk-QPH5ZKP5.cjs.map +1 -0
  52. package/dist/chunk-SEO6NAQT.js +14 -0
  53. package/dist/chunk-SEO6NAQT.js.map +1 -0
  54. package/dist/{chunk-QC5MNKVF.js → chunk-TFRZOUTV.js} +13 -12
  55. package/dist/chunk-TFRZOUTV.js.map +1 -0
  56. package/dist/chunk-VQTCQKHQ.cjs +17 -0
  57. package/dist/chunk-VQTCQKHQ.cjs.map +1 -0
  58. package/dist/chunk-Z7VAOK5X.js +1183 -0
  59. package/dist/chunk-Z7VAOK5X.js.map +1 -0
  60. package/dist/{chunk-W35FVJBC.js → chunk-ZDPIWKWD.js} +9 -5
  61. package/dist/chunk-ZDPIWKWD.js.map +1 -0
  62. package/dist/correlation-id.cjs +22 -10
  63. package/dist/correlation-id.js +14 -2
  64. package/dist/decorators.cjs +7 -8
  65. package/dist/decorators.cjs.map +1 -1
  66. package/dist/decorators.d.cts +1 -1
  67. package/dist/decorators.d.ts +1 -1
  68. package/dist/decorators.js +6 -7
  69. package/dist/decorators.js.map +1 -1
  70. package/dist/event.cjs +8 -9
  71. package/dist/event.js +5 -6
  72. package/dist/functional.cjs +13 -14
  73. package/dist/functional.d.cts +1 -1
  74. package/dist/functional.d.ts +1 -1
  75. package/dist/functional.js +6 -7
  76. package/dist/http.cjs +13 -2
  77. package/dist/http.cjs.map +1 -1
  78. package/dist/http.js +12 -1
  79. package/dist/http.js.map +1 -1
  80. package/dist/index.cjs +305 -280
  81. package/dist/index.cjs.map +1 -1
  82. package/dist/index.d.cts +89 -10
  83. package/dist/index.d.ts +89 -10
  84. package/dist/index.js +180 -181
  85. package/dist/index.js.map +1 -1
  86. package/dist/instrumentation.cjs +9 -9
  87. package/dist/instrumentation.js +2 -2
  88. package/dist/messaging-adapters.d.cts +1 -1
  89. package/dist/messaging-adapters.d.ts +1 -1
  90. package/dist/messaging-testing.d.cts +1 -1
  91. package/dist/messaging-testing.d.ts +1 -1
  92. package/dist/messaging.cjs +11 -11
  93. package/dist/messaging.d.cts +1 -1
  94. package/dist/messaging.d.ts +1 -1
  95. package/dist/messaging.js +8 -8
  96. package/dist/semantic-helpers.cjs +11 -12
  97. package/dist/semantic-helpers.d.cts +1 -1
  98. package/dist/semantic-helpers.d.ts +1 -1
  99. package/dist/semantic-helpers.js +7 -8
  100. package/dist/{trace-context-t5X1AP-e.d.cts → trace-context-DbGKd1Rn.d.cts} +18 -5
  101. package/dist/{trace-context-t5X1AP-e.d.ts → trace-context-DbGKd1Rn.d.ts} +18 -5
  102. package/dist/trace-helpers.cjs +13 -13
  103. package/dist/trace-helpers.d.cts +2 -2
  104. package/dist/trace-helpers.d.ts +2 -2
  105. package/dist/trace-helpers.js +1 -1
  106. package/dist/{utils-CbUkl8r1.d.cts → utils-BahBCFtJ.d.cts} +1 -1
  107. package/dist/{utils-Buel3cj0.d.ts → utils-CLKwaUlG.d.ts} +1 -1
  108. package/dist/webhook.cjs +21 -12
  109. package/dist/webhook.cjs.map +1 -1
  110. package/dist/webhook.d.cts +1 -1
  111. package/dist/webhook.d.ts +1 -1
  112. package/dist/webhook.js +20 -11
  113. package/dist/webhook.js.map +1 -1
  114. package/dist/workflow-distributed.cjs +25 -21
  115. package/dist/workflow-distributed.cjs.map +1 -1
  116. package/dist/workflow-distributed.d.cts +1 -1
  117. package/dist/workflow-distributed.d.ts +1 -1
  118. package/dist/workflow-distributed.js +23 -19
  119. package/dist/workflow-distributed.js.map +1 -1
  120. package/dist/workflow.cjs +12 -12
  121. package/dist/workflow.d.cts +1 -1
  122. package/dist/workflow.d.ts +1 -1
  123. package/dist/workflow.js +8 -8
  124. package/package.json +43 -45
  125. package/skills/analyze-traces/SKILL.md +178 -0
  126. package/skills/autotel-core/SKILL.md +2 -7
  127. package/skills/autotel-events/SKILL.md +2 -6
  128. package/skills/autotel-frameworks/SKILL.md +2 -9
  129. package/skills/autotel-instrumentation/SKILL.md +2 -7
  130. package/skills/autotel-request-logging/SKILL.md +2 -8
  131. package/skills/autotel-structured-errors/SKILL.md +2 -7
  132. package/skills/build-audit-trails/SKILL.md +302 -0
  133. package/skills/debug-missing-spans/SKILL.md +248 -0
  134. package/skills/migrate-to-autotel/SKILL.md +268 -0
  135. package/skills/review-otel-patterns/SKILL.md +488 -0
  136. package/skills/review-otel-patterns/references/code-review.md +75 -0
  137. package/skills/review-otel-patterns/references/processor-pipeline.md +205 -0
  138. package/skills/review-otel-patterns/references/structured-errors.md +102 -0
  139. package/skills/review-otel-patterns/references/wide-spans.md +85 -0
  140. package/skills/tune-sampling/SKILL.md +210 -0
  141. package/src/attribute-redacting-processor.test.ts +6 -4
  142. package/src/attribute-redacting-processor.ts +11 -2
  143. package/src/correlated-events.test.ts +151 -0
  144. package/src/correlated-events.ts +47 -0
  145. package/src/drain-toolkit.test.ts +113 -0
  146. package/src/drain-toolkit.ts +129 -0
  147. package/src/enricher-toolkit.test.ts +67 -0
  148. package/src/enricher-toolkit.ts +79 -0
  149. package/src/functional.ts +2 -0
  150. package/src/gen-ai-events.ts +14 -5
  151. package/src/index.ts +39 -4
  152. package/src/messaging.ts +10 -9
  153. package/src/redact-values.test.ts +24 -10
  154. package/src/redact-values.ts +9 -2
  155. package/src/request-logger.test.ts +91 -0
  156. package/src/request-logger.ts +40 -5
  157. package/src/structured-error.test.ts +86 -1
  158. package/src/structured-error.ts +9 -2
  159. package/src/trace-context.ts +39 -11
  160. package/src/trace-helpers.ts +2 -2
  161. package/src/trace-hybrid.test.ts +42 -0
  162. package/src/trace-hybrid.ts +37 -0
  163. package/src/webhook.ts +16 -7
  164. package/src/workflow-distributed.ts +18 -13
  165. package/src/workflow.ts +7 -6
  166. package/bin/intent.js +0 -6
  167. package/dist/chunk-563EL6O6.cjs.map +0 -1
  168. package/dist/chunk-6YGUN7IY.cjs.map +0 -1
  169. package/dist/chunk-B3ZHLLMP.js.map +0 -1
  170. package/dist/chunk-BBBWDIYQ.js +0 -211
  171. package/dist/chunk-BBBWDIYQ.js.map +0 -1
  172. package/dist/chunk-CMNGGTQL.cjs.map +0 -1
  173. package/dist/chunk-D5LMF53P.cjs +0 -150
  174. package/dist/chunk-D5LMF53P.cjs.map +0 -1
  175. package/dist/chunk-GML3FBOT.cjs.map +0 -1
  176. package/dist/chunk-HPUGKUMZ.js.map +0 -1
  177. package/dist/chunk-HZ3FYBJG.cjs +0 -217
  178. package/dist/chunk-HZ3FYBJG.cjs.map +0 -1
  179. package/dist/chunk-JSNUWSBH.cjs +0 -62
  180. package/dist/chunk-JSNUWSBH.cjs.map +0 -1
  181. package/dist/chunk-OBWXM4NN.cjs.map +0 -1
  182. package/dist/chunk-QC5MNKVF.js.map +0 -1
  183. package/dist/chunk-S4OFEXLA.js +0 -53
  184. package/dist/chunk-S4OFEXLA.js.map +0 -1
  185. package/dist/chunk-TDNKIHKT.js.map +0 -1
  186. package/dist/chunk-UTZR7P7E.cjs.map +0 -1
  187. package/dist/chunk-W35FVJBC.js.map +0 -1
  188. package/dist/chunk-WD4RP6IV.js +0 -146
  189. package/dist/chunk-WD4RP6IV.js.map +0 -1
  190. package/dist/chunk-YN7USLHW.js.map +0 -1
  191. package/src/package-manifest.test.ts +0 -24
package/README.md CHANGED
@@ -538,8 +538,9 @@ export const rollDice = trace(async function rollDice(rolls: number) {
538
538
  { name: 'roll.once', attributes: { roll: i + 1 } },
539
539
  async (span) => {
540
540
  span.setAttribute('range', '1-6');
541
- span.addEvent('dice.rolled', { value: rollOnce() });
542
- results.push(rollOnce());
541
+ const value = rollOnce();
542
+ span.setAttribute('dice.value', value);
543
+ results.push(value);
543
544
  },
544
545
  );
545
546
  }
@@ -555,6 +556,9 @@ Nested spans automatically inherit context and correlation IDs.
555
556
  Every `trace((ctx) => ...)` factory receives a type-safe helper backed by `AsyncLocalStorage`.
556
557
 
557
558
  ```typescript
559
+ import { trace, recordStructuredError } from 'autotel';
560
+ import { SpanStatusCode } from '@opentelemetry/api';
561
+
558
562
  export const createUser = trace((ctx) => async (input: CreateUserData) => {
559
563
  logger.info({ traceId: ctx.traceId }, 'Handling request');
560
564
  ctx.setAttributes({ 'user.id': input.id, 'user.plan': input.plan });
@@ -564,17 +568,20 @@ export const createUser = trace((ctx) => async (input: CreateUserData) => {
564
568
  ctx.setStatus({ code: SpanStatusCode.OK });
565
569
  return user;
566
570
  } catch (error) {
567
- ctx.recordException(error as Error);
568
- ctx.setStatus({
569
- code: SpanStatusCode.ERROR,
570
- message: 'Failed to create user',
571
- });
571
+ // Records the error on the span and sets ERROR status. Pair with
572
+ // `getRequestLogger(ctx).error(error)` if you also want a correlated log.
573
+ recordStructuredError(ctx, error as Error);
572
574
  throw error;
573
575
  }
574
576
  });
575
577
  ```
576
578
 
577
- Available helpers: `traceId`, `spanId`, `correlationId`, `setAttribute`, `setAttributes`, `setStatus`, `recordException`, `getBaggage`, `setBaggage`, `deleteBaggage`, `getAllBaggage`.
579
+ Available helpers: `traceId`, `spanId`, `correlationId`, `setAttribute`, `setAttributes`, `setStatus`, `getBaggage`, `setBaggage`, `deleteBaggage`, `getAllBaggage`.
580
+
581
+ > **Errors and events:** prefer `recordStructuredError(ctx, error)` and the
582
+ > request logger over the raw `Span.recordException` / `Span.addEvent` APIs.
583
+ > See [MIGRATION.md](./MIGRATION.md) for the OTel Span Event deprecation
584
+ > direction.
578
585
 
579
586
  #### Baggage (Context Propagation)
580
587
 
@@ -1749,7 +1756,7 @@ init({
1749
1756
  ### Request Logger DX
1750
1757
 
1751
1758
  For teams that prefer `log.set({...})` ergonomics, you can use `getRequestLogger()`.
1752
- It writes directly to span attributes/events, so canonical log lines still emit one
1759
+ It writes correlated request context and log records, so canonical log lines still emit one
1753
1760
  wide event per request.
1754
1761
 
1755
1762
  ```typescript
@@ -1784,7 +1791,7 @@ export const checkout = trace((ctx) => async (order: Order) => {
1784
1791
  You also get:
1785
1792
 
1786
1793
  - `log.getContext()` to inspect the accumulated request context.
1787
- - `log.emitNow(overrides?)` to capture an immediate snapshot (adds a span event
1794
+ - `log.emitNow(overrides?)` to capture an immediate snapshot (emits a correlated log-style snapshot
1788
1795
  and returns `{ timestamp, traceId, spanId, correlationId, context }`).
1789
1796
 
1790
1797
  ### Drain Pipeline (Batch + Retry + Flush)
@@ -2365,20 +2372,20 @@ export async function customWorkflow() {
2365
2372
  }
2366
2373
  }
2367
2374
 
2368
- // Add attributes and events to the currently active span
2375
+ // Add attributes to the currently active span
2369
2376
  export function enrichCurrentSpan(userId: string) {
2370
2377
  const span = getActiveSpan();
2371
2378
  if (span) {
2372
2379
  span.setAttribute('user.id', userId);
2373
- span.addEvent('User identified', { userId, timestamp: Date.now() });
2380
+ span.setAttribute('user.identified_at', Date.now());
2374
2381
  }
2375
2382
  }
2376
2383
 
2377
- // Add events with attributes (e.g., queue operations)
2384
+ // Add attributes with queue context
2378
2385
  export async function processQueue() {
2379
2386
  const span = getActiveSpan();
2380
2387
  if (span) {
2381
- span.addEvent('queue.wait', {
2388
+ span.setAttributes({
2382
2389
  queue_size: 42,
2383
2390
  queue_name: 'order-processing',
2384
2391
  });
@@ -2398,8 +2405,8 @@ export async function backgroundJob() {
2398
2405
  });
2399
2406
  span.setStatus({ code: SpanStatusCode.OK });
2400
2407
  } catch (error) {
2401
- span.recordException(error);
2402
2408
  span.setStatus({ code: SpanStatusCode.ERROR });
2409
+ throw error;
2403
2410
  } finally {
2404
2411
  span.end();
2405
2412
  }
@@ -2523,14 +2530,31 @@ export const handler = trace(async (event) => {
2523
2530
 
2524
2531
  ### Edge Runtimes (Cloudflare Workers, Vercel Edge)
2525
2532
 
2526
- For edge runtimes with different constraints, use the `autotel-edge` package instead:
2533
+ For edge runtimes with different constraints:
2534
+
2535
+ - **Cloudflare Workers:** use `autotel-cloudflare`.
2536
+ - **Other edge runtimes (Vercel/Netlify/Deno):** use `autotel-edge`.
2537
+
2538
+ Cloudflare Workers example:
2527
2539
 
2528
2540
  ```typescript
2529
- import { init } from 'autotel-edge';
2530
- // Auto-flush built-in for edge environments
2541
+ import { wrapModule, trace, init } from 'autotel-cloudflare';
2542
+
2543
+ const processOrder = trace(async (orderId: string, kv: KVNamespace) => {
2544
+ return kv.get(orderId);
2545
+ });
2546
+
2547
+ export default wrapModule(
2548
+ { service: { name: 'my-worker' } },
2549
+ {
2550
+ async fetch(_req, env) {
2551
+ return Response.json(await processOrder('123', env.ORDERS_KV));
2552
+ },
2553
+ },
2554
+ );
2531
2555
  ```
2532
2556
 
2533
- The `autotel-edge` package is optimized for edge runtimes with automatic flush behavior.
2557
+ `autotel-edge` remains optimized for vendor-agnostic edge runtimes with automatic flush behavior.
2534
2558
 
2535
2559
  ## API Reference
2536
2560
 
@@ -3024,11 +3048,14 @@ import {
3024
3048
  // Span methods
3025
3049
  span.setAttribute(key, value); // Add single attribute
3026
3050
  span.setAttributes({ key: value }); // Add multiple attributes
3027
- span.addEvent('cache.hit'); // Add event (name only)
3028
- span.addEvent('queue.wait', { queue_size: 42 }); // Add event with attributes
3029
- span.recordException(error); // Record exception
3030
- span.setStatus({ code: SpanStatusCode.ERROR }); // Set status
3051
+ span.setStatus({ code: SpanStatusCode.OK }); // Mark span successful
3052
+ span.setStatus({ code: SpanStatusCode.ERROR, message }); // Mark span failed
3031
3053
  span.end(); // End span
3054
+
3055
+ // For events and exceptions, prefer the autotel APIs over raw Span methods:
3056
+ // - recordStructuredError(ctx, error) // span error + status
3057
+ // - getRequestLogger(ctx).info(name, fields) // correlated log event
3058
+ // See MIGRATION.md for the OTel Span Event deprecation direction.
3032
3059
  ```
3033
3060
 
3034
3061
  #### Semantic Conventions (Optional)
@@ -1,37 +1,37 @@
1
1
  'use strict';
2
2
 
3
- var chunkCMNGGTQL_cjs = require('./chunk-CMNGGTQL.cjs');
3
+ var chunkNXLRY2CE_cjs = require('./chunk-NXLRY2CE.cjs');
4
4
  require('./chunk-JEQ2X3Z6.cjs');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "AttributeRedactingProcessor", {
9
9
  enumerable: true,
10
- get: function () { return chunkCMNGGTQL_cjs.AttributeRedactingProcessor; }
10
+ get: function () { return chunkNXLRY2CE_cjs.AttributeRedactingProcessor; }
11
11
  });
12
12
  Object.defineProperty(exports, "REDACTOR_PATTERNS", {
13
13
  enumerable: true,
14
- get: function () { return chunkCMNGGTQL_cjs.REDACTOR_PATTERNS; }
14
+ get: function () { return chunkNXLRY2CE_cjs.REDACTOR_PATTERNS; }
15
15
  });
16
16
  Object.defineProperty(exports, "REDACTOR_PRESETS", {
17
17
  enumerable: true,
18
- get: function () { return chunkCMNGGTQL_cjs.REDACTOR_PRESETS; }
18
+ get: function () { return chunkNXLRY2CE_cjs.REDACTOR_PRESETS; }
19
19
  });
20
20
  Object.defineProperty(exports, "builtinPatterns", {
21
21
  enumerable: true,
22
- get: function () { return chunkCMNGGTQL_cjs.builtinPatterns; }
22
+ get: function () { return chunkNXLRY2CE_cjs.builtinPatterns; }
23
23
  });
24
24
  Object.defineProperty(exports, "createAttributeRedactor", {
25
25
  enumerable: true,
26
- get: function () { return chunkCMNGGTQL_cjs.createAttributeRedactor; }
26
+ get: function () { return chunkNXLRY2CE_cjs.createAttributeRedactor; }
27
27
  });
28
28
  Object.defineProperty(exports, "createRedactedSpan", {
29
29
  enumerable: true,
30
- get: function () { return chunkCMNGGTQL_cjs.createRedactedSpan; }
30
+ get: function () { return chunkNXLRY2CE_cjs.createRedactedSpan; }
31
31
  });
32
32
  Object.defineProperty(exports, "normalizeAttributeRedactorConfig", {
33
33
  enumerable: true,
34
- get: function () { return chunkCMNGGTQL_cjs.normalizeAttributeRedactorConfig; }
34
+ get: function () { return chunkNXLRY2CE_cjs.normalizeAttributeRedactorConfig; }
35
35
  });
36
36
  //# sourceMappingURL=attribute-redacting-processor.cjs.map
37
37
  //# sourceMappingURL=attribute-redacting-processor.cjs.map
@@ -116,7 +116,16 @@ declare const builtinPatterns: {
116
116
  readonly pattern: RegExp;
117
117
  readonly mask: (m: string) => string;
118
118
  };
119
- /** International phone numbers → +33******78 (country code + last 2 digits) */
119
+ /**
120
+ * International / formatted phone numbers.
121
+ *
122
+ * Matches:
123
+ * - `+33 1 23 45 67 89` -> `+33******89`
124
+ * - `(415) 555-1234` -> `********34`
125
+ * - `555-123-4567` / `555.123.4567` / `5551234567` -> `********67`
126
+ *
127
+ * Bare short digit runs like `12345678` are intentionally not matched.
128
+ */
120
129
  readonly phone: {
121
130
  readonly pattern: RegExp;
122
131
  readonly mask: (m: string) => string;
@@ -116,7 +116,16 @@ declare const builtinPatterns: {
116
116
  readonly pattern: RegExp;
117
117
  readonly mask: (m: string) => string;
118
118
  };
119
- /** International phone numbers → +33******78 (country code + last 2 digits) */
119
+ /**
120
+ * International / formatted phone numbers.
121
+ *
122
+ * Matches:
123
+ * - `+33 1 23 45 67 89` -> `+33******89`
124
+ * - `(415) 555-1234` -> `********34`
125
+ * - `555-123-4567` / `555.123.4567` / `5551234567` -> `********67`
126
+ *
127
+ * Bare short digit runs like `12345678` are intentionally not matched.
128
+ */
120
129
  readonly phone: {
121
130
  readonly pattern: RegExp;
122
131
  readonly mask: (m: string) => string;
@@ -1,4 +1,4 @@
1
- export { AttributeRedactingProcessor, REDACTOR_PATTERNS, REDACTOR_PRESETS, builtinPatterns, createAttributeRedactor, createRedactedSpan, normalizeAttributeRedactorConfig } from './chunk-TDNKIHKT.js';
1
+ export { AttributeRedactingProcessor, REDACTOR_PATTERNS, REDACTOR_PRESETS, builtinPatterns, createAttributeRedactor, createRedactedSpan, normalizeAttributeRedactorConfig } from './chunk-JVWJDHDB.js';
2
2
  import './chunk-DGUM43GV.js';
3
3
  //# sourceMappingURL=attribute-redacting-processor.js.map
4
4
  //# sourceMappingURL=attribute-redacting-processor.js.map
@@ -1,87 +1,87 @@
1
1
  'use strict';
2
2
 
3
- var chunkJKIMEPI2_cjs = require('./chunk-JKIMEPI2.cjs');
3
+ var chunkDQ2SUROF_cjs = require('./chunk-DQ2SUROF.cjs');
4
4
  require('./chunk-ESMHTKLJ.cjs');
5
- require('./chunk-CMNGGTQL.cjs');
5
+ require('./chunk-NXLRY2CE.cjs');
6
6
  require('./chunk-JEQ2X3Z6.cjs');
7
7
 
8
8
 
9
9
 
10
10
  Object.defineProperty(exports, "attrs", {
11
11
  enumerable: true,
12
- get: function () { return chunkJKIMEPI2_cjs.attrs; }
12
+ get: function () { return chunkDQ2SUROF_cjs.attrs; }
13
13
  });
14
14
  Object.defineProperty(exports, "autoRedactPII", {
15
15
  enumerable: true,
16
- get: function () { return chunkJKIMEPI2_cjs.autoRedactPII; }
16
+ get: function () { return chunkDQ2SUROF_cjs.autoRedactPII; }
17
17
  });
18
18
  Object.defineProperty(exports, "checkDeprecatedAttribute", {
19
19
  enumerable: true,
20
- get: function () { return chunkJKIMEPI2_cjs.checkDeprecatedAttribute; }
20
+ get: function () { return chunkDQ2SUROF_cjs.checkDeprecatedAttribute; }
21
21
  });
22
22
  Object.defineProperty(exports, "dbClient", {
23
23
  enumerable: true,
24
- get: function () { return chunkJKIMEPI2_cjs.dbClient; }
24
+ get: function () { return chunkDQ2SUROF_cjs.dbClient; }
25
25
  });
26
26
  Object.defineProperty(exports, "defaultGuardrails", {
27
27
  enumerable: true,
28
- get: function () { return chunkJKIMEPI2_cjs.defaultGuardrails; }
28
+ get: function () { return chunkDQ2SUROF_cjs.defaultGuardrails; }
29
29
  });
30
30
  Object.defineProperty(exports, "httpClient", {
31
31
  enumerable: true,
32
- get: function () { return chunkJKIMEPI2_cjs.httpClient; }
32
+ get: function () { return chunkDQ2SUROF_cjs.httpClient; }
33
33
  });
34
34
  Object.defineProperty(exports, "httpServer", {
35
35
  enumerable: true,
36
- get: function () { return chunkJKIMEPI2_cjs.httpServer; }
36
+ get: function () { return chunkDQ2SUROF_cjs.httpServer; }
37
37
  });
38
38
  Object.defineProperty(exports, "identify", {
39
39
  enumerable: true,
40
- get: function () { return chunkJKIMEPI2_cjs.identify; }
40
+ get: function () { return chunkDQ2SUROF_cjs.identify; }
41
41
  });
42
42
  Object.defineProperty(exports, "mergeAttrs", {
43
43
  enumerable: true,
44
- get: function () { return chunkJKIMEPI2_cjs.mergeAttrs; }
44
+ get: function () { return chunkDQ2SUROF_cjs.mergeAttrs; }
45
45
  });
46
46
  Object.defineProperty(exports, "mergeServiceResource", {
47
47
  enumerable: true,
48
- get: function () { return chunkJKIMEPI2_cjs.mergeServiceResource; }
48
+ get: function () { return chunkDQ2SUROF_cjs.mergeServiceResource; }
49
49
  });
50
50
  Object.defineProperty(exports, "request", {
51
51
  enumerable: true,
52
- get: function () { return chunkJKIMEPI2_cjs.request; }
52
+ get: function () { return chunkDQ2SUROF_cjs.request; }
53
53
  });
54
54
  Object.defineProperty(exports, "safeSetAttributes", {
55
55
  enumerable: true,
56
- get: function () { return chunkJKIMEPI2_cjs.safeSetAttributes; }
56
+ get: function () { return chunkDQ2SUROF_cjs.safeSetAttributes; }
57
57
  });
58
58
  Object.defineProperty(exports, "setDevice", {
59
59
  enumerable: true,
60
- get: function () { return chunkJKIMEPI2_cjs.setDevice; }
60
+ get: function () { return chunkDQ2SUROF_cjs.setDevice; }
61
61
  });
62
62
  Object.defineProperty(exports, "setError", {
63
63
  enumerable: true,
64
- get: function () { return chunkJKIMEPI2_cjs.setError; }
64
+ get: function () { return chunkDQ2SUROF_cjs.setError; }
65
65
  });
66
66
  Object.defineProperty(exports, "setException", {
67
67
  enumerable: true,
68
- get: function () { return chunkJKIMEPI2_cjs.setException; }
68
+ get: function () { return chunkDQ2SUROF_cjs.setException; }
69
69
  });
70
70
  Object.defineProperty(exports, "setSession", {
71
71
  enumerable: true,
72
- get: function () { return chunkJKIMEPI2_cjs.setSession; }
72
+ get: function () { return chunkDQ2SUROF_cjs.setSession; }
73
73
  });
74
74
  Object.defineProperty(exports, "setUser", {
75
75
  enumerable: true,
76
- get: function () { return chunkJKIMEPI2_cjs.setUser; }
76
+ get: function () { return chunkDQ2SUROF_cjs.setUser; }
77
77
  });
78
78
  Object.defineProperty(exports, "transaction", {
79
79
  enumerable: true,
80
- get: function () { return chunkJKIMEPI2_cjs.transaction; }
80
+ get: function () { return chunkDQ2SUROF_cjs.transaction; }
81
81
  });
82
82
  Object.defineProperty(exports, "validateAttribute", {
83
83
  enumerable: true,
84
- get: function () { return chunkJKIMEPI2_cjs.validateAttribute; }
84
+ get: function () { return chunkDQ2SUROF_cjs.validateAttribute; }
85
85
  });
86
86
  //# sourceMappingURL=attributes.cjs.map
87
87
  //# sourceMappingURL=attributes.cjs.map
@@ -1,6 +1,6 @@
1
- import { U as UserAttrs, S as SessionAttrs, A as AttributePolicy } from './utils-CbUkl8r1.cjs';
2
- export { a as AttributeGuardrails, C as ClientAttrs, b as CloudAttrs, c as CodeAttrs, d as ContainerAttrs, D as DBAttrs, e as DeploymentAttrs, f as DeviceAttrs, E as ErrorAttrs, g as ExceptionAttrs, F as FaaSAttrs, h as FeatureFlagAttrs, G as GenAIAttrs, i as GraphQLAttrs, H as HTTPClientAttrs, j as HTTPServerAttrs, K as K8sAttrs, M as MessagingAttrs, N as NetworkAttrs, O as OTelAttrs, P as PeerAttrs, k as ProcessAttrs, R as RPCAttrs, l as ServerAddressAttrs, m as ServiceAttrs, T as TLSAttrs, n as ThreadAttrs, o as URLAttrs, p as attrs, q as autoRedactPII, r as checkDeprecatedAttribute, s as dbClient, t as defaultGuardrails, u as httpClient, v as httpServer, w as identify, x as mergeAttrs, y as mergeServiceResource, z as request, B as safeSetAttributes, I as setDevice, J as setError, L as setException, Q as setSession, V as setUser, W as validateAttribute } from './utils-CbUkl8r1.cjs';
3
- import { T as TraceContext } from './trace-context-t5X1AP-e.cjs';
1
+ import { U as UserAttrs, S as SessionAttrs, A as AttributePolicy } from './utils-BahBCFtJ.cjs';
2
+ export { a as AttributeGuardrails, C as ClientAttrs, b as CloudAttrs, c as CodeAttrs, d as ContainerAttrs, D as DBAttrs, e as DeploymentAttrs, f as DeviceAttrs, E as ErrorAttrs, g as ExceptionAttrs, F as FaaSAttrs, h as FeatureFlagAttrs, G as GenAIAttrs, i as GraphQLAttrs, H as HTTPClientAttrs, j as HTTPServerAttrs, K as K8sAttrs, M as MessagingAttrs, N as NetworkAttrs, O as OTelAttrs, P as PeerAttrs, k as ProcessAttrs, R as RPCAttrs, l as ServerAddressAttrs, m as ServiceAttrs, T as TLSAttrs, n as ThreadAttrs, o as URLAttrs, p as attrs, q as autoRedactPII, r as checkDeprecatedAttribute, s as dbClient, t as defaultGuardrails, u as httpClient, v as httpServer, w as identify, x as mergeAttrs, y as mergeServiceResource, z as request, B as safeSetAttributes, I as setDevice, J as setError, L as setException, Q as setSession, V as setUser, W as validateAttribute } from './utils-BahBCFtJ.cjs';
3
+ import { T as TraceContext } from './trace-context-DbGKd1Rn.cjs';
4
4
  import '@opentelemetry/api';
5
5
  import '@opentelemetry/resources';
6
6
 
@@ -1,6 +1,6 @@
1
- import { U as UserAttrs, S as SessionAttrs, A as AttributePolicy } from './utils-Buel3cj0.js';
2
- export { a as AttributeGuardrails, C as ClientAttrs, b as CloudAttrs, c as CodeAttrs, d as ContainerAttrs, D as DBAttrs, e as DeploymentAttrs, f as DeviceAttrs, E as ErrorAttrs, g as ExceptionAttrs, F as FaaSAttrs, h as FeatureFlagAttrs, G as GenAIAttrs, i as GraphQLAttrs, H as HTTPClientAttrs, j as HTTPServerAttrs, K as K8sAttrs, M as MessagingAttrs, N as NetworkAttrs, O as OTelAttrs, P as PeerAttrs, k as ProcessAttrs, R as RPCAttrs, l as ServerAddressAttrs, m as ServiceAttrs, T as TLSAttrs, n as ThreadAttrs, o as URLAttrs, p as attrs, q as autoRedactPII, r as checkDeprecatedAttribute, s as dbClient, t as defaultGuardrails, u as httpClient, v as httpServer, w as identify, x as mergeAttrs, y as mergeServiceResource, z as request, B as safeSetAttributes, I as setDevice, J as setError, L as setException, Q as setSession, V as setUser, W as validateAttribute } from './utils-Buel3cj0.js';
3
- import { T as TraceContext } from './trace-context-t5X1AP-e.js';
1
+ import { U as UserAttrs, S as SessionAttrs, A as AttributePolicy } from './utils-CLKwaUlG.js';
2
+ export { a as AttributeGuardrails, C as ClientAttrs, b as CloudAttrs, c as CodeAttrs, d as ContainerAttrs, D as DBAttrs, e as DeploymentAttrs, f as DeviceAttrs, E as ErrorAttrs, g as ExceptionAttrs, F as FaaSAttrs, h as FeatureFlagAttrs, G as GenAIAttrs, i as GraphQLAttrs, H as HTTPClientAttrs, j as HTTPServerAttrs, K as K8sAttrs, M as MessagingAttrs, N as NetworkAttrs, O as OTelAttrs, P as PeerAttrs, k as ProcessAttrs, R as RPCAttrs, l as ServerAddressAttrs, m as ServiceAttrs, T as TLSAttrs, n as ThreadAttrs, o as URLAttrs, p as attrs, q as autoRedactPII, r as checkDeprecatedAttribute, s as dbClient, t as defaultGuardrails, u as httpClient, v as httpServer, w as identify, x as mergeAttrs, y as mergeServiceResource, z as request, B as safeSetAttributes, I as setDevice, J as setError, L as setException, Q as setSession, V as setUser, W as validateAttribute } from './utils-CLKwaUlG.js';
3
+ import { T as TraceContext } from './trace-context-DbGKd1Rn.js';
4
4
  import '@opentelemetry/api';
5
5
  import '@opentelemetry/resources';
6
6
 
@@ -1,6 +1,6 @@
1
- export { attrs, autoRedactPII, checkDeprecatedAttribute, dbClient, defaultGuardrails, httpClient, httpServer, identify, mergeAttrs, mergeServiceResource, request, safeSetAttributes, setDevice, setError, setException, setSession, setUser, transaction, validateAttribute } from './chunk-ER43K7ES.js';
1
+ export { attrs, autoRedactPII, checkDeprecatedAttribute, dbClient, defaultGuardrails, httpClient, httpServer, identify, mergeAttrs, mergeServiceResource, request, safeSetAttributes, setDevice, setError, setException, setSession, setUser, transaction, validateAttribute } from './chunk-DDXIUZEG.js';
2
2
  import './chunk-4A53YIAX.js';
3
- import './chunk-TDNKIHKT.js';
3
+ import './chunk-JVWJDHDB.js';
4
4
  import './chunk-DGUM43GV.js';
5
5
  //# sourceMappingURL=attributes.js.map
6
6
  //# sourceMappingURL=attributes.js.map
package/dist/auto.cjs CHANGED
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var chunk563EL6O6_cjs = require('./chunk-563EL6O6.cjs');
3
+ var chunkBPO2PQ3T_cjs = require('./chunk-BPO2PQ3T.cjs');
4
4
  var chunkOC6X2VIN_cjs = require('./chunk-OC6X2VIN.cjs');
5
5
  require('./chunk-CEAQK2QY.cjs');
6
6
  require('./chunk-ZNMBW67B.cjs');
7
7
  require('./chunk-IOYFAFHJ.cjs');
8
- require('./chunk-CMNGGTQL.cjs');
8
+ require('./chunk-NXLRY2CE.cjs');
9
9
  require('./chunk-CU6IDACR.cjs');
10
10
  require('./chunk-6S5RUKU3.cjs');
11
11
  require('./chunk-YS6C2YJE.cjs');
@@ -23,7 +23,7 @@ module$1.register("import-in-the-middle/hook.mjs", (typeof document === 'undefin
23
23
  var yamlConfig = chunkOC6X2VIN_cjs.loadYamlConfig();
24
24
  var autoInstrumentationsEnv = process.env.AUTOTEL_INTEGRATIONS;
25
25
  var autoInstrumentations = autoInstrumentationsEnv === "true" ? true : autoInstrumentationsEnv ? autoInstrumentationsEnv.split(",").map((s) => s.trim()) : yamlConfig?.autoInstrumentations ?? ["http", "express"];
26
- chunk563EL6O6_cjs.init({
26
+ chunkBPO2PQ3T_cjs.init({
27
27
  service: yamlConfig?.service ?? process.env.OTEL_SERVICE_NAME ?? "unknown-service",
28
28
  debug: yamlConfig?.debug ?? process.env.AUTOTEL_DEBUG === "true",
29
29
  autoInstrumentations
package/dist/auto.js CHANGED
@@ -1,9 +1,9 @@
1
- import { init } from './chunk-W35FVJBC.js';
1
+ import { init } from './chunk-ZDPIWKWD.js';
2
2
  import { loadYamlConfig } from './chunk-3SDILILG.js';
3
3
  import './chunk-A4E5AQFK.js';
4
4
  import './chunk-WGWSHJ2N.js';
5
5
  import './chunk-GYR5K654.js';
6
- import './chunk-TDNKIHKT.js';
6
+ import './chunk-JVWJDHDB.js';
7
7
  import './chunk-6UQRVUN3.js';
8
8
  import './chunk-3QXBFGKP.js';
9
9
  import './chunk-33WTKH7X.js';
@@ -1,4 +1,4 @@
1
- import { T as TraceContext } from './trace-context-t5X1AP-e.cjs';
1
+ import { T as TraceContext } from './trace-context-DbGKd1Rn.cjs';
2
2
  import '@opentelemetry/api';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { T as TraceContext } from './trace-context-t5X1AP-e.js';
1
+ import { T as TraceContext } from './trace-context-DbGKd1Rn.js';
2
2
  import '@opentelemetry/api';
3
3
 
4
4
  /**
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ // src/correlated-events.ts
4
+ function sanitizeEventKey(input) {
5
+ return input.replaceAll(/[^a-zA-Z0-9_.-]/g, "_");
6
+ }
7
+ var sequenceByTarget = /* @__PURE__ */ new WeakMap();
8
+ function nextSequence(target) {
9
+ const n = (sequenceByTarget.get(target) ?? 0) + 1;
10
+ sequenceByTarget.set(target, n);
11
+ return n;
12
+ }
13
+ function emitCorrelatedEvent(ctx, name, attrs = {}) {
14
+ const eventName = sanitizeEventKey(name);
15
+ if (typeof ctx.addEvent === "function") {
16
+ ctx.addEvent.call(ctx, eventName, attrs);
17
+ return;
18
+ }
19
+ const seq = nextSequence(ctx);
20
+ const prefix = `autotel.event.${seq}.${eventName}`;
21
+ const flattened = {
22
+ [`${prefix}.name`]: eventName,
23
+ [`${prefix}.ts`]: (/* @__PURE__ */ new Date()).toISOString()
24
+ };
25
+ for (const [k, v] of Object.entries(attrs)) {
26
+ flattened[`${prefix}.${sanitizeEventKey(k)}`] = v;
27
+ }
28
+ ctx.setAttributes(flattened);
29
+ }
30
+
31
+ exports.emitCorrelatedEvent = emitCorrelatedEvent;
32
+ //# sourceMappingURL=chunk-4P6ZOARG.cjs.map
33
+ //# sourceMappingURL=chunk-4P6ZOARG.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/correlated-events.ts"],"names":[],"mappings":";;;AAUA,SAAS,iBAAiB,KAAA,EAAuB;AAC/C,EAAA,OAAO,KAAA,CAAM,UAAA,CAAW,kBAAA,EAAoB,GAAG,CAAA;AACjD;AAMA,IAAM,gBAAA,uBAAuB,OAAA,EAAwB;AAErD,SAAS,aAAa,MAAA,EAAwB;AAC5C,EAAA,MAAM,CAAA,GAAA,CAAK,gBAAA,CAAiB,GAAA,CAAI,MAAM,KAAK,CAAA,IAAK,CAAA;AAChD,EAAA,gBAAA,CAAiB,GAAA,CAAI,QAAQ,CAAC,CAAA;AAC9B,EAAA,OAAO,CAAA;AACT;AAEO,SAAS,mBAAA,CACd,GAAA,EACA,IAAA,EACA,KAAA,GAAwC,EAAC,EACnC;AACN,EAAA,MAAM,SAAA,GAAY,iBAAiB,IAAI,CAAA;AACvC,EAAA,IAAI,OAAO,GAAA,CAAI,QAAA,KAAa,UAAA,EAAY;AACtC,IAAA,GAAA,CAAI,QAAA,CAAS,IAAA,CAAK,GAAA,EAAK,SAAA,EAAW,KAAK,CAAA;AACvC,IAAA;AAAA,EACF;AACA,EAAA,MAAM,GAAA,GAAM,aAAa,GAAG,CAAA;AAC5B,EAAA,MAAM,MAAA,GAAS,CAAA,cAAA,EAAiB,GAAG,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAChD,EAAA,MAAM,SAAA,GAA4C;AAAA,IAChD,CAAC,CAAA,EAAG,MAAM,CAAA,KAAA,CAAO,GAAG,SAAA;AAAA,IACpB,CAAC,GAAG,MAAM,CAAA,GAAA,CAAK,oBAAG,IAAI,IAAA,IAAO,WAAA;AAAY,GAC3C;AACA,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC1C,IAAA,SAAA,CAAU,GAAG,MAAM,CAAA,CAAA,EAAI,iBAAiB,CAAC,CAAC,EAAE,CAAA,GAAI,CAAA;AAAA,EAClD;AACA,EAAA,GAAA,CAAI,cAAc,SAAS,CAAA;AAC7B","file":"chunk-4P6ZOARG.cjs","sourcesContent":["import type { AttributeValue } from './trace-context';\n\nexport interface CorrelatedEventTarget {\n setAttribute(key: string, value: AttributeValue): unknown;\n setAttributes(attrs: Record<string, AttributeValue>): unknown;\n addEvent?(name: string, attrs?: Record<string, AttributeValue>): unknown;\n}\n\n// OTel attribute keys are dot-namespaced flat strings; we keep `.`/`-`/`_` and\n// drop everything else so user-supplied event names can't break attribute keys.\nfunction sanitizeEventKey(input: string): string {\n return input.replaceAll(/[^a-zA-Z0-9_.-]/g, '_');\n}\n\n// Per-target sequence so the fallback path can encode multiple events with the\n// same name without one overwriting the previous (attributes are\n// last-write-wins; events are not). Today the addEvent path is always taken;\n// this keeps the fallback correct if/when the runtime stops binding addEvent.\nconst sequenceByTarget = new WeakMap<object, number>();\n\nfunction nextSequence(target: object): number {\n const n = (sequenceByTarget.get(target) ?? 0) + 1;\n sequenceByTarget.set(target, n);\n return n;\n}\n\nexport function emitCorrelatedEvent(\n ctx: CorrelatedEventTarget,\n name: string,\n attrs: Record<string, AttributeValue> = {},\n): void {\n const eventName = sanitizeEventKey(name);\n if (typeof ctx.addEvent === 'function') {\n ctx.addEvent.call(ctx, eventName, attrs);\n return;\n }\n const seq = nextSequence(ctx);\n const prefix = `autotel.event.${seq}.${eventName}`;\n const flattened: Record<string, AttributeValue> = {\n [`${prefix}.name`]: eventName,\n [`${prefix}.ts`]: new Date().toISOString(),\n };\n for (const [k, v] of Object.entries(attrs)) {\n flattened[`${prefix}.${sanitizeEventKey(k)}`] = v;\n }\n ctx.setAttributes(flattened);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { trace } from './chunk-HPUGKUMZ.js';
1
+ import { trace } from './chunk-PMRWMRXY.js';
2
2
 
3
3
  // src/semantic-helpers.ts
4
4
  function traceLLM(config) {
@@ -91,5 +91,5 @@ function traceMessaging(config) {
91
91
  }
92
92
 
93
93
  export { traceDB, traceHTTP, traceLLM, traceMessaging };
94
- //# sourceMappingURL=chunk-U54FTVFH.js.map
95
- //# sourceMappingURL=chunk-U54FTVFH.js.map
94
+ //# sourceMappingURL=chunk-52PUSFC2.js.map
95
+ //# sourceMappingURL=chunk-52PUSFC2.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/semantic-helpers.ts"],"names":[],"mappings":"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","file":"chunk-U54FTVFH.js","sourcesContent":["/**\n * Semantic convention helpers for OpenTelemetry\n *\n * Pre-configured trace helpers that follow OpenTelemetry semantic conventions\n * for common operation types. Reduces boilerplate and ensures consistency.\n *\n * Based on: https://opentelemetry.io/docs/specs/semconv/\n */\n\nimport { trace } from './functional';\nimport type { TraceContext } from './trace-context';\nimport type { Attributes } from '@opentelemetry/api';\n\n/**\n * Configuration for LLM (Large Language Model) operations\n *\n * Follows Gen AI semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/gen-ai/\n */\nexport interface LLMConfig {\n /** Model name (e.g., 'gpt-4', 'claude-3-opus') */\n model: string;\n /** Operation type */\n operation?: 'chat' | 'completion' | 'embedding';\n /** Model provider (e.g., 'openai', 'anthropic', 'cohere') - maps to gen.ai.system */\n provider?: string;\n /** Additional attributes to add to the span */\n attributes?: Attributes;\n}\n\n/**\n * Configuration for database operations\n *\n * Follows DB semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/database/\n */\nexport interface DBConfig {\n /** Database system (e.g., 'postgresql', 'mongodb', 'redis') */\n system: string;\n /** Operation type (e.g., 'SELECT', 'INSERT', 'find', 'get') */\n operation?: string;\n /** Database name */\n database?: string;\n /** Collection/table name */\n collection?: string;\n /** Additional attributes to add to the span */\n attributes?: Attributes;\n}\n\n/**\n * Configuration for HTTP client operations\n *\n * Follows HTTP semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/http/\n */\nexport interface HTTPConfig {\n /** HTTP method (e.g., 'GET', 'POST') */\n method?: string;\n /** Target URL or URL template */\n url?: string;\n /** Additional attributes to add to the span */\n attributes?: Attributes;\n}\n\n/**\n * Configuration for messaging operations\n *\n * Follows Messaging semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/messaging/\n */\nexport interface MessagingConfig {\n /** Messaging system (e.g., 'kafka', 'rabbitmq', 'sqs') */\n system: string;\n /** Operation type */\n operation?: 'publish' | 'receive' | 'process';\n /** Destination name (queue/topic) */\n destination?: string;\n /** Additional attributes to add to the span */\n attributes?: Attributes;\n}\n\n/**\n * Trace LLM operations with Gen AI semantic conventions\n *\n * Automatically adds standard attributes for LLM operations:\n * - gen.ai.request.model\n * - gen.ai.operation.name\n * - gen.ai.system\n *\n * **Use Cases:**\n * - Chat completions\n * - Text generation\n * - Embeddings\n * - Multi-step LLM workflows\n *\n * @param config - LLM operation configuration\n * @returns Traced function factory with Gen AI attributes\n *\n * @example Chat completion with OpenAI\n * ```typescript\n * import { traceLLM } from 'autotel/semantic-helpers'\n * import OpenAI from 'openai'\n *\n * const openai = new OpenAI()\n *\n * export const generateResponse = traceLLM({\n * model: 'gpt-4-turbo',\n * operation: 'chat',\n * provider: 'openai'\n * })(ctx => async (prompt: string) => {\n * const response = await openai.chat.completions.create({\n * model: 'gpt-4-turbo',\n * messages: [{ role: 'user', content: prompt }]\n * })\n *\n * // Add usage metrics to span\n * ctx.setAttribute('gen.ai.usage.completion_tokens', response.usage?.completion_tokens)\n * ctx.setAttribute('gen.ai.usage.prompt_tokens', response.usage?.prompt_tokens)\n *\n * return response.choices[0].message.content\n * })\n * ```\n *\n * @example Anthropic Claude with streaming\n * ```typescript\n * import { traceLLM } from 'autotel/semantic-helpers'\n * import Anthropic from '@anthropic-ai/sdk'\n *\n * const anthropic = new Anthropic()\n *\n * export const streamResponse = traceLLM({\n * model: 'claude-3-opus-20240229',\n * operation: 'chat',\n * provider: 'anthropic'\n * })(ctx => async function* (prompt: string) {\n * const stream = await anthropic.messages.create({\n * model: 'claude-3-opus-20240229',\n * messages: [{ role: 'user', content: prompt }],\n * stream: true,\n * max_tokens: 1024\n * })\n *\n * let totalTokens = 0\n * for await (const event of stream) {\n * if (event.type === 'content_block_delta') {\n * yield event.delta.text\n * }\n * if (event.type === 'message_stop') {\n * ctx.setAttribute('gen.ai.usage.completion_tokens', event.message.usage.output_tokens)\n * totalTokens = event.message.usage.output_tokens\n * }\n * }\n *\n * return totalTokens\n * })\n * ```\n *\n * @example Embeddings\n * ```typescript\n * import { traceLLM } from 'autotel/semantic-helpers'\n * import { OpenAIEmbeddings } from '@langchain/openai'\n *\n * const embeddings = new OpenAIEmbeddings()\n *\n * export const embed = traceLLM({\n * model: 'text-embedding-3-small',\n * operation: 'embedding',\n * provider: 'openai'\n * })(ctx => async (text: string) => {\n * const result = await embeddings.embedQuery(text)\n * ctx.setAttribute('gen.ai.response.embedding_length', result.length)\n * return result\n * })\n * ```\n *\n * @public\n */\nexport function traceLLM<TArgs extends unknown[], TReturn>(config: LLMConfig) {\n return (\n fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n ): ((...args: TArgs) => Promise<TReturn>) => {\n return trace<TArgs, TReturn>((ctx) => {\n // Set semantic convention attributes\n ctx.setAttribute('gen.ai.request.model', config.model);\n ctx.setAttribute('gen.ai.operation.name', config.operation || 'chat');\n if (config.provider) {\n ctx.setAttribute('gen.ai.system', config.provider);\n }\n if (config.attributes) {\n for (const [key, value] of Object.entries(config.attributes)) {\n if (value !== undefined && value !== null) {\n // setAttribute only accepts primitives (string | number | boolean)\n // Arrays and objects should be serialized\n const attrValue =\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ? value\n : JSON.stringify(value);\n ctx.setAttribute(key, attrValue);\n }\n }\n }\n\n // Call the user's factory to get their function and return it\n return fnFactory(ctx);\n });\n };\n}\n\n/**\n * Trace database operations with DB semantic conventions\n *\n * Automatically adds standard attributes for database operations:\n * - db.system\n * - db.operation\n * - db.name\n * - db.collection.name (for NoSQL)\n *\n * **Use Cases:**\n * - SQL queries (PostgreSQL, MySQL, SQLite)\n * - NoSQL operations (MongoDB, DynamoDB, Redis)\n * - ORM queries (Prisma, TypeORM, Drizzle)\n *\n * @param config - Database operation configuration\n * @returns Traced function factory with DB attributes\n *\n * @example PostgreSQL query\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { pool } from './db'\n *\n * export const getUser = traceDB({\n * system: 'postgresql',\n * operation: 'SELECT',\n * database: 'app_db',\n * collection: 'users'\n * })(ctx => async (userId: string) => {\n * const query = 'SELECT * FROM users WHERE id = $1'\n * ctx.setAttribute('db.statement', query)\n *\n * const result = await pool.query(query, [userId])\n * ctx.setAttribute('db.rows_affected', result.rowCount)\n *\n * return result.rows[0]\n * })\n * ```\n *\n * @example MongoDB with Mongoose\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { User } from './models/User'\n *\n * export const findUsers = traceDB({\n * system: 'mongodb',\n * operation: 'find',\n * database: 'app_db',\n * collection: 'users'\n * })(ctx => async (filter: object) => {\n * ctx.setAttribute('db.mongodb.filter', JSON.stringify(filter))\n *\n * const users = await User.find(filter).limit(100)\n * ctx.setAttribute('db.response.count', users.length)\n *\n * return users\n * })\n * ```\n *\n * @example Redis operations\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { redis } from './redis'\n *\n * export const cacheGet = traceDB({\n * system: 'redis',\n * operation: 'GET'\n * })(ctx => async (key: string) => {\n * ctx.setAttribute('db.redis.key', key)\n *\n * const value = await redis.get(key)\n * ctx.setAttribute('db.response.cache_hit', value !== null)\n *\n * return value\n * })\n * ```\n *\n * @example Prisma with detailed query info\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { prisma } from './prisma'\n *\n * export const createPost = traceDB({\n * system: 'postgresql',\n * operation: 'INSERT',\n * database: 'app_db',\n * collection: 'posts'\n * })(ctx => async (data: { title: string; content: string; authorId: string }) => {\n * ctx.setAttribute('db.prisma.model', 'Post')\n * ctx.setAttribute('db.prisma.action', 'create')\n *\n * const post = await prisma.post.create({ data })\n *\n * ctx.setAttribute('db.response.id', post.id)\n * return post\n * })\n * ```\n *\n * @public\n */\nexport function traceDB<TArgs extends unknown[], TReturn>(config: DBConfig) {\n return (\n fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n ): ((...args: TArgs) => Promise<TReturn>) => {\n return trace<TArgs, TReturn>((ctx) => {\n // Set semantic convention attributes\n ctx.setAttribute('db.system', config.system);\n if (config.operation) {\n ctx.setAttribute('db.operation', config.operation);\n }\n if (config.database) {\n ctx.setAttribute('db.name', config.database);\n }\n if (config.collection) {\n ctx.setAttribute('db.collection.name', config.collection);\n }\n if (config.attributes) {\n for (const [key, value] of Object.entries(config.attributes)) {\n if (value !== undefined && value !== null) {\n // setAttribute only accepts primitives (string | number | boolean)\n // Arrays and objects should be serialized\n const attrValue =\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ? value\n : JSON.stringify(value);\n ctx.setAttribute(key, attrValue);\n }\n }\n }\n\n // Call the user's factory to get their function and return it\n return fnFactory(ctx);\n });\n };\n}\n\n/**\n * Trace HTTP client operations with HTTP semantic conventions\n *\n * Automatically adds standard attributes for HTTP requests:\n * - http.request.method\n * - url.full\n *\n * **Use Cases:**\n * - External API calls\n * - Microservice communication\n * - Third-party integrations\n *\n * @param config - HTTP operation configuration\n * @returns Traced function factory with HTTP attributes\n *\n * @example Fetch API\n * ```typescript\n * import { traceHTTP } from 'autotel/semantic-helpers'\n *\n * export const fetchUser = traceHTTP({\n * method: 'GET',\n * url: 'https://api.example.com/users/:id'\n * })(ctx => async (userId: string) => {\n * const url = `https://api.example.com/users/${userId}`\n * ctx.setAttribute('url.full', url)\n *\n * const response = await fetch(url)\n * ctx.setAttribute('http.response.status_code', response.status)\n *\n * if (!response.ok) {\n * ctx.setAttribute('error', true)\n * throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n * }\n *\n * return response.json()\n * })\n * ```\n *\n * @example Axios with retry logic\n * ```typescript\n * import { traceHTTP } from 'autotel/semantic-helpers'\n * import axios from 'axios'\n *\n * export const sendWebhook = traceHTTP({\n * method: 'POST',\n * url: 'https://webhook.example.com/events'\n * })(ctx => async (payload: object) => {\n * let attempts = 0\n * const maxAttempts = 3\n *\n * while (attempts < maxAttempts) {\n * try {\n * attempts++\n * ctx.setAttribute('http.request.resend_count', attempts - 1)\n *\n * const response = await axios.post('https://webhook.example.com/events', payload)\n * ctx.setAttribute('http.response.status_code', response.status)\n * return response.data\n * } catch (error) {\n * if (attempts >= maxAttempts) throw error\n * await new Promise(resolve => setTimeout(resolve, 1000 * attempts))\n * }\n * }\n * })\n * ```\n *\n * @public\n */\nexport function traceHTTP<TArgs extends unknown[], TReturn>(\n config: HTTPConfig,\n) {\n return (\n fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n ): ((...args: TArgs) => Promise<TReturn>) => {\n return trace<TArgs, TReturn>((ctx) => {\n // Set semantic convention attributes\n if (config.method) {\n ctx.setAttribute('http.request.method', config.method);\n }\n if (config.url) {\n ctx.setAttribute('url.full', config.url);\n }\n if (config.attributes) {\n for (const [key, value] of Object.entries(config.attributes)) {\n if (value !== undefined && value !== null) {\n // setAttribute only accepts primitives (string | number | boolean)\n // Arrays and objects should be serialized\n const attrValue =\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ? value\n : JSON.stringify(value);\n ctx.setAttribute(key, attrValue);\n }\n }\n }\n\n // Call the user's factory to get their function and return it\n return fnFactory(ctx);\n });\n };\n}\n\n/**\n * Trace messaging operations with Messaging semantic conventions\n *\n * Automatically adds standard attributes for messaging:\n * - messaging.system\n * - messaging.operation\n * - messaging.destination.name\n *\n * **Use Cases:**\n * - Publishing messages to queues/topics\n * - Consuming messages from queues/topics\n * - Event-driven architectures\n *\n * @param config - Messaging operation configuration\n * @returns Traced function factory with Messaging attributes\n *\n * @example Publishing to Kafka\n * ```typescript\n * import { traceMessaging } from 'autotel/semantic-helpers'\n * import { kafka } from './kafka'\n *\n * const producer = kafka.producer()\n *\n * export const publishEvent = traceMessaging({\n * system: 'kafka',\n * operation: 'publish',\n * destination: 'user-events'\n * })(ctx => async (event: { type: string; userId: string; data: object }) => {\n * ctx.setAttribute('messaging.message.type', event.type)\n * ctx.setAttribute('messaging.kafka.partition', 0)\n *\n * await producer.send({\n * topic: 'user-events',\n * messages: [\n * {\n * key: event.userId,\n * value: JSON.stringify(event.data)\n * }\n * ]\n * })\n *\n * ctx.setAttribute('messaging.message.id', event.userId)\n * })\n * ```\n *\n * @example Consuming from RabbitMQ\n * ```typescript\n * import { traceMessaging } from 'autotel/semantic-helpers'\n * import { channel } from './rabbitmq'\n *\n * export const processOrder = traceMessaging({\n * system: 'rabbitmq',\n * operation: 'process',\n * destination: 'orders'\n * })(ctx => async (message: { orderId: string; items: object[] }) => {\n * ctx.setAttribute('messaging.message.id', message.orderId)\n * ctx.setAttribute('messaging.message.body.size', JSON.stringify(message).length)\n *\n * // Process order logic\n * const result = await processOrderInternal(message)\n *\n * ctx.setAttribute('messaging.operation.result', 'success')\n * return result\n * })\n * ```\n *\n * @example AWS SQS with batch processing\n * ```typescript\n * import { traceMessaging } from 'autotel/semantic-helpers'\n * import { SQS } from '@aws-sdk/client-sqs'\n *\n * const sqs = new SQS()\n *\n * export const sendBatch = traceMessaging({\n * system: 'aws_sqs',\n * operation: 'publish',\n * destination: 'notifications-queue'\n * })(ctx => async (messages: Array<{ id: string; body: object }>) => {\n * ctx.setAttribute('messaging.batch.message_count', messages.length)\n *\n * const result = await sqs.sendMessageBatch({\n * QueueUrl: process.env.QUEUE_URL,\n * Entries: messages.map(msg => ({\n * Id: msg.id,\n * MessageBody: JSON.stringify(msg.body)\n * }))\n * })\n *\n * ctx.setAttribute('messaging.operation.success_count', result.Successful?.length || 0)\n * ctx.setAttribute('messaging.operation.failed_count', result.Failed?.length || 0)\n *\n * return result\n * })\n * ```\n *\n * @public\n */\nexport function traceMessaging<TArgs extends unknown[], TReturn>(\n config: MessagingConfig,\n) {\n return (\n fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n ): ((...args: TArgs) => Promise<TReturn>) => {\n return trace<TArgs, TReturn>((ctx) => {\n // Set semantic convention attributes\n ctx.setAttribute('messaging.system', config.system);\n if (config.operation) {\n ctx.setAttribute('messaging.operation', config.operation);\n }\n if (config.destination) {\n ctx.setAttribute('messaging.destination.name', config.destination);\n }\n if (config.attributes) {\n for (const [key, value] of Object.entries(config.attributes)) {\n if (value !== undefined && value !== null) {\n // setAttribute only accepts primitives (string | number | boolean)\n // Arrays and objects should be serialized\n const attrValue =\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ? value\n : JSON.stringify(value);\n ctx.setAttribute(key, attrValue);\n }\n }\n }\n\n // Call the user's factory to get their function and return it\n return fnFactory(ctx);\n });\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/semantic-helpers.ts"],"names":[],"mappings":"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","file":"chunk-52PUSFC2.js","sourcesContent":["/**\n * Semantic convention helpers for OpenTelemetry\n *\n * Pre-configured trace helpers that follow OpenTelemetry semantic conventions\n * for common operation types. Reduces boilerplate and ensures consistency.\n *\n * Based on: https://opentelemetry.io/docs/specs/semconv/\n */\n\nimport { trace } from './functional';\nimport type { TraceContext } from './trace-context';\nimport type { Attributes } from '@opentelemetry/api';\n\n/**\n * Configuration for LLM (Large Language Model) operations\n *\n * Follows Gen AI semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/gen-ai/\n */\nexport interface LLMConfig {\n /** Model name (e.g., 'gpt-4', 'claude-3-opus') */\n model: string;\n /** Operation type */\n operation?: 'chat' | 'completion' | 'embedding';\n /** Model provider (e.g., 'openai', 'anthropic', 'cohere') - maps to gen.ai.system */\n provider?: string;\n /** Additional attributes to add to the span */\n attributes?: Attributes;\n}\n\n/**\n * Configuration for database operations\n *\n * Follows DB semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/database/\n */\nexport interface DBConfig {\n /** Database system (e.g., 'postgresql', 'mongodb', 'redis') */\n system: string;\n /** Operation type (e.g., 'SELECT', 'INSERT', 'find', 'get') */\n operation?: string;\n /** Database name */\n database?: string;\n /** Collection/table name */\n collection?: string;\n /** Additional attributes to add to the span */\n attributes?: Attributes;\n}\n\n/**\n * Configuration for HTTP client operations\n *\n * Follows HTTP semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/http/\n */\nexport interface HTTPConfig {\n /** HTTP method (e.g., 'GET', 'POST') */\n method?: string;\n /** Target URL or URL template */\n url?: string;\n /** Additional attributes to add to the span */\n attributes?: Attributes;\n}\n\n/**\n * Configuration for messaging operations\n *\n * Follows Messaging semantic conventions:\n * https://opentelemetry.io/docs/specs/semconv/messaging/\n */\nexport interface MessagingConfig {\n /** Messaging system (e.g., 'kafka', 'rabbitmq', 'sqs') */\n system: string;\n /** Operation type */\n operation?: 'publish' | 'receive' | 'process';\n /** Destination name (queue/topic) */\n destination?: string;\n /** Additional attributes to add to the span */\n attributes?: Attributes;\n}\n\n/**\n * Trace LLM operations with Gen AI semantic conventions\n *\n * Automatically adds standard attributes for LLM operations:\n * - gen.ai.request.model\n * - gen.ai.operation.name\n * - gen.ai.system\n *\n * **Use Cases:**\n * - Chat completions\n * - Text generation\n * - Embeddings\n * - Multi-step LLM workflows\n *\n * @param config - LLM operation configuration\n * @returns Traced function factory with Gen AI attributes\n *\n * @example Chat completion with OpenAI\n * ```typescript\n * import { traceLLM } from 'autotel/semantic-helpers'\n * import OpenAI from 'openai'\n *\n * const openai = new OpenAI()\n *\n * export const generateResponse = traceLLM({\n * model: 'gpt-4-turbo',\n * operation: 'chat',\n * provider: 'openai'\n * })(ctx => async (prompt: string) => {\n * const response = await openai.chat.completions.create({\n * model: 'gpt-4-turbo',\n * messages: [{ role: 'user', content: prompt }]\n * })\n *\n * // Add usage metrics to span\n * ctx.setAttribute('gen.ai.usage.completion_tokens', response.usage?.completion_tokens)\n * ctx.setAttribute('gen.ai.usage.prompt_tokens', response.usage?.prompt_tokens)\n *\n * return response.choices[0].message.content\n * })\n * ```\n *\n * @example Anthropic Claude with streaming\n * ```typescript\n * import { traceLLM } from 'autotel/semantic-helpers'\n * import Anthropic from '@anthropic-ai/sdk'\n *\n * const anthropic = new Anthropic()\n *\n * export const streamResponse = traceLLM({\n * model: 'claude-3-opus-20240229',\n * operation: 'chat',\n * provider: 'anthropic'\n * })(ctx => async function* (prompt: string) {\n * const stream = await anthropic.messages.create({\n * model: 'claude-3-opus-20240229',\n * messages: [{ role: 'user', content: prompt }],\n * stream: true,\n * max_tokens: 1024\n * })\n *\n * let totalTokens = 0\n * for await (const event of stream) {\n * if (event.type === 'content_block_delta') {\n * yield event.delta.text\n * }\n * if (event.type === 'message_stop') {\n * ctx.setAttribute('gen.ai.usage.completion_tokens', event.message.usage.output_tokens)\n * totalTokens = event.message.usage.output_tokens\n * }\n * }\n *\n * return totalTokens\n * })\n * ```\n *\n * @example Embeddings\n * ```typescript\n * import { traceLLM } from 'autotel/semantic-helpers'\n * import { OpenAIEmbeddings } from '@langchain/openai'\n *\n * const embeddings = new OpenAIEmbeddings()\n *\n * export const embed = traceLLM({\n * model: 'text-embedding-3-small',\n * operation: 'embedding',\n * provider: 'openai'\n * })(ctx => async (text: string) => {\n * const result = await embeddings.embedQuery(text)\n * ctx.setAttribute('gen.ai.response.embedding_length', result.length)\n * return result\n * })\n * ```\n *\n * @public\n */\nexport function traceLLM<TArgs extends unknown[], TReturn>(config: LLMConfig) {\n return (\n fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n ): ((...args: TArgs) => Promise<TReturn>) => {\n return trace<TArgs, TReturn>((ctx) => {\n // Set semantic convention attributes\n ctx.setAttribute('gen.ai.request.model', config.model);\n ctx.setAttribute('gen.ai.operation.name', config.operation || 'chat');\n if (config.provider) {\n ctx.setAttribute('gen.ai.system', config.provider);\n }\n if (config.attributes) {\n for (const [key, value] of Object.entries(config.attributes)) {\n if (value !== undefined && value !== null) {\n // setAttribute only accepts primitives (string | number | boolean)\n // Arrays and objects should be serialized\n const attrValue =\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ? value\n : JSON.stringify(value);\n ctx.setAttribute(key, attrValue);\n }\n }\n }\n\n // Call the user's factory to get their function and return it\n return fnFactory(ctx);\n });\n };\n}\n\n/**\n * Trace database operations with DB semantic conventions\n *\n * Automatically adds standard attributes for database operations:\n * - db.system\n * - db.operation\n * - db.name\n * - db.collection.name (for NoSQL)\n *\n * **Use Cases:**\n * - SQL queries (PostgreSQL, MySQL, SQLite)\n * - NoSQL operations (MongoDB, DynamoDB, Redis)\n * - ORM queries (Prisma, TypeORM, Drizzle)\n *\n * @param config - Database operation configuration\n * @returns Traced function factory with DB attributes\n *\n * @example PostgreSQL query\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { pool } from './db'\n *\n * export const getUser = traceDB({\n * system: 'postgresql',\n * operation: 'SELECT',\n * database: 'app_db',\n * collection: 'users'\n * })(ctx => async (userId: string) => {\n * const query = 'SELECT * FROM users WHERE id = $1'\n * ctx.setAttribute('db.statement', query)\n *\n * const result = await pool.query(query, [userId])\n * ctx.setAttribute('db.rows_affected', result.rowCount)\n *\n * return result.rows[0]\n * })\n * ```\n *\n * @example MongoDB with Mongoose\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { User } from './models/User'\n *\n * export const findUsers = traceDB({\n * system: 'mongodb',\n * operation: 'find',\n * database: 'app_db',\n * collection: 'users'\n * })(ctx => async (filter: object) => {\n * ctx.setAttribute('db.mongodb.filter', JSON.stringify(filter))\n *\n * const users = await User.find(filter).limit(100)\n * ctx.setAttribute('db.response.count', users.length)\n *\n * return users\n * })\n * ```\n *\n * @example Redis operations\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { redis } from './redis'\n *\n * export const cacheGet = traceDB({\n * system: 'redis',\n * operation: 'GET'\n * })(ctx => async (key: string) => {\n * ctx.setAttribute('db.redis.key', key)\n *\n * const value = await redis.get(key)\n * ctx.setAttribute('db.response.cache_hit', value !== null)\n *\n * return value\n * })\n * ```\n *\n * @example Prisma with detailed query info\n * ```typescript\n * import { traceDB } from 'autotel/semantic-helpers'\n * import { prisma } from './prisma'\n *\n * export const createPost = traceDB({\n * system: 'postgresql',\n * operation: 'INSERT',\n * database: 'app_db',\n * collection: 'posts'\n * })(ctx => async (data: { title: string; content: string; authorId: string }) => {\n * ctx.setAttribute('db.prisma.model', 'Post')\n * ctx.setAttribute('db.prisma.action', 'create')\n *\n * const post = await prisma.post.create({ data })\n *\n * ctx.setAttribute('db.response.id', post.id)\n * return post\n * })\n * ```\n *\n * @public\n */\nexport function traceDB<TArgs extends unknown[], TReturn>(config: DBConfig) {\n return (\n fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n ): ((...args: TArgs) => Promise<TReturn>) => {\n return trace<TArgs, TReturn>((ctx) => {\n // Set semantic convention attributes\n ctx.setAttribute('db.system', config.system);\n if (config.operation) {\n ctx.setAttribute('db.operation', config.operation);\n }\n if (config.database) {\n ctx.setAttribute('db.name', config.database);\n }\n if (config.collection) {\n ctx.setAttribute('db.collection.name', config.collection);\n }\n if (config.attributes) {\n for (const [key, value] of Object.entries(config.attributes)) {\n if (value !== undefined && value !== null) {\n // setAttribute only accepts primitives (string | number | boolean)\n // Arrays and objects should be serialized\n const attrValue =\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ? value\n : JSON.stringify(value);\n ctx.setAttribute(key, attrValue);\n }\n }\n }\n\n // Call the user's factory to get their function and return it\n return fnFactory(ctx);\n });\n };\n}\n\n/**\n * Trace HTTP client operations with HTTP semantic conventions\n *\n * Automatically adds standard attributes for HTTP requests:\n * - http.request.method\n * - url.full\n *\n * **Use Cases:**\n * - External API calls\n * - Microservice communication\n * - Third-party integrations\n *\n * @param config - HTTP operation configuration\n * @returns Traced function factory with HTTP attributes\n *\n * @example Fetch API\n * ```typescript\n * import { traceHTTP } from 'autotel/semantic-helpers'\n *\n * export const fetchUser = traceHTTP({\n * method: 'GET',\n * url: 'https://api.example.com/users/:id'\n * })(ctx => async (userId: string) => {\n * const url = `https://api.example.com/users/${userId}`\n * ctx.setAttribute('url.full', url)\n *\n * const response = await fetch(url)\n * ctx.setAttribute('http.response.status_code', response.status)\n *\n * if (!response.ok) {\n * ctx.setAttribute('error', true)\n * throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n * }\n *\n * return response.json()\n * })\n * ```\n *\n * @example Axios with retry logic\n * ```typescript\n * import { traceHTTP } from 'autotel/semantic-helpers'\n * import axios from 'axios'\n *\n * export const sendWebhook = traceHTTP({\n * method: 'POST',\n * url: 'https://webhook.example.com/events'\n * })(ctx => async (payload: object) => {\n * let attempts = 0\n * const maxAttempts = 3\n *\n * while (attempts < maxAttempts) {\n * try {\n * attempts++\n * ctx.setAttribute('http.request.resend_count', attempts - 1)\n *\n * const response = await axios.post('https://webhook.example.com/events', payload)\n * ctx.setAttribute('http.response.status_code', response.status)\n * return response.data\n * } catch (error) {\n * if (attempts >= maxAttempts) throw error\n * await new Promise(resolve => setTimeout(resolve, 1000 * attempts))\n * }\n * }\n * })\n * ```\n *\n * @public\n */\nexport function traceHTTP<TArgs extends unknown[], TReturn>(\n config: HTTPConfig,\n) {\n return (\n fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n ): ((...args: TArgs) => Promise<TReturn>) => {\n return trace<TArgs, TReturn>((ctx) => {\n // Set semantic convention attributes\n if (config.method) {\n ctx.setAttribute('http.request.method', config.method);\n }\n if (config.url) {\n ctx.setAttribute('url.full', config.url);\n }\n if (config.attributes) {\n for (const [key, value] of Object.entries(config.attributes)) {\n if (value !== undefined && value !== null) {\n // setAttribute only accepts primitives (string | number | boolean)\n // Arrays and objects should be serialized\n const attrValue =\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ? value\n : JSON.stringify(value);\n ctx.setAttribute(key, attrValue);\n }\n }\n }\n\n // Call the user's factory to get their function and return it\n return fnFactory(ctx);\n });\n };\n}\n\n/**\n * Trace messaging operations with Messaging semantic conventions\n *\n * Automatically adds standard attributes for messaging:\n * - messaging.system\n * - messaging.operation\n * - messaging.destination.name\n *\n * **Use Cases:**\n * - Publishing messages to queues/topics\n * - Consuming messages from queues/topics\n * - Event-driven architectures\n *\n * @param config - Messaging operation configuration\n * @returns Traced function factory with Messaging attributes\n *\n * @example Publishing to Kafka\n * ```typescript\n * import { traceMessaging } from 'autotel/semantic-helpers'\n * import { kafka } from './kafka'\n *\n * const producer = kafka.producer()\n *\n * export const publishEvent = traceMessaging({\n * system: 'kafka',\n * operation: 'publish',\n * destination: 'user-events'\n * })(ctx => async (event: { type: string; userId: string; data: object }) => {\n * ctx.setAttribute('messaging.message.type', event.type)\n * ctx.setAttribute('messaging.kafka.partition', 0)\n *\n * await producer.send({\n * topic: 'user-events',\n * messages: [\n * {\n * key: event.userId,\n * value: JSON.stringify(event.data)\n * }\n * ]\n * })\n *\n * ctx.setAttribute('messaging.message.id', event.userId)\n * })\n * ```\n *\n * @example Consuming from RabbitMQ\n * ```typescript\n * import { traceMessaging } from 'autotel/semantic-helpers'\n * import { channel } from './rabbitmq'\n *\n * export const processOrder = traceMessaging({\n * system: 'rabbitmq',\n * operation: 'process',\n * destination: 'orders'\n * })(ctx => async (message: { orderId: string; items: object[] }) => {\n * ctx.setAttribute('messaging.message.id', message.orderId)\n * ctx.setAttribute('messaging.message.body.size', JSON.stringify(message).length)\n *\n * // Process order logic\n * const result = await processOrderInternal(message)\n *\n * ctx.setAttribute('messaging.operation.result', 'success')\n * return result\n * })\n * ```\n *\n * @example AWS SQS with batch processing\n * ```typescript\n * import { traceMessaging } from 'autotel/semantic-helpers'\n * import { SQS } from '@aws-sdk/client-sqs'\n *\n * const sqs = new SQS()\n *\n * export const sendBatch = traceMessaging({\n * system: 'aws_sqs',\n * operation: 'publish',\n * destination: 'notifications-queue'\n * })(ctx => async (messages: Array<{ id: string; body: object }>) => {\n * ctx.setAttribute('messaging.batch.message_count', messages.length)\n *\n * const result = await sqs.sendMessageBatch({\n * QueueUrl: process.env.QUEUE_URL,\n * Entries: messages.map(msg => ({\n * Id: msg.id,\n * MessageBody: JSON.stringify(msg.body)\n * }))\n * })\n *\n * ctx.setAttribute('messaging.operation.success_count', result.Successful?.length || 0)\n * ctx.setAttribute('messaging.operation.failed_count', result.Failed?.length || 0)\n *\n * return result\n * })\n * ```\n *\n * @public\n */\nexport function traceMessaging<TArgs extends unknown[], TReturn>(\n config: MessagingConfig,\n) {\n return (\n fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,\n ): ((...args: TArgs) => Promise<TReturn>) => {\n return trace<TArgs, TReturn>((ctx) => {\n // Set semantic convention attributes\n ctx.setAttribute('messaging.system', config.system);\n if (config.operation) {\n ctx.setAttribute('messaging.operation', config.operation);\n }\n if (config.destination) {\n ctx.setAttribute('messaging.destination.name', config.destination);\n }\n if (config.attributes) {\n for (const [key, value] of Object.entries(config.attributes)) {\n if (value !== undefined && value !== null) {\n // setAttribute only accepts primitives (string | number | boolean)\n // Arrays and objects should be serialized\n const attrValue =\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n ? value\n : JSON.stringify(value);\n ctx.setAttribute(key, attrValue);\n }\n }\n }\n\n // Call the user's factory to get their function and return it\n return fnFactory(ctx);\n });\n };\n}\n"]}