autotel 3.7.0 → 4.1.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 (132) hide show
  1. package/README.md +26 -1
  2. package/dist/{attributes-ksn4HVbd.js → attributes-CmYpdqCN.js} +2 -11
  3. package/dist/attributes-CmYpdqCN.js.map +1 -0
  4. package/dist/{attributes-D3etyRVc.cjs → attributes-PZ5doLgw.cjs} +2 -11
  5. package/dist/attributes-PZ5doLgw.cjs.map +1 -0
  6. package/dist/attributes.cjs +1 -1
  7. package/dist/attributes.d.cts +2 -2
  8. package/dist/attributes.d.ts +2 -2
  9. package/dist/attributes.js +1 -1
  10. package/dist/auto.cjs +2 -2
  11. package/dist/auto.js +1 -1
  12. package/dist/correlation-id.cjs +1 -1
  13. package/dist/correlation-id.js +1 -1
  14. package/dist/decorators.cjs +1 -1
  15. package/dist/decorators.js +1 -1
  16. package/dist/{event-Dlqr4ZNL.cjs → event-BhHREDJk.cjs} +3 -3
  17. package/dist/{event-Dlqr4ZNL.cjs.map → event-BhHREDJk.cjs.map} +1 -1
  18. package/dist/{event-_58ryBjh.js → event-ByBTV9M2.js} +3 -3
  19. package/dist/{event-_58ryBjh.js.map → event-ByBTV9M2.js.map} +1 -1
  20. package/dist/event.cjs +1 -1
  21. package/dist/event.js +1 -1
  22. package/dist/{functional-BGkT8J-h.js → functional-DtI0u4vx.js} +19 -19
  23. package/dist/functional-DtI0u4vx.js.map +1 -0
  24. package/dist/{functional-C4CzoVrX.cjs → functional-zpzNLhky.cjs} +4 -4
  25. package/dist/{functional-C4CzoVrX.cjs.map → functional-zpzNLhky.cjs.map} +1 -1
  26. package/dist/functional.cjs +1 -1
  27. package/dist/functional.js +1 -1
  28. package/dist/http.cjs +1 -1
  29. package/dist/http.js +1 -1
  30. package/dist/{index-CX0aG1Uh.d.ts → index-Ck06vlW2.d.ts} +2 -32
  31. package/dist/index-Ck06vlW2.d.ts.map +1 -0
  32. package/dist/{index-DIWZFKUS.d.cts → index-eKuioqT1.d.cts} +2 -32
  33. package/dist/index-eKuioqT1.d.cts.map +1 -0
  34. package/dist/index.cjs +7 -351
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +4 -172
  37. package/dist/index.d.cts.map +1 -1
  38. package/dist/index.d.ts +4 -172
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +9 -338
  41. package/dist/index.js.map +1 -1
  42. package/dist/{init-DJQOdVlN.d.ts → init-B7u-DjxM.d.ts} +57 -2
  43. package/dist/init-B7u-DjxM.d.ts.map +1 -0
  44. package/dist/{init-DvapOXCc.cjs → init-BX7AmFRl.cjs} +40 -21
  45. package/dist/init-BX7AmFRl.cjs.map +1 -0
  46. package/dist/{init-Ch6t7MNI.js → init-D-jnNMix.js} +39 -20
  47. package/dist/init-D-jnNMix.js.map +1 -0
  48. package/dist/{init-CNp-ee80.d.cts → init-DSrRmVnz.d.cts} +57 -2
  49. package/dist/init-DSrRmVnz.d.cts.map +1 -0
  50. package/dist/instrumentation.cjs +1 -1
  51. package/dist/instrumentation.js +1 -1
  52. package/dist/logger-D3Ej3DII.js +446 -0
  53. package/dist/logger-D3Ej3DII.js.map +1 -0
  54. package/dist/logger-thMPLpOG.cjs +487 -0
  55. package/dist/logger-thMPLpOG.cjs.map +1 -0
  56. package/dist/logger.cjs +8 -236
  57. package/dist/logger.js +2 -204
  58. package/dist/messaging.cjs +1 -1
  59. package/dist/messaging.js +1 -1
  60. package/dist/{registry-DfXA3R1L.js → registry-DVSmWg6Y.js} +2 -11
  61. package/dist/registry-DVSmWg6Y.js.map +1 -0
  62. package/dist/{registry-JZg2J3RZ.cjs → registry-DYgvb62e.cjs} +1 -16
  63. package/dist/registry-DYgvb62e.cjs.map +1 -0
  64. package/dist/semantic-conventions.cjs +1 -1
  65. package/dist/semantic-conventions.js +1 -1
  66. package/dist/semantic-helpers.cjs +1 -114
  67. package/dist/semantic-helpers.cjs.map +1 -1
  68. package/dist/semantic-helpers.d.cts +1 -114
  69. package/dist/semantic-helpers.d.cts.map +1 -1
  70. package/dist/semantic-helpers.d.ts +1 -114
  71. package/dist/semantic-helpers.d.ts.map +1 -1
  72. package/dist/semantic-helpers.js +2 -114
  73. package/dist/semantic-helpers.js.map +1 -1
  74. package/dist/{track-3HY4NGV-.cjs → track-D59FfpL0.cjs} +2 -2
  75. package/dist/{track-3HY4NGV-.cjs.map → track-D59FfpL0.cjs.map} +1 -1
  76. package/dist/{track-nsKVy-pj.js → track-wc0HafS_.js} +6 -6
  77. package/dist/track-wc0HafS_.js.map +1 -0
  78. package/dist/webhook.cjs +1 -1
  79. package/dist/webhook.js +1 -1
  80. package/dist/workflow-distributed.cjs +1 -1
  81. package/dist/workflow-distributed.js +1 -1
  82. package/dist/workflow.cjs +1 -1
  83. package/dist/workflow.js +1 -1
  84. package/dist/{yaml-config-B3dQ82GR.cjs → yaml-config-Ck2uB0Dp.cjs} +2 -1
  85. package/dist/yaml-config-Ck2uB0Dp.cjs.map +1 -0
  86. package/dist/yaml-config.cjs +1 -1
  87. package/dist/yaml-config.d.cts +7 -1
  88. package/dist/yaml-config.d.cts.map +1 -1
  89. package/dist/yaml-config.d.ts +7 -1
  90. package/dist/yaml-config.d.ts.map +1 -1
  91. package/dist/yaml-config.js +1 -0
  92. package/dist/yaml-config.js.map +1 -1
  93. package/package.json +1 -1
  94. package/skills/analyze-traces/SKILL.md +14 -12
  95. package/skills/autotel-core/SKILL.md +2 -0
  96. package/skills/autotel-instrumentation/SKILL.md +25 -0
  97. package/skills/debug-missing-spans/SKILL.md +3 -1
  98. package/skills/migrate-to-autotel/SKILL.md +24 -23
  99. package/skills/review-otel-patterns/SKILL.md +9 -6
  100. package/skills/tune-sampling/SKILL.md +8 -3
  101. package/src/attributes/builders.ts +2 -20
  102. package/src/attributes/index.ts +0 -1
  103. package/src/attributes/registry.ts +2 -9
  104. package/src/attributes/types.ts +0 -8
  105. package/src/index.ts +4 -41
  106. package/src/init.customization.test.ts +71 -0
  107. package/src/init.ts +167 -40
  108. package/src/semantic-helpers.test.ts +2 -87
  109. package/src/semantic-helpers.ts +0 -146
  110. package/src/yaml-config.test.ts +36 -0
  111. package/src/yaml-config.ts +10 -1
  112. package/dist/attributes-D3etyRVc.cjs.map +0 -1
  113. package/dist/attributes-ksn4HVbd.js.map +0 -1
  114. package/dist/functional-BGkT8J-h.js.map +0 -1
  115. package/dist/index-CX0aG1Uh.d.ts.map +0 -1
  116. package/dist/index-DIWZFKUS.d.cts.map +0 -1
  117. package/dist/init-CNp-ee80.d.cts.map +0 -1
  118. package/dist/init-Ch6t7MNI.js.map +0 -1
  119. package/dist/init-DJQOdVlN.d.ts.map +0 -1
  120. package/dist/init-DvapOXCc.cjs.map +0 -1
  121. package/dist/logger.cjs.map +0 -1
  122. package/dist/logger.js.map +0 -1
  123. package/dist/registry-DfXA3R1L.js.map +0 -1
  124. package/dist/registry-JZg2J3RZ.cjs.map +0 -1
  125. package/dist/track-nsKVy-pj.js.map +0 -1
  126. package/dist/yaml-config-B3dQ82GR.cjs.map +0 -1
  127. package/src/gen-ai-cost.test.ts +0 -81
  128. package/src/gen-ai-cost.ts +0 -145
  129. package/src/gen-ai-events.test.ts +0 -135
  130. package/src/gen-ai-events.ts +0 -208
  131. package/src/gen-ai-metrics.test.ts +0 -96
  132. package/src/gen-ai-metrics.ts +0 -128
@@ -3,12 +3,7 @@
3
3
  */
4
4
 
5
5
  import { describe, it, expect, beforeEach } from 'vitest';
6
- import {
7
- traceLLM,
8
- traceDB,
9
- traceHTTP,
10
- traceMessaging,
11
- } from './semantic-helpers';
6
+ import { traceDB, traceHTTP, traceMessaging } from './semantic-helpers';
12
7
  import { createTraceCollector } from './testing';
13
8
 
14
9
  describe('Semantic Helpers', () => {
@@ -18,69 +13,7 @@ describe('Semantic Helpers', () => {
18
13
  collector = createTraceCollector();
19
14
  });
20
15
 
21
- describe('traceLLM', () => {
22
- it('should add Gen AI semantic convention attributes', async () => {
23
- const generateText = traceLLM({
24
- model: 'gpt-4',
25
- operation: 'chat',
26
- provider: 'openai',
27
- })((_ctx) => async (prompt: string) => {
28
- return `Response to: ${prompt}`;
29
- });
30
-
31
- await generateText('Hello');
32
-
33
- const spans = collector.getSpans();
34
- expect(spans).toHaveLength(1);
35
-
36
- const span = spans[0];
37
- expect(span.attributes['gen.ai.request.model']).toBe('gpt-4');
38
- expect(span.attributes['gen.ai.operation.name']).toBe('chat');
39
- expect(span.attributes['gen.ai.system']).toBe('openai');
40
- });
41
-
42
- it('should use default operation when not specified', async () => {
43
- const generateText = traceLLM({
44
- model: 'claude-3',
45
- })((_ctx) => async () => 'result');
46
-
47
- await generateText();
48
-
49
- const spans = collector.getSpans();
50
- expect(spans[0].attributes['gen.ai.operation.name']).toBe('chat');
51
- });
52
-
53
- it('should support embedding operation', async () => {
54
- const embed = traceLLM({
55
- model: 'text-embedding-3-small',
56
- operation: 'embedding',
57
- provider: 'openai',
58
- })((_ctx) => async (_text: string) => [0.1, 0.2, 0.3]);
59
-
60
- await embed('test text');
61
-
62
- const spans = collector.getSpans();
63
- expect(spans[0].attributes['gen.ai.operation.name']).toBe('embedding');
64
- });
65
-
66
- it('should support additional custom attributes', async () => {
67
- const generateText = traceLLM({
68
- model: 'gpt-4',
69
- attributes: {
70
- 'custom.attribute': 'custom-value',
71
- 'custom.number': 123,
72
- },
73
- })((_ctx) => async () => 'result');
74
-
75
- await generateText();
76
-
77
- const spans = collector.getSpans();
78
- const span = spans[0];
79
- expect(span.attributes['gen.ai.request.model']).toBe('gpt-4');
80
- expect(span.attributes['custom.attribute']).toBe('custom-value');
81
- expect(span.attributes['custom.number']).toBe(123);
82
- });
83
- });
16
+ // GenAI/LLM helpers (`traceLLM`) moved to the `autotel-genai` package.
84
17
 
85
18
  describe('traceDB', () => {
86
19
  it('should add DB semantic convention attributes', async () => {
@@ -273,24 +206,6 @@ describe('Semantic Helpers', () => {
273
206
  });
274
207
 
275
208
  describe('Attribute merging', () => {
276
- it('should merge custom attributes with semantic attributes in traceLLM', async () => {
277
- const fn = traceLLM({
278
- model: 'gpt-4',
279
- attributes: {
280
- 'gen.ai.request.temperature': 0.7,
281
- 'custom.attr': 'value',
282
- },
283
- })((_ctx) => async () => 'result');
284
-
285
- await fn();
286
-
287
- const spans = collector.getSpans();
288
- const span = spans[0];
289
- expect(span.attributes['gen.ai.request.model']).toBe('gpt-4');
290
- expect(span.attributes['gen.ai.request.temperature']).toBe(0.7);
291
- expect(span.attributes['custom.attr']).toBe('value');
292
- });
293
-
294
209
  it('should allow custom attributes to override semantic defaults', async () => {
295
210
  const fn = traceDB({
296
211
  system: 'postgresql',
@@ -11,23 +11,6 @@ import { trace } from './functional';
11
11
  import type { TraceContext } from './trace-context';
12
12
  import type { Attributes } from '@opentelemetry/api';
13
13
 
14
- /**
15
- * Configuration for LLM (Large Language Model) operations
16
- *
17
- * Follows Gen AI semantic conventions:
18
- * https://opentelemetry.io/docs/specs/semconv/gen-ai/
19
- */
20
- export interface LLMConfig {
21
- /** Model name (e.g., 'gpt-4', 'claude-3-opus') */
22
- model: string;
23
- /** Operation type */
24
- operation?: 'chat' | 'completion' | 'embedding';
25
- /** Model provider (e.g., 'openai', 'anthropic', 'cohere') - maps to gen.ai.system */
26
- provider?: string;
27
- /** Additional attributes to add to the span */
28
- attributes?: Attributes;
29
- }
30
-
31
14
  /**
32
15
  * Configuration for database operations
33
16
  *
@@ -79,135 +62,6 @@ export interface MessagingConfig {
79
62
  attributes?: Attributes;
80
63
  }
81
64
 
82
- /**
83
- * Trace LLM operations with Gen AI semantic conventions
84
- *
85
- * Automatically adds standard attributes for LLM operations:
86
- * - gen.ai.request.model
87
- * - gen.ai.operation.name
88
- * - gen.ai.system
89
- *
90
- * **Use Cases:**
91
- * - Chat completions
92
- * - Text generation
93
- * - Embeddings
94
- * - Multi-step LLM workflows
95
- *
96
- * @param config - LLM operation configuration
97
- * @returns Traced function factory with Gen AI attributes
98
- *
99
- * @example Chat completion with OpenAI
100
- * ```typescript
101
- * import { traceLLM } from 'autotel/semantic-helpers'
102
- * import OpenAI from 'openai'
103
- *
104
- * const openai = new OpenAI()
105
- *
106
- * export const generateResponse = traceLLM({
107
- * model: 'gpt-4-turbo',
108
- * operation: 'chat',
109
- * provider: 'openai'
110
- * })(ctx => async (prompt: string) => {
111
- * const response = await openai.chat.completions.create({
112
- * model: 'gpt-4-turbo',
113
- * messages: [{ role: 'user', content: prompt }]
114
- * })
115
- *
116
- * // Add usage metrics to span
117
- * ctx.setAttribute('gen.ai.usage.completion_tokens', response.usage?.completion_tokens)
118
- * ctx.setAttribute('gen.ai.usage.prompt_tokens', response.usage?.prompt_tokens)
119
- *
120
- * return response.choices[0].message.content
121
- * })
122
- * ```
123
- *
124
- * @example Anthropic Claude with streaming
125
- * ```typescript
126
- * import { traceLLM } from 'autotel/semantic-helpers'
127
- * import Anthropic from '@anthropic-ai/sdk'
128
- *
129
- * const anthropic = new Anthropic()
130
- *
131
- * export const streamResponse = traceLLM({
132
- * model: 'claude-3-opus-20240229',
133
- * operation: 'chat',
134
- * provider: 'anthropic'
135
- * })(ctx => async function* (prompt: string) {
136
- * const stream = await anthropic.messages.create({
137
- * model: 'claude-3-opus-20240229',
138
- * messages: [{ role: 'user', content: prompt }],
139
- * stream: true,
140
- * max_tokens: 1024
141
- * })
142
- *
143
- * let totalTokens = 0
144
- * for await (const event of stream) {
145
- * if (event.type === 'content_block_delta') {
146
- * yield event.delta.text
147
- * }
148
- * if (event.type === 'message_stop') {
149
- * ctx.setAttribute('gen.ai.usage.completion_tokens', event.message.usage.output_tokens)
150
- * totalTokens = event.message.usage.output_tokens
151
- * }
152
- * }
153
- *
154
- * return totalTokens
155
- * })
156
- * ```
157
- *
158
- * @example Embeddings
159
- * ```typescript
160
- * import { traceLLM } from 'autotel/semantic-helpers'
161
- * import { OpenAIEmbeddings } from '@langchain/openai'
162
- *
163
- * const embeddings = new OpenAIEmbeddings()
164
- *
165
- * export const embed = traceLLM({
166
- * model: 'text-embedding-3-small',
167
- * operation: 'embedding',
168
- * provider: 'openai'
169
- * })(ctx => async (text: string) => {
170
- * const result = await embeddings.embedQuery(text)
171
- * ctx.setAttribute('gen.ai.response.embedding_length', result.length)
172
- * return result
173
- * })
174
- * ```
175
- *
176
- * @public
177
- */
178
- export function traceLLM<TArgs extends unknown[], TReturn>(config: LLMConfig) {
179
- return (
180
- fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>,
181
- ): ((...args: TArgs) => Promise<TReturn>) => {
182
- return trace<TArgs, TReturn>((ctx) => {
183
- // Set semantic convention attributes
184
- ctx.setAttribute('gen.ai.request.model', config.model);
185
- ctx.setAttribute('gen.ai.operation.name', config.operation || 'chat');
186
- if (config.provider) {
187
- ctx.setAttribute('gen.ai.system', config.provider);
188
- }
189
- if (config.attributes) {
190
- for (const [key, value] of Object.entries(config.attributes)) {
191
- if (value !== undefined && value !== null) {
192
- // setAttribute only accepts primitives (string | number | boolean)
193
- // Arrays and objects should be serialized
194
- const attrValue =
195
- typeof value === 'string' ||
196
- typeof value === 'number' ||
197
- typeof value === 'boolean'
198
- ? value
199
- : JSON.stringify(value);
200
- ctx.setAttribute(key, attrValue);
201
- }
202
- }
203
- }
204
-
205
- // Call the user's factory to get their function and return it
206
- return fnFactory(ctx);
207
- });
208
- };
209
- }
210
-
211
65
  /**
212
66
  * Trace database operations with DB semantic conventions
213
67
  *
@@ -70,6 +70,42 @@ exporter:
70
70
  });
71
71
  });
72
72
 
73
+ it('should parse exporter destinations configuration', () => {
74
+ const yaml = `
75
+ exporter:
76
+ destinations:
77
+ - endpoint: https://otlp-gateway.grafana.net/otlp
78
+ headers:
79
+ Authorization: Basic grafana
80
+ - endpoint: https://api.honeycomb.io
81
+ protocol: grpc
82
+ headers:
83
+ x-honeycomb-team: secret-key
84
+ signals:
85
+ - traces
86
+ `;
87
+ const filePath = path.join(testDir, 'exporter-destinations.yaml');
88
+ writeFileSync(filePath, yaml);
89
+
90
+ const config = loadYamlConfigFromFile(filePath);
91
+ expect(config.destinations).toEqual([
92
+ {
93
+ endpoint: 'https://otlp-gateway.grafana.net/otlp',
94
+ headers: {
95
+ Authorization: 'Basic grafana',
96
+ },
97
+ },
98
+ {
99
+ endpoint: 'https://api.honeycomb.io',
100
+ protocol: 'grpc',
101
+ headers: {
102
+ 'x-honeycomb-team': 'secret-key',
103
+ },
104
+ signals: ['traces'],
105
+ },
106
+ ]);
107
+ });
108
+
73
109
  it('should parse resource attributes', () => {
74
110
  const yaml = `
75
111
  resource:
@@ -23,7 +23,7 @@
23
23
 
24
24
  import { readFileSync, existsSync } from 'node:fs';
25
25
  import path from 'node:path';
26
- import type { AutotelConfig } from './init';
26
+ import type { AutotelConfig, OtlpSignal } from './init';
27
27
  import {
28
28
  AdaptiveSampler,
29
29
  AlwaysSampler,
@@ -61,6 +61,12 @@ export interface YamlConfig {
61
61
  endpoint?: string;
62
62
  protocol?: 'http' | 'grpc';
63
63
  headers?: Record<string, string>;
64
+ destinations?: Array<{
65
+ endpoint: string;
66
+ protocol?: 'http' | 'grpc';
67
+ headers?: Record<string, string>;
68
+ signals?: OtlpSignal[];
69
+ }>;
64
70
  };
65
71
  resource?: Record<string, string | number | boolean>;
66
72
  sampling?: {
@@ -179,6 +185,9 @@ function yamlToAutotelConfig(yaml: YamlConfig): Partial<AutotelConfig> {
179
185
  if (yaml.exporter?.endpoint) config.endpoint = yaml.exporter.endpoint;
180
186
  if (yaml.exporter?.protocol) config.protocol = yaml.exporter.protocol;
181
187
  if (yaml.exporter?.headers) config.headers = yaml.exporter.headers;
188
+ if (yaml.exporter?.destinations) {
189
+ config.destinations = yaml.exporter.destinations;
190
+ }
182
191
 
183
192
  // Resource attributes (flattened)
184
193
  if (yaml.resource) config.resourceAttributes = yaml.resource;
@@ -1 +0,0 @@
1
- {"version":3,"file":"attributes-D3etyRVc.cjs","names":["UserAttributes","SessionAttributes","DeviceAttributes","HTTPAttributes","DBAttributes","ServiceAttributes","NetworkAttributes","ServerAddressAttributes","URLAttributes","ErrorAttributes","ExceptionAttributes","ProcessAttributes","ThreadAttributes","ContainerAttributes","K8sAttributes","CloudAttributes","FaaSAttributes","FeatureFlagAttributes","MessagingAttributes","GenAIAttributes","RPCAttributes","GraphQLAttributes","OTelAttributes","CodeAttributes","TLSAttributes","REDACTOR_PATTERNS"],"sources":["../src/attributes/builders.ts","../src/attributes/validators.ts","../src/attributes/utils.ts","../src/attributes/attachers.ts","../src/attributes/domains.ts"],"sourcesContent":["/**\n * Attribute builders for constructing OpenTelemetry attributes\n * Provides both key builders (Pattern A) and object builders (Pattern B)\n *\n * @example Pattern A: Key builders\n * ```typescript\n * attrs.user.id('123') // { 'user.id': '123' }\n * attrs.user.email('user@example.com') // { 'user.email': 'user@example.com' }\n * attrs.http.request.method('GET') // { 'http.request.method': 'GET' }\n * attrs.http.response.statusCode(200) // { 'http.response.status_code': 200 }\n * ```\n *\n * @example Pattern B: Object builders\n * ```typescript\n * attrs.user({ id: '123', email: 'user@example.com' })\n * attrs.http.server({ method: 'GET', route: '/users/:id', statusCode: 200 })\n * attrs.db.client({ system: 'postgresql', operation: 'SELECT', collectionName: 'users' })\n * ```\n */\n\nimport {\n UserAttributes,\n SessionAttributes,\n DeviceAttributes,\n HTTPAttributes,\n DBAttributes,\n ServiceAttributes,\n NetworkAttributes,\n ServerAddressAttributes,\n URLAttributes,\n ErrorAttributes,\n ExceptionAttributes,\n ProcessAttributes,\n ThreadAttributes,\n ContainerAttributes,\n K8sAttributes,\n CloudAttributes,\n FaaSAttributes,\n FeatureFlagAttributes,\n MessagingAttributes,\n GenAIAttributes,\n RPCAttributes,\n GraphQLAttributes,\n OTelAttributes,\n CodeAttributes,\n TLSAttributes,\n} from './registry';\n\nimport type {\n UserAttrs,\n SessionAttrs,\n DeviceAttrs,\n HTTPServerAttrs,\n HTTPClientAttrs,\n DBAttrs,\n ServiceAttrs,\n NetworkAttrs,\n ErrorAttrs,\n MessagingAttrs,\n CloudAttrs,\n ServerAddressAttrs,\n URLAttrs,\n ProcessAttrs,\n ContainerAttrs,\n ExceptionAttrs,\n} from './types';\n\nexport const attrs = {\n user: {\n id: (value: string) => ({ [UserAttributes.id]: value }),\n email: (value: string) => ({ [UserAttributes.email]: value }),\n name: (value: string) => ({ [UserAttributes.name]: value }),\n fullName: (value: string) => ({ [UserAttributes.fullName]: value }),\n hash: (value: string) => ({ [UserAttributes.hash]: value }),\n roles: (value: string[]) => ({ [UserAttributes.roles]: value }),\n\n data: (data: UserAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.id !== undefined) result[UserAttributes.id] = data.id;\n if (data.email !== undefined) result[UserAttributes.email] = data.email;\n if (data.name !== undefined) result[UserAttributes.name] = data.name;\n if (data.fullName !== undefined)\n result[UserAttributes.fullName] = data.fullName;\n if (data.hash !== undefined) result[UserAttributes.hash] = data.hash;\n if (data.roles !== undefined) result[UserAttributes.roles] = data.roles;\n return result;\n },\n },\n\n session: {\n id: (value: string) => ({ [SessionAttributes.id]: value }),\n previousId: (value: string) => ({ [SessionAttributes.previousId]: value }),\n\n data: (data: SessionAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.id !== undefined) result[SessionAttributes.id] = data.id;\n if (data.previousId !== undefined)\n result[SessionAttributes.previousId] = data.previousId;\n return result;\n },\n },\n\n device: {\n id: (value: string) => ({ [DeviceAttributes.id]: value }),\n manufacturer: (value: string) => ({\n [DeviceAttributes.manufacturer]: value,\n }),\n modelIdentifier: (value: string) => ({\n [DeviceAttributes.modelIdentifier]: value,\n }),\n modelName: (value: string) => ({ [DeviceAttributes.modelName]: value }),\n\n data: (data: DeviceAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.id !== undefined) result[DeviceAttributes.id] = data.id;\n if (data.manufacturer !== undefined)\n result[DeviceAttributes.manufacturer] = data.manufacturer;\n if (data.modelIdentifier !== undefined)\n result[DeviceAttributes.modelIdentifier] = data.modelIdentifier;\n if (data.modelName !== undefined)\n result[DeviceAttributes.modelName] = data.modelName;\n return result;\n },\n },\n\n http: {\n request: {\n method: (value: string) => ({ [HTTPAttributes.requestMethod]: value }),\n methodOriginal: (value: string) => ({\n [HTTPAttributes.requestMethodOriginal]: value,\n }),\n resendCount: (value: number) => ({\n [HTTPAttributes.requestResendCount]: value,\n }),\n size: (value: number) => ({ [HTTPAttributes.requestSize]: value }),\n bodySize: (value: number) => ({\n [HTTPAttributes.requestBodySize]: value,\n }),\n },\n\n response: {\n statusCode: (value: number) => ({\n [HTTPAttributes.responseStatusCode]: value,\n }),\n size: (value: number) => ({ [HTTPAttributes.responseSize]: value }),\n bodySize: (value: number) => ({\n [HTTPAttributes.responseBodySize]: value,\n }),\n },\n\n route: (value: string) => ({ [HTTPAttributes.route]: value }),\n connectionState: (value: string) => ({\n [HTTPAttributes.connectionState]: value,\n }),\n\n server: (data: HTTPServerAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.method !== undefined)\n result[HTTPAttributes.requestMethod] = data.method;\n if (data.route !== undefined) result[HTTPAttributes.route] = data.route;\n if (data.statusCode !== undefined)\n result[HTTPAttributes.responseStatusCode] = data.statusCode;\n if (data.bodySize !== undefined)\n result[HTTPAttributes.requestBodySize] = data.bodySize;\n if (data.requestSize !== undefined)\n result[HTTPAttributes.requestSize] = data.requestSize;\n if (data.responseSize !== undefined)\n result[HTTPAttributes.responseSize] = data.responseSize;\n if (data.resendCount !== undefined)\n result[HTTPAttributes.requestResendCount] = data.resendCount;\n return result;\n },\n\n client: (data: HTTPClientAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.method !== undefined)\n result[HTTPAttributes.requestMethod] = data.method;\n if (data.url !== undefined) result[HTTPAttributes.route] = data.url;\n if (data.statusCode !== undefined)\n result[HTTPAttributes.responseStatusCode] = data.statusCode;\n return result;\n },\n },\n\n db: {\n client: {\n system: (value: string) => ({ [DBAttributes.systemName]: value }),\n operation: (value: string) => ({ [DBAttributes.operationName]: value }),\n collectionName: (value: string) => ({\n [DBAttributes.collectionName]: value,\n }),\n namespace: (value: string) => ({ [DBAttributes.namespace]: value }),\n statement: (value: string) => ({ [DBAttributes.statement]: value }),\n querySummary: (value: string) => ({ [DBAttributes.querySummary]: value }),\n queryText: (value: string) => ({ [DBAttributes.queryText]: value }),\n responseStatus: (value: string | number) => ({\n [DBAttributes.responseStatusCode]: value,\n }),\n rowsReturned: (value: number) => ({\n [DBAttributes.responseReturnedRows]: value,\n }),\n\n data: (data: DBAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.system !== undefined)\n result[DBAttributes.systemName] = data.system;\n if (data.operation !== undefined)\n result[DBAttributes.operationName] = data.operation;\n if (data.collectionName !== undefined)\n result[DBAttributes.collectionName] = data.collectionName;\n // 'name' maps to db.namespace (db.name is deprecated per OTel semantic conventions)\n if (data.name !== undefined) result[DBAttributes.namespace] = data.name;\n // 'namespace' takes precedence over 'name' if both are provided\n if (data.namespace !== undefined)\n result[DBAttributes.namespace] = data.namespace;\n if (data.statement !== undefined)\n result[DBAttributes.statement] = data.statement;\n if (data.querySummary !== undefined)\n result[DBAttributes.querySummary] = data.querySummary;\n if (data.queryText !== undefined)\n result[DBAttributes.queryText] = data.queryText;\n if (data.responseStatus !== undefined)\n result[DBAttributes.responseStatusCode] = data.responseStatus;\n if (data.rowsReturned !== undefined)\n result[DBAttributes.responseReturnedRows] = data.rowsReturned;\n return result;\n },\n },\n },\n\n service: {\n name: (value: string) => ({ [ServiceAttributes.name]: value }),\n instance: (value: string) => ({ [ServiceAttributes.instance]: value }),\n version: (value: string) => ({ [ServiceAttributes.version]: value }),\n\n data: (data: ServiceAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.name !== undefined) result[ServiceAttributes.name] = data.name;\n if (data.instance !== undefined)\n result[ServiceAttributes.instance] = data.instance;\n if (data.version !== undefined)\n result[ServiceAttributes.version] = data.version;\n return result;\n },\n },\n\n network: {\n peerAddress: (value: string) => ({\n [NetworkAttributes.peerAddress]: value,\n }),\n peerPort: (value: number) => ({ [NetworkAttributes.peerPort]: value }),\n transport: (value: string) => ({ [NetworkAttributes.transport]: value }),\n protocolName: (value: string) => ({\n [NetworkAttributes.protocolName]: value,\n }),\n protocolVersion: (value: string) => ({\n [NetworkAttributes.protocolVersion]: value,\n }),\n\n data: (data: NetworkAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.peerAddress !== undefined)\n result[NetworkAttributes.peerAddress] = data.peerAddress;\n if (data.peerPort !== undefined)\n result[NetworkAttributes.peerPort] = data.peerPort;\n if (data.transport !== undefined)\n result[NetworkAttributes.transport] = data.transport;\n if (data.protocolName !== undefined)\n result[NetworkAttributes.protocolName] = data.protocolName;\n if (data.protocolVersion !== undefined)\n result[NetworkAttributes.protocolVersion] = data.protocolVersion;\n return result;\n },\n },\n\n server: {\n address: (value: string) => ({ [ServerAddressAttributes.address]: value }),\n port: (value: number) => ({ [ServerAddressAttributes.port]: value }),\n socketAddress: (value: string) => ({\n [ServerAddressAttributes.socketAddress]: value,\n }),\n\n data: (data: ServerAddressAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.address !== undefined)\n result[ServerAddressAttributes.address] = data.address;\n if (data.port !== undefined)\n result[ServerAddressAttributes.port] = data.port;\n if (data.socketAddress !== undefined)\n result[ServerAddressAttributes.socketAddress] = data.socketAddress;\n return result;\n },\n },\n\n url: {\n scheme: (value: string) => ({ [URLAttributes.scheme]: value }),\n full: (value: string) => ({ [URLAttributes.full]: value }),\n path: (value: string) => ({ [URLAttributes.path]: value }),\n query: (value: string) => ({ [URLAttributes.query]: value }),\n fragment: (value: string) => ({ [URLAttributes.fragment]: value }),\n\n data: (data: URLAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.scheme !== undefined) result[URLAttributes.scheme] = data.scheme;\n if (data.full !== undefined) result[URLAttributes.full] = data.full;\n if (data.path !== undefined) result[URLAttributes.path] = data.path;\n if (data.query !== undefined) result[URLAttributes.query] = data.query;\n if (data.fragment !== undefined)\n result[URLAttributes.fragment] = data.fragment;\n return result;\n },\n },\n\n error: {\n type: (value: string) => ({ [ErrorAttributes.type]: value }),\n message: (value: string) => ({ [ErrorAttributes.message]: value }),\n stackTrace: (value: string) => ({ [ErrorAttributes.stackTrace]: value }),\n code: (value: string | number) => ({ [ErrorAttributes.code]: value }),\n\n data: (data: ErrorAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.type !== undefined) result[ErrorAttributes.type] = data.type;\n if (data.message !== undefined)\n result[ErrorAttributes.message] = data.message;\n if (data.stackTrace !== undefined)\n result[ErrorAttributes.stackTrace] = data.stackTrace;\n if (data.code !== undefined) result[ErrorAttributes.code] = data.code;\n return result;\n },\n },\n\n exception: {\n escaped: (value: boolean) => ({ [ExceptionAttributes.escaped]: value }),\n message: (value: string) => ({ [ExceptionAttributes.message]: value }),\n stackTrace: (value: string) => ({\n [ExceptionAttributes.stackTrace]: value,\n }),\n type: (value: string) => ({ [ExceptionAttributes.type]: value }),\n moduleName: (value: string) => ({\n [ExceptionAttributes.moduleName]: value,\n }),\n\n data: (data: ExceptionAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.escaped !== undefined)\n result[ExceptionAttributes.escaped] = data.escaped;\n if (data.message !== undefined)\n result[ExceptionAttributes.message] = data.message;\n if (data.stackTrace !== undefined)\n result[ExceptionAttributes.stackTrace] = data.stackTrace;\n if (data.type !== undefined) result[ExceptionAttributes.type] = data.type;\n if (data.moduleName !== undefined)\n result[ExceptionAttributes.moduleName] = data.moduleName;\n return result;\n },\n },\n\n process: {\n pid: (value: number) => ({ [ProcessAttributes.pid]: value }),\n executablePath: (value: string) => ({\n [ProcessAttributes.executablePath]: value,\n }),\n command: (value: string) => ({ [ProcessAttributes.command]: value }),\n owner: (value: string) => ({ [ProcessAttributes.owner]: value }),\n\n data: (data: ProcessAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.pid !== undefined) result[ProcessAttributes.pid] = data.pid;\n if (data.executablePath !== undefined)\n result[ProcessAttributes.executablePath] = data.executablePath;\n if (data.command !== undefined)\n result[ProcessAttributes.command] = data.command;\n if (data.owner !== undefined)\n result[ProcessAttributes.owner] = data.owner;\n return result;\n },\n },\n\n thread: {\n id: (value: number) => ({ [ThreadAttributes.id]: value }),\n name: (value: string) => ({ [ThreadAttributes.name]: value }),\n },\n\n container: {\n id: (value: string) => ({ [ContainerAttributes.id]: value }),\n name: (value: string) => ({ [ContainerAttributes.name]: value }),\n image: (value: string) => ({ [ContainerAttributes.image]: value }),\n tag: (value: string) => ({ [ContainerAttributes.tag]: value }),\n\n data: (data: ContainerAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.id !== undefined) result[ContainerAttributes.id] = data.id;\n if (data.name !== undefined) result[ContainerAttributes.name] = data.name;\n if (data.image !== undefined)\n result[ContainerAttributes.image] = data.image;\n if (data.tag !== undefined) result[ContainerAttributes.tag] = data.tag;\n return result;\n },\n },\n\n k8s: {\n podName: (value: string) => ({ [K8sAttributes.podName]: value }),\n namespaceName: (value: string) => ({\n [K8sAttributes.namespaceName]: value,\n }),\n deploymentName: (value: string) => ({\n [K8sAttributes.deploymentName]: value,\n }),\n state: (value: string) => ({ [K8sAttributes.state]: value }),\n },\n\n cloud: {\n provider: (value: string) => ({ [CloudAttributes.provider]: value }),\n accountId: (value: string) => ({ [CloudAttributes.accountId]: value }),\n region: (value: string) => ({ [CloudAttributes.region]: value }),\n availabilityZone: (value: string) => ({\n [CloudAttributes.availabilityZone]: value,\n }),\n platform: (value: string) => ({ [CloudAttributes.platform]: value }),\n\n data: (data: CloudAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.provider !== undefined)\n result[CloudAttributes.provider] = data.provider;\n if (data.accountId !== undefined)\n result[CloudAttributes.accountId] = data.accountId;\n if (data.region !== undefined)\n result[CloudAttributes.region] = data.region;\n if (data.availabilityZone !== undefined)\n result[CloudAttributes.availabilityZone] = data.availabilityZone;\n if (data.platform !== undefined)\n result[CloudAttributes.platform] = data.platform;\n return result;\n },\n },\n\n faas: {\n name: (value: string) => ({ [FaaSAttributes.name]: value }),\n version: (value: string) => ({ [FaaSAttributes.version]: value }),\n instance: (value: string) => ({ [FaaSAttributes.instance]: value }),\n execution: (value: string) => ({ [FaaSAttributes.execution]: value }),\n coldstart: (value: boolean) => ({ [FaaSAttributes.coldstart]: value }),\n },\n\n featureFlag: {\n key: (value: string) => ({ [FeatureFlagAttributes.key]: value }),\n provider: (value: string) => ({ [FeatureFlagAttributes.provider]: value }),\n variant: (value: string) => ({ [FeatureFlagAttributes.variant]: value }),\n },\n\n messaging: {\n system: (value: string) => ({ [MessagingAttributes.system]: value }),\n destination: (value: string) => ({\n [MessagingAttributes.destination]: value,\n }),\n operation: (value: 'publish' | 'receive' | 'process') => ({\n [MessagingAttributes.operation]: value,\n }),\n messageId: (value: string) => ({ [MessagingAttributes.messageId]: value }),\n conversationId: (value: string) => ({\n [MessagingAttributes.conversationId]: value,\n }),\n\n data: (data: MessagingAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.system !== undefined)\n result[MessagingAttributes.system] = data.system;\n if (data.destination !== undefined)\n result[MessagingAttributes.destination] = data.destination;\n if (data.operation !== undefined)\n result[MessagingAttributes.operation] = data.operation;\n if (data.messageId !== undefined)\n result[MessagingAttributes.messageId] = data.messageId;\n if (data.conversationId !== undefined)\n result[MessagingAttributes.conversationId] = data.conversationId;\n return result;\n },\n },\n\n genAI: {\n system: (value: string) => ({ [GenAIAttributes.system]: value }),\n requestModel: (value: string) => ({\n [GenAIAttributes.requestModel]: value,\n }),\n responseModel: (value: string) => ({\n [GenAIAttributes.responseModel]: value,\n }),\n operationName: (value: 'chat' | 'completion' | 'embedding') => ({\n [GenAIAttributes.operationName]: value,\n }),\n usagePromptTokens: (value: number) => ({\n [GenAIAttributes.usagePromptTokens]: value,\n }),\n usageCompletionTokens: (value: number) => ({\n [GenAIAttributes.usageCompletionTokens]: value,\n }),\n provider: (value: string) => ({ [GenAIAttributes.provider]: value }),\n },\n\n rpc: {\n system: (value: string) => ({ [RPCAttributes.system]: value }),\n service: (value: string) => ({ [RPCAttributes.service]: value }),\n method: (value: string) => ({ [RPCAttributes.method]: value }),\n grpcStatusCode: (value: number) => ({\n [RPCAttributes.grpcStatusCode]: value,\n }),\n },\n\n graphql: {\n document: (value: string) => ({ [GraphQLAttributes.document]: value }),\n operationName: (value: string) => ({\n [GraphQLAttributes.operationName]: value,\n }),\n operationType: (value: 'query' | 'mutation' | 'subscription') => ({\n [GraphQLAttributes.operationType]: value,\n }),\n },\n\n otel: {\n libraryName: (value: string) => ({ [OTelAttributes.libraryName]: value }),\n libraryVersion: (value: string) => ({\n [OTelAttributes.libraryVersion]: value,\n }),\n statusCode: (value: string) => ({ [OTelAttributes.statusCode]: value }),\n },\n\n code: {\n namespace: (value: string) => ({ [CodeAttributes.namespace]: value }),\n filepath: (value: string) => ({ [CodeAttributes.filepath]: value }),\n function: (value: string) => ({ [CodeAttributes.function]: value }),\n class: (value: string) => ({ [CodeAttributes.class]: value }),\n method: (value: string) => ({ [CodeAttributes.method]: value }),\n column: (value: string) => ({ [CodeAttributes.column]: value }),\n lineNumber: (value: number) => ({ [CodeAttributes.lineNumber]: value }),\n repository: (value: string) => ({ [CodeAttributes.repository]: value }),\n revision: (value: string) => ({ [CodeAttributes.revision]: value }),\n },\n\n tls: {\n protocolVersion: (value: string) => ({\n [TLSAttributes.protocolVersion]: value,\n }),\n cipher: (value: string) => ({ [TLSAttributes.cipher]: value }),\n curveName: (value: string) => ({ [TLSAttributes.curveName]: value }),\n resumed: (value: boolean) => ({ [TLSAttributes.resumed]: value }),\n },\n} as const;\n","/**\n * Attribute validation, PII detection, and guardrails\n * Provides safe-by-default attribute handling with configurable policies\n */\n\nimport { REDACTOR_PATTERNS } from '../attribute-redacting-processor';\n\nexport interface AttributeGuardrails {\n /** How to handle PII in attributes */\n pii?: 'allow' | 'redact' | 'hash' | 'block';\n\n /** Maximum length for attribute values */\n maxLength?: number;\n\n /** Validate enum values against known values */\n validateEnum?: boolean;\n\n /** Log warnings for deprecated attributes instead of throwing */\n warnDeprecated?: boolean;\n\n /** Custom deprecation warnings */\n deprecatedWarnings?: Record<string, string>;\n}\n\nexport interface AttributePolicy {\n guardrails?: AttributeGuardrails;\n /** Custom deprecation warnings for specific attributes */\n deprecatedWarnings?: Record<string, string>;\n}\n\nconst DEPRECATED_ATTRIBUTES = {\n 'enduser.id': 'user.id',\n 'enduser.role': 'user.roles',\n 'enduser.scope': undefined,\n 'http.method': 'http.request.method',\n 'http.host': 'server.address',\n 'http.status_code': 'http.response.status_code',\n 'http.target': 'url.path',\n 'http.url': 'url.full',\n 'http.user_agent': 'user_agent.original',\n 'http.flavor': 'network.protocol.name',\n 'http.scheme': 'url.scheme',\n 'http.server_name': 'server.address',\n 'db.name': 'db.namespace',\n 'db.operation': 'db.operation.name',\n 'db.statement': 'db.query.text',\n 'db.system': 'db.system.name',\n 'db.collection': 'db.collection.name',\n 'db.instance.id': undefined,\n 'db.jdbc.driver_classname': undefined,\n 'db.mssql.instance_name': 'mssql.instance.name',\n 'db.sql.table': 'db.collection.name',\n 'http.client_ip': 'client.address',\n 'user_agent.original': 'user_agent.original',\n} as const;\n\nconst HTTP_METHODS = new Set([\n 'GET',\n 'POST',\n 'PUT',\n 'DELETE',\n 'PATCH',\n 'HEAD',\n 'OPTIONS',\n 'TRACE',\n 'QUERY',\n '_OTHER',\n]);\n\nexport function validateAttribute(\n key: string,\n value: unknown,\n policy: AttributePolicy = {},\n): unknown {\n const { guardrails = {} } = policy;\n\n if (value === undefined || value === null) {\n return undefined;\n }\n\n // For non-string values that don't need transformation, preserve the original type\n if (typeof value !== 'string') {\n // PII checks only apply to strings\n // maxLength only applies to strings\n // validateEnum only applies to strings\n return value;\n }\n\n const stringValue = value;\n\n if (guardrails.pii) {\n const piiResult = applyPIIPolicy(key, stringValue, guardrails.pii);\n if (piiResult !== stringValue) {\n return piiResult;\n }\n }\n\n if (guardrails.maxLength && stringValue.length > guardrails.maxLength) {\n return truncateValue(key, stringValue, guardrails.maxLength);\n }\n\n if (guardrails.validateEnum && HTTP_METHODS.has(stringValue)) {\n const normalizedMethod = normalizeHTTPMethod(stringValue);\n if (normalizedMethod !== stringValue) {\n return normalizedMethod;\n }\n }\n\n return stringValue;\n}\n\nfunction applyPIIPolicy(\n key: string,\n value: string,\n pii: AttributeGuardrails['pii'],\n): string {\n if (pii === 'allow') {\n return value;\n }\n\n if (pii === 'redact') {\n return redactIfPII(key, value);\n }\n\n if (pii === 'hash') {\n return hashIfPII(key, value);\n }\n\n if (pii === 'block' && isPIIKey(key)) {\n throw new Error(\n `PII attribute \"${key}\" is blocked by guardrails. Use pii: \"allow\" to enable it.`,\n );\n }\n\n return value;\n}\n\nfunction isPIIKey(key: string): boolean {\n const piiKeyPatterns = [\n 'email',\n 'phone',\n 'ssn',\n 'credit_card',\n 'password',\n 'secret',\n 'token',\n 'api_key',\n 'authorization',\n ];\n const lowerKey = key.toLowerCase();\n return piiKeyPatterns.some((pattern) => lowerKey.includes(pattern));\n}\n\nfunction redactIfPII(key: string, value: string): string {\n if (isPIIKey(key)) {\n // REDACTOR_PATTERNS values are RegExp patterns\n for (const [, pattern] of Object.entries(REDACTOR_PATTERNS)) {\n if (pattern instanceof RegExp && pattern.test(value)) {\n return '[REDACTED]';\n }\n }\n // If no pattern matched but key is PII, still redact\n return '[REDACTED]';\n }\n return value;\n}\n\nfunction hashIfPII(key: string, value: string): string {\n if (!isPIIKey(key)) {\n return value;\n }\n\n // Use a simple but consistent hash that produces 32-char hex\n // FNV-1a hash variant producing 128-bit output (32 hex chars)\n const FNV_PRIME = 0x01_00_01_93;\n const FNV_OFFSET = 0x81_1c_9d_c5;\n\n // Generate 4 32-bit hashes to produce 32 hex chars\n const hashes: number[] = [];\n for (let round = 0; round < 4; round++) {\n let hash = FNV_OFFSET;\n for (let i = 0; i < value.length; i++) {\n hash ^= (value.codePointAt(i) ?? 0) + round;\n hash = Math.imul(hash, FNV_PRIME);\n }\n hashes.push(hash >>> 0); // Convert to unsigned\n }\n\n return `hash_${hashes.map((h) => h.toString(16).padStart(8, '0')).join('')}`;\n}\n\nfunction truncateValue(key: string, value: string, maxLength: number): string {\n if (value.length <= maxLength) {\n return value;\n }\n return value.slice(0, maxLength - 3) + '...';\n}\n\nfunction normalizeHTTPMethod(method: string): string {\n const upper = method.toUpperCase();\n if (HTTP_METHODS.has(upper)) {\n return upper;\n }\n return upper;\n}\n\nexport function checkDeprecatedAttribute(\n key: string,\n policy: AttributePolicy = {},\n): string | null {\n const { guardrails = {}, deprecatedWarnings = {} } = policy;\n const { warnDeprecated = true } = guardrails;\n\n if (!warnDeprecated) {\n return null;\n }\n\n // Check if the key exists in the deprecated attributes map\n const isDeprecated = key in DEPRECATED_ATTRIBUTES;\n if (isDeprecated) {\n const replacement =\n DEPRECATED_ATTRIBUTES[key as keyof typeof DEPRECATED_ATTRIBUTES];\n if (replacement === undefined) {\n // Deprecated with no replacement (e.g., enduser.scope)\n console.warn(\n `[autotel/attributes] Attribute \"${key}\" is deprecated and has no replacement. ` +\n `Remove or find a replacement in OpenTelemetry semantic conventions.`,\n );\n } else {\n // Deprecated with a known replacement\n console.warn(\n `[autotel/attributes] Attribute \"${key}\" is deprecated. Use \"${replacement}\" instead.`,\n );\n }\n }\n\n if (deprecatedWarnings[key]) {\n console.warn(`[autotel/attributes] ${deprecatedWarnings[key]}`);\n }\n\n const replacement =\n DEPRECATED_ATTRIBUTES[key as keyof typeof DEPRECATED_ATTRIBUTES];\n return replacement ?? null;\n}\n\nexport function autoRedactPII(\n attributes: Record<string, unknown>,\n policy: AttributePolicy = {},\n): Record<string, unknown> {\n const { guardrails = { pii: 'redact' } } = policy;\n\n const redacted: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(attributes)) {\n redacted[key] = validateAttribute(key, value, { guardrails });\n }\n return redacted;\n}\n\nexport function defaultGuardrails(): AttributeGuardrails {\n return {\n pii: 'redact',\n maxLength: 255,\n validateEnum: true,\n warnDeprecated: true,\n };\n}\n","/**\n * Attribute utility functions\n */\n\nimport type { AttributeValue } from '../trace-context';\nimport {\n validateAttribute,\n autoRedactPII,\n defaultGuardrails,\n checkDeprecatedAttribute,\n type AttributePolicy,\n} from './validators';\n\n// Type for objects that have setAttributes method (spans or contexts)\n// Using a generic parameter to accommodate different AttributeValue types\ntype AttributeSetter = {\n setAttributes: (attrs: Record<string, AttributeValue>) => void;\n};\n\nexport function mergeAttrs(\n ...attrSets: Array<Record<string, unknown> | undefined>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const attrSet of attrSets) {\n if (attrSet) {\n Object.assign(result, attrSet);\n }\n }\n return result;\n}\n\nexport function safeSetAttributes(\n span: AttributeSetter,\n attrs: Record<string, unknown>,\n policy?: AttributePolicy,\n): void {\n // Merge user-supplied guardrails with defaults so callers can tweak\n // a single option without opting out of the rest\n const mergedGuardrails = {\n ...defaultGuardrails(),\n ...policy?.guardrails,\n };\n const effectivePolicy: AttributePolicy = {\n ...policy,\n guardrails: mergedGuardrails,\n };\n\n const validated = autoRedactPII(attrs, effectivePolicy);\n\n const sanitizedAttrs: Record<string, AttributeValue> = {};\n for (const [key, value] of Object.entries(validated)) {\n if (value !== undefined) {\n // Check for deprecated attributes and log warnings\n checkDeprecatedAttribute(key, effectivePolicy);\n const validatedValue = validateAttribute(key, value, effectivePolicy);\n if (validatedValue !== undefined) {\n // Cast to AttributeValue since validateAttribute ensures valid types\n sanitizedAttrs[key] = validatedValue as AttributeValue;\n }\n }\n }\n\n span.setAttributes(sanitizedAttrs);\n}\n","/**\n * Signal attachment helpers\n * These functions know WHERE to attach attributes automatically\n * They handle span, resource, and log signals correctly\n */\n\nimport type { Span, Attributes } from '@opentelemetry/api';\nimport {\n resourceFromAttributes,\n type Resource,\n} from '@opentelemetry/resources';\nimport type { TraceContext } from '../trace-context';\nimport { attrs } from './builders';\nimport { safeSetAttributes } from './utils';\n\nexport function setUser(\n spanOrContext: Span | TraceContext,\n data: import('./types').UserAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.user.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function setSession(\n spanOrContext: Span | TraceContext,\n data: import('./types').SessionAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.session.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function setDevice(\n spanOrContext: Span | TraceContext,\n data: import('./types').DeviceAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.device.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function httpServer(\n spanOrContext: Span | TraceContext,\n data: import('./types').HTTPServerAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.http.server(data);\n\n if ('updateName' in spanOrContext && data.method && data.route) {\n const span = spanOrContext as Span;\n span.updateName(`HTTP ${data.method} ${data.route}`);\n }\n\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function httpClient(\n spanOrContext: Span | TraceContext,\n data: import('./types').HTTPClientAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.http.client(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function dbClient(\n spanOrContext: Span | TraceContext,\n data: import('./types').DBAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.db.client.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\n/**\n * Merge service attributes into a Resource and return a new Resource.\n *\n * Resource.attributes is readonly, so this function returns a new merged\n * Resource rather than mutating the input.\n *\n * @param resource - The existing resource to merge with\n * @param data - Service attributes to add\n * @returns A new Resource with the merged attributes\n *\n * @example\n * ```typescript\n * const baseResource = Resource.default();\n * const enrichedResource = mergeServiceResource(baseResource, {\n * name: 'my-service',\n * version: '1.0.0',\n * });\n * ```\n */\nexport function mergeServiceResource(\n resource: Resource,\n data: import('./types').ServiceAttrs,\n): Resource {\n const attributes = attrs.service.data(data);\n return resource.merge(resourceFromAttributes(attributes as Attributes));\n}\n\nexport function identify(\n spanOrContext: Span | TraceContext,\n data: {\n user?: import('./types').UserAttrs;\n session?: import('./types').SessionAttrs;\n device?: import('./types').DeviceAttrs;\n },\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const allAttrs = [];\n\n if (data.user) {\n allAttrs.push(attrs.user.data(data.user));\n }\n if (data.session) {\n allAttrs.push(attrs.session.data(data.session));\n }\n if (data.device) {\n allAttrs.push(attrs.device.data(data.device));\n }\n\n const merged: Record<string, unknown> = {};\n for (const attrSet of allAttrs) {\n Object.assign(merged, attrSet);\n }\n\n safeSetAttributes(spanOrContext, merged, guardrails);\n}\n\nexport function request(\n spanOrContext: Span | TraceContext,\n data: import('./types').HTTPServerAttrs & {\n clientIp?: string;\n },\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const httpAttrs = attrs.http.server(data);\n const networkAttrs = attrs.network.peerAddress(data.clientIp || '');\n const merged = { ...httpAttrs, ...networkAttrs };\n safeSetAttributes(spanOrContext, merged, guardrails);\n}\n\nexport function setError(\n spanOrContext: Span | TraceContext,\n data: import('./types').ErrorAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.error.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function setException(\n spanOrContext: Span | TraceContext,\n data: import('./types').ExceptionAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.exception.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n","/**\n * Domain helpers for common attribute patterns\n * These bundle multiple attribute groups into semantic helpers\n */\n\nimport { attrs } from './builders';\nimport { safeSetAttributes } from './utils';\n\nexport function transaction(\n spanOrContext: import('../trace-context').TraceContext,\n config: {\n user?: import('./types').UserAttrs;\n session?: import('./types').SessionAttrs;\n method?: string;\n route?: string;\n statusCode?: number;\n clientIp?: string;\n },\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const userAttrs = attrs.user.data(config.user || {});\n const sessionAttrs = attrs.session.data(config.session || {});\n const httpAttrs = attrs.http.server({\n method: config.method,\n route: config.route,\n statusCode: config.statusCode,\n });\n const networkAttrs = attrs.network.peerAddress(config.clientIp || '');\n\n const merged = {\n ...userAttrs,\n ...sessionAttrs,\n ...httpAttrs,\n ...networkAttrs,\n };\n\n if (config.method && config.route && 'updateName' in spanOrContext) {\n spanOrContext.updateName(`HTTP ${config.method} ${config.route}`);\n }\n\n safeSetAttributes(spanOrContext, merged, guardrails);\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"attributes-ksn4HVbd.js","names":[],"sources":["../src/attributes/builders.ts","../src/attributes/validators.ts","../src/attributes/utils.ts","../src/attributes/attachers.ts","../src/attributes/domains.ts"],"sourcesContent":["/**\n * Attribute builders for constructing OpenTelemetry attributes\n * Provides both key builders (Pattern A) and object builders (Pattern B)\n *\n * @example Pattern A: Key builders\n * ```typescript\n * attrs.user.id('123') // { 'user.id': '123' }\n * attrs.user.email('user@example.com') // { 'user.email': 'user@example.com' }\n * attrs.http.request.method('GET') // { 'http.request.method': 'GET' }\n * attrs.http.response.statusCode(200) // { 'http.response.status_code': 200 }\n * ```\n *\n * @example Pattern B: Object builders\n * ```typescript\n * attrs.user({ id: '123', email: 'user@example.com' })\n * attrs.http.server({ method: 'GET', route: '/users/:id', statusCode: 200 })\n * attrs.db.client({ system: 'postgresql', operation: 'SELECT', collectionName: 'users' })\n * ```\n */\n\nimport {\n UserAttributes,\n SessionAttributes,\n DeviceAttributes,\n HTTPAttributes,\n DBAttributes,\n ServiceAttributes,\n NetworkAttributes,\n ServerAddressAttributes,\n URLAttributes,\n ErrorAttributes,\n ExceptionAttributes,\n ProcessAttributes,\n ThreadAttributes,\n ContainerAttributes,\n K8sAttributes,\n CloudAttributes,\n FaaSAttributes,\n FeatureFlagAttributes,\n MessagingAttributes,\n GenAIAttributes,\n RPCAttributes,\n GraphQLAttributes,\n OTelAttributes,\n CodeAttributes,\n TLSAttributes,\n} from './registry';\n\nimport type {\n UserAttrs,\n SessionAttrs,\n DeviceAttrs,\n HTTPServerAttrs,\n HTTPClientAttrs,\n DBAttrs,\n ServiceAttrs,\n NetworkAttrs,\n ErrorAttrs,\n MessagingAttrs,\n CloudAttrs,\n ServerAddressAttrs,\n URLAttrs,\n ProcessAttrs,\n ContainerAttrs,\n ExceptionAttrs,\n} from './types';\n\nexport const attrs = {\n user: {\n id: (value: string) => ({ [UserAttributes.id]: value }),\n email: (value: string) => ({ [UserAttributes.email]: value }),\n name: (value: string) => ({ [UserAttributes.name]: value }),\n fullName: (value: string) => ({ [UserAttributes.fullName]: value }),\n hash: (value: string) => ({ [UserAttributes.hash]: value }),\n roles: (value: string[]) => ({ [UserAttributes.roles]: value }),\n\n data: (data: UserAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.id !== undefined) result[UserAttributes.id] = data.id;\n if (data.email !== undefined) result[UserAttributes.email] = data.email;\n if (data.name !== undefined) result[UserAttributes.name] = data.name;\n if (data.fullName !== undefined)\n result[UserAttributes.fullName] = data.fullName;\n if (data.hash !== undefined) result[UserAttributes.hash] = data.hash;\n if (data.roles !== undefined) result[UserAttributes.roles] = data.roles;\n return result;\n },\n },\n\n session: {\n id: (value: string) => ({ [SessionAttributes.id]: value }),\n previousId: (value: string) => ({ [SessionAttributes.previousId]: value }),\n\n data: (data: SessionAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.id !== undefined) result[SessionAttributes.id] = data.id;\n if (data.previousId !== undefined)\n result[SessionAttributes.previousId] = data.previousId;\n return result;\n },\n },\n\n device: {\n id: (value: string) => ({ [DeviceAttributes.id]: value }),\n manufacturer: (value: string) => ({\n [DeviceAttributes.manufacturer]: value,\n }),\n modelIdentifier: (value: string) => ({\n [DeviceAttributes.modelIdentifier]: value,\n }),\n modelName: (value: string) => ({ [DeviceAttributes.modelName]: value }),\n\n data: (data: DeviceAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.id !== undefined) result[DeviceAttributes.id] = data.id;\n if (data.manufacturer !== undefined)\n result[DeviceAttributes.manufacturer] = data.manufacturer;\n if (data.modelIdentifier !== undefined)\n result[DeviceAttributes.modelIdentifier] = data.modelIdentifier;\n if (data.modelName !== undefined)\n result[DeviceAttributes.modelName] = data.modelName;\n return result;\n },\n },\n\n http: {\n request: {\n method: (value: string) => ({ [HTTPAttributes.requestMethod]: value }),\n methodOriginal: (value: string) => ({\n [HTTPAttributes.requestMethodOriginal]: value,\n }),\n resendCount: (value: number) => ({\n [HTTPAttributes.requestResendCount]: value,\n }),\n size: (value: number) => ({ [HTTPAttributes.requestSize]: value }),\n bodySize: (value: number) => ({\n [HTTPAttributes.requestBodySize]: value,\n }),\n },\n\n response: {\n statusCode: (value: number) => ({\n [HTTPAttributes.responseStatusCode]: value,\n }),\n size: (value: number) => ({ [HTTPAttributes.responseSize]: value }),\n bodySize: (value: number) => ({\n [HTTPAttributes.responseBodySize]: value,\n }),\n },\n\n route: (value: string) => ({ [HTTPAttributes.route]: value }),\n connectionState: (value: string) => ({\n [HTTPAttributes.connectionState]: value,\n }),\n\n server: (data: HTTPServerAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.method !== undefined)\n result[HTTPAttributes.requestMethod] = data.method;\n if (data.route !== undefined) result[HTTPAttributes.route] = data.route;\n if (data.statusCode !== undefined)\n result[HTTPAttributes.responseStatusCode] = data.statusCode;\n if (data.bodySize !== undefined)\n result[HTTPAttributes.requestBodySize] = data.bodySize;\n if (data.requestSize !== undefined)\n result[HTTPAttributes.requestSize] = data.requestSize;\n if (data.responseSize !== undefined)\n result[HTTPAttributes.responseSize] = data.responseSize;\n if (data.resendCount !== undefined)\n result[HTTPAttributes.requestResendCount] = data.resendCount;\n return result;\n },\n\n client: (data: HTTPClientAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.method !== undefined)\n result[HTTPAttributes.requestMethod] = data.method;\n if (data.url !== undefined) result[HTTPAttributes.route] = data.url;\n if (data.statusCode !== undefined)\n result[HTTPAttributes.responseStatusCode] = data.statusCode;\n return result;\n },\n },\n\n db: {\n client: {\n system: (value: string) => ({ [DBAttributes.systemName]: value }),\n operation: (value: string) => ({ [DBAttributes.operationName]: value }),\n collectionName: (value: string) => ({\n [DBAttributes.collectionName]: value,\n }),\n namespace: (value: string) => ({ [DBAttributes.namespace]: value }),\n statement: (value: string) => ({ [DBAttributes.statement]: value }),\n querySummary: (value: string) => ({ [DBAttributes.querySummary]: value }),\n queryText: (value: string) => ({ [DBAttributes.queryText]: value }),\n responseStatus: (value: string | number) => ({\n [DBAttributes.responseStatusCode]: value,\n }),\n rowsReturned: (value: number) => ({\n [DBAttributes.responseReturnedRows]: value,\n }),\n\n data: (data: DBAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.system !== undefined)\n result[DBAttributes.systemName] = data.system;\n if (data.operation !== undefined)\n result[DBAttributes.operationName] = data.operation;\n if (data.collectionName !== undefined)\n result[DBAttributes.collectionName] = data.collectionName;\n // 'name' maps to db.namespace (db.name is deprecated per OTel semantic conventions)\n if (data.name !== undefined) result[DBAttributes.namespace] = data.name;\n // 'namespace' takes precedence over 'name' if both are provided\n if (data.namespace !== undefined)\n result[DBAttributes.namespace] = data.namespace;\n if (data.statement !== undefined)\n result[DBAttributes.statement] = data.statement;\n if (data.querySummary !== undefined)\n result[DBAttributes.querySummary] = data.querySummary;\n if (data.queryText !== undefined)\n result[DBAttributes.queryText] = data.queryText;\n if (data.responseStatus !== undefined)\n result[DBAttributes.responseStatusCode] = data.responseStatus;\n if (data.rowsReturned !== undefined)\n result[DBAttributes.responseReturnedRows] = data.rowsReturned;\n return result;\n },\n },\n },\n\n service: {\n name: (value: string) => ({ [ServiceAttributes.name]: value }),\n instance: (value: string) => ({ [ServiceAttributes.instance]: value }),\n version: (value: string) => ({ [ServiceAttributes.version]: value }),\n\n data: (data: ServiceAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.name !== undefined) result[ServiceAttributes.name] = data.name;\n if (data.instance !== undefined)\n result[ServiceAttributes.instance] = data.instance;\n if (data.version !== undefined)\n result[ServiceAttributes.version] = data.version;\n return result;\n },\n },\n\n network: {\n peerAddress: (value: string) => ({\n [NetworkAttributes.peerAddress]: value,\n }),\n peerPort: (value: number) => ({ [NetworkAttributes.peerPort]: value }),\n transport: (value: string) => ({ [NetworkAttributes.transport]: value }),\n protocolName: (value: string) => ({\n [NetworkAttributes.protocolName]: value,\n }),\n protocolVersion: (value: string) => ({\n [NetworkAttributes.protocolVersion]: value,\n }),\n\n data: (data: NetworkAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.peerAddress !== undefined)\n result[NetworkAttributes.peerAddress] = data.peerAddress;\n if (data.peerPort !== undefined)\n result[NetworkAttributes.peerPort] = data.peerPort;\n if (data.transport !== undefined)\n result[NetworkAttributes.transport] = data.transport;\n if (data.protocolName !== undefined)\n result[NetworkAttributes.protocolName] = data.protocolName;\n if (data.protocolVersion !== undefined)\n result[NetworkAttributes.protocolVersion] = data.protocolVersion;\n return result;\n },\n },\n\n server: {\n address: (value: string) => ({ [ServerAddressAttributes.address]: value }),\n port: (value: number) => ({ [ServerAddressAttributes.port]: value }),\n socketAddress: (value: string) => ({\n [ServerAddressAttributes.socketAddress]: value,\n }),\n\n data: (data: ServerAddressAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.address !== undefined)\n result[ServerAddressAttributes.address] = data.address;\n if (data.port !== undefined)\n result[ServerAddressAttributes.port] = data.port;\n if (data.socketAddress !== undefined)\n result[ServerAddressAttributes.socketAddress] = data.socketAddress;\n return result;\n },\n },\n\n url: {\n scheme: (value: string) => ({ [URLAttributes.scheme]: value }),\n full: (value: string) => ({ [URLAttributes.full]: value }),\n path: (value: string) => ({ [URLAttributes.path]: value }),\n query: (value: string) => ({ [URLAttributes.query]: value }),\n fragment: (value: string) => ({ [URLAttributes.fragment]: value }),\n\n data: (data: URLAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.scheme !== undefined) result[URLAttributes.scheme] = data.scheme;\n if (data.full !== undefined) result[URLAttributes.full] = data.full;\n if (data.path !== undefined) result[URLAttributes.path] = data.path;\n if (data.query !== undefined) result[URLAttributes.query] = data.query;\n if (data.fragment !== undefined)\n result[URLAttributes.fragment] = data.fragment;\n return result;\n },\n },\n\n error: {\n type: (value: string) => ({ [ErrorAttributes.type]: value }),\n message: (value: string) => ({ [ErrorAttributes.message]: value }),\n stackTrace: (value: string) => ({ [ErrorAttributes.stackTrace]: value }),\n code: (value: string | number) => ({ [ErrorAttributes.code]: value }),\n\n data: (data: ErrorAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.type !== undefined) result[ErrorAttributes.type] = data.type;\n if (data.message !== undefined)\n result[ErrorAttributes.message] = data.message;\n if (data.stackTrace !== undefined)\n result[ErrorAttributes.stackTrace] = data.stackTrace;\n if (data.code !== undefined) result[ErrorAttributes.code] = data.code;\n return result;\n },\n },\n\n exception: {\n escaped: (value: boolean) => ({ [ExceptionAttributes.escaped]: value }),\n message: (value: string) => ({ [ExceptionAttributes.message]: value }),\n stackTrace: (value: string) => ({\n [ExceptionAttributes.stackTrace]: value,\n }),\n type: (value: string) => ({ [ExceptionAttributes.type]: value }),\n moduleName: (value: string) => ({\n [ExceptionAttributes.moduleName]: value,\n }),\n\n data: (data: ExceptionAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.escaped !== undefined)\n result[ExceptionAttributes.escaped] = data.escaped;\n if (data.message !== undefined)\n result[ExceptionAttributes.message] = data.message;\n if (data.stackTrace !== undefined)\n result[ExceptionAttributes.stackTrace] = data.stackTrace;\n if (data.type !== undefined) result[ExceptionAttributes.type] = data.type;\n if (data.moduleName !== undefined)\n result[ExceptionAttributes.moduleName] = data.moduleName;\n return result;\n },\n },\n\n process: {\n pid: (value: number) => ({ [ProcessAttributes.pid]: value }),\n executablePath: (value: string) => ({\n [ProcessAttributes.executablePath]: value,\n }),\n command: (value: string) => ({ [ProcessAttributes.command]: value }),\n owner: (value: string) => ({ [ProcessAttributes.owner]: value }),\n\n data: (data: ProcessAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.pid !== undefined) result[ProcessAttributes.pid] = data.pid;\n if (data.executablePath !== undefined)\n result[ProcessAttributes.executablePath] = data.executablePath;\n if (data.command !== undefined)\n result[ProcessAttributes.command] = data.command;\n if (data.owner !== undefined)\n result[ProcessAttributes.owner] = data.owner;\n return result;\n },\n },\n\n thread: {\n id: (value: number) => ({ [ThreadAttributes.id]: value }),\n name: (value: string) => ({ [ThreadAttributes.name]: value }),\n },\n\n container: {\n id: (value: string) => ({ [ContainerAttributes.id]: value }),\n name: (value: string) => ({ [ContainerAttributes.name]: value }),\n image: (value: string) => ({ [ContainerAttributes.image]: value }),\n tag: (value: string) => ({ [ContainerAttributes.tag]: value }),\n\n data: (data: ContainerAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.id !== undefined) result[ContainerAttributes.id] = data.id;\n if (data.name !== undefined) result[ContainerAttributes.name] = data.name;\n if (data.image !== undefined)\n result[ContainerAttributes.image] = data.image;\n if (data.tag !== undefined) result[ContainerAttributes.tag] = data.tag;\n return result;\n },\n },\n\n k8s: {\n podName: (value: string) => ({ [K8sAttributes.podName]: value }),\n namespaceName: (value: string) => ({\n [K8sAttributes.namespaceName]: value,\n }),\n deploymentName: (value: string) => ({\n [K8sAttributes.deploymentName]: value,\n }),\n state: (value: string) => ({ [K8sAttributes.state]: value }),\n },\n\n cloud: {\n provider: (value: string) => ({ [CloudAttributes.provider]: value }),\n accountId: (value: string) => ({ [CloudAttributes.accountId]: value }),\n region: (value: string) => ({ [CloudAttributes.region]: value }),\n availabilityZone: (value: string) => ({\n [CloudAttributes.availabilityZone]: value,\n }),\n platform: (value: string) => ({ [CloudAttributes.platform]: value }),\n\n data: (data: CloudAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.provider !== undefined)\n result[CloudAttributes.provider] = data.provider;\n if (data.accountId !== undefined)\n result[CloudAttributes.accountId] = data.accountId;\n if (data.region !== undefined)\n result[CloudAttributes.region] = data.region;\n if (data.availabilityZone !== undefined)\n result[CloudAttributes.availabilityZone] = data.availabilityZone;\n if (data.platform !== undefined)\n result[CloudAttributes.platform] = data.platform;\n return result;\n },\n },\n\n faas: {\n name: (value: string) => ({ [FaaSAttributes.name]: value }),\n version: (value: string) => ({ [FaaSAttributes.version]: value }),\n instance: (value: string) => ({ [FaaSAttributes.instance]: value }),\n execution: (value: string) => ({ [FaaSAttributes.execution]: value }),\n coldstart: (value: boolean) => ({ [FaaSAttributes.coldstart]: value }),\n },\n\n featureFlag: {\n key: (value: string) => ({ [FeatureFlagAttributes.key]: value }),\n provider: (value: string) => ({ [FeatureFlagAttributes.provider]: value }),\n variant: (value: string) => ({ [FeatureFlagAttributes.variant]: value }),\n },\n\n messaging: {\n system: (value: string) => ({ [MessagingAttributes.system]: value }),\n destination: (value: string) => ({\n [MessagingAttributes.destination]: value,\n }),\n operation: (value: 'publish' | 'receive' | 'process') => ({\n [MessagingAttributes.operation]: value,\n }),\n messageId: (value: string) => ({ [MessagingAttributes.messageId]: value }),\n conversationId: (value: string) => ({\n [MessagingAttributes.conversationId]: value,\n }),\n\n data: (data: MessagingAttrs) => {\n const result: Record<string, unknown> = {};\n if (data.system !== undefined)\n result[MessagingAttributes.system] = data.system;\n if (data.destination !== undefined)\n result[MessagingAttributes.destination] = data.destination;\n if (data.operation !== undefined)\n result[MessagingAttributes.operation] = data.operation;\n if (data.messageId !== undefined)\n result[MessagingAttributes.messageId] = data.messageId;\n if (data.conversationId !== undefined)\n result[MessagingAttributes.conversationId] = data.conversationId;\n return result;\n },\n },\n\n genAI: {\n system: (value: string) => ({ [GenAIAttributes.system]: value }),\n requestModel: (value: string) => ({\n [GenAIAttributes.requestModel]: value,\n }),\n responseModel: (value: string) => ({\n [GenAIAttributes.responseModel]: value,\n }),\n operationName: (value: 'chat' | 'completion' | 'embedding') => ({\n [GenAIAttributes.operationName]: value,\n }),\n usagePromptTokens: (value: number) => ({\n [GenAIAttributes.usagePromptTokens]: value,\n }),\n usageCompletionTokens: (value: number) => ({\n [GenAIAttributes.usageCompletionTokens]: value,\n }),\n provider: (value: string) => ({ [GenAIAttributes.provider]: value }),\n },\n\n rpc: {\n system: (value: string) => ({ [RPCAttributes.system]: value }),\n service: (value: string) => ({ [RPCAttributes.service]: value }),\n method: (value: string) => ({ [RPCAttributes.method]: value }),\n grpcStatusCode: (value: number) => ({\n [RPCAttributes.grpcStatusCode]: value,\n }),\n },\n\n graphql: {\n document: (value: string) => ({ [GraphQLAttributes.document]: value }),\n operationName: (value: string) => ({\n [GraphQLAttributes.operationName]: value,\n }),\n operationType: (value: 'query' | 'mutation' | 'subscription') => ({\n [GraphQLAttributes.operationType]: value,\n }),\n },\n\n otel: {\n libraryName: (value: string) => ({ [OTelAttributes.libraryName]: value }),\n libraryVersion: (value: string) => ({\n [OTelAttributes.libraryVersion]: value,\n }),\n statusCode: (value: string) => ({ [OTelAttributes.statusCode]: value }),\n },\n\n code: {\n namespace: (value: string) => ({ [CodeAttributes.namespace]: value }),\n filepath: (value: string) => ({ [CodeAttributes.filepath]: value }),\n function: (value: string) => ({ [CodeAttributes.function]: value }),\n class: (value: string) => ({ [CodeAttributes.class]: value }),\n method: (value: string) => ({ [CodeAttributes.method]: value }),\n column: (value: string) => ({ [CodeAttributes.column]: value }),\n lineNumber: (value: number) => ({ [CodeAttributes.lineNumber]: value }),\n repository: (value: string) => ({ [CodeAttributes.repository]: value }),\n revision: (value: string) => ({ [CodeAttributes.revision]: value }),\n },\n\n tls: {\n protocolVersion: (value: string) => ({\n [TLSAttributes.protocolVersion]: value,\n }),\n cipher: (value: string) => ({ [TLSAttributes.cipher]: value }),\n curveName: (value: string) => ({ [TLSAttributes.curveName]: value }),\n resumed: (value: boolean) => ({ [TLSAttributes.resumed]: value }),\n },\n} as const;\n","/**\n * Attribute validation, PII detection, and guardrails\n * Provides safe-by-default attribute handling with configurable policies\n */\n\nimport { REDACTOR_PATTERNS } from '../attribute-redacting-processor';\n\nexport interface AttributeGuardrails {\n /** How to handle PII in attributes */\n pii?: 'allow' | 'redact' | 'hash' | 'block';\n\n /** Maximum length for attribute values */\n maxLength?: number;\n\n /** Validate enum values against known values */\n validateEnum?: boolean;\n\n /** Log warnings for deprecated attributes instead of throwing */\n warnDeprecated?: boolean;\n\n /** Custom deprecation warnings */\n deprecatedWarnings?: Record<string, string>;\n}\n\nexport interface AttributePolicy {\n guardrails?: AttributeGuardrails;\n /** Custom deprecation warnings for specific attributes */\n deprecatedWarnings?: Record<string, string>;\n}\n\nconst DEPRECATED_ATTRIBUTES = {\n 'enduser.id': 'user.id',\n 'enduser.role': 'user.roles',\n 'enduser.scope': undefined,\n 'http.method': 'http.request.method',\n 'http.host': 'server.address',\n 'http.status_code': 'http.response.status_code',\n 'http.target': 'url.path',\n 'http.url': 'url.full',\n 'http.user_agent': 'user_agent.original',\n 'http.flavor': 'network.protocol.name',\n 'http.scheme': 'url.scheme',\n 'http.server_name': 'server.address',\n 'db.name': 'db.namespace',\n 'db.operation': 'db.operation.name',\n 'db.statement': 'db.query.text',\n 'db.system': 'db.system.name',\n 'db.collection': 'db.collection.name',\n 'db.instance.id': undefined,\n 'db.jdbc.driver_classname': undefined,\n 'db.mssql.instance_name': 'mssql.instance.name',\n 'db.sql.table': 'db.collection.name',\n 'http.client_ip': 'client.address',\n 'user_agent.original': 'user_agent.original',\n} as const;\n\nconst HTTP_METHODS = new Set([\n 'GET',\n 'POST',\n 'PUT',\n 'DELETE',\n 'PATCH',\n 'HEAD',\n 'OPTIONS',\n 'TRACE',\n 'QUERY',\n '_OTHER',\n]);\n\nexport function validateAttribute(\n key: string,\n value: unknown,\n policy: AttributePolicy = {},\n): unknown {\n const { guardrails = {} } = policy;\n\n if (value === undefined || value === null) {\n return undefined;\n }\n\n // For non-string values that don't need transformation, preserve the original type\n if (typeof value !== 'string') {\n // PII checks only apply to strings\n // maxLength only applies to strings\n // validateEnum only applies to strings\n return value;\n }\n\n const stringValue = value;\n\n if (guardrails.pii) {\n const piiResult = applyPIIPolicy(key, stringValue, guardrails.pii);\n if (piiResult !== stringValue) {\n return piiResult;\n }\n }\n\n if (guardrails.maxLength && stringValue.length > guardrails.maxLength) {\n return truncateValue(key, stringValue, guardrails.maxLength);\n }\n\n if (guardrails.validateEnum && HTTP_METHODS.has(stringValue)) {\n const normalizedMethod = normalizeHTTPMethod(stringValue);\n if (normalizedMethod !== stringValue) {\n return normalizedMethod;\n }\n }\n\n return stringValue;\n}\n\nfunction applyPIIPolicy(\n key: string,\n value: string,\n pii: AttributeGuardrails['pii'],\n): string {\n if (pii === 'allow') {\n return value;\n }\n\n if (pii === 'redact') {\n return redactIfPII(key, value);\n }\n\n if (pii === 'hash') {\n return hashIfPII(key, value);\n }\n\n if (pii === 'block' && isPIIKey(key)) {\n throw new Error(\n `PII attribute \"${key}\" is blocked by guardrails. Use pii: \"allow\" to enable it.`,\n );\n }\n\n return value;\n}\n\nfunction isPIIKey(key: string): boolean {\n const piiKeyPatterns = [\n 'email',\n 'phone',\n 'ssn',\n 'credit_card',\n 'password',\n 'secret',\n 'token',\n 'api_key',\n 'authorization',\n ];\n const lowerKey = key.toLowerCase();\n return piiKeyPatterns.some((pattern) => lowerKey.includes(pattern));\n}\n\nfunction redactIfPII(key: string, value: string): string {\n if (isPIIKey(key)) {\n // REDACTOR_PATTERNS values are RegExp patterns\n for (const [, pattern] of Object.entries(REDACTOR_PATTERNS)) {\n if (pattern instanceof RegExp && pattern.test(value)) {\n return '[REDACTED]';\n }\n }\n // If no pattern matched but key is PII, still redact\n return '[REDACTED]';\n }\n return value;\n}\n\nfunction hashIfPII(key: string, value: string): string {\n if (!isPIIKey(key)) {\n return value;\n }\n\n // Use a simple but consistent hash that produces 32-char hex\n // FNV-1a hash variant producing 128-bit output (32 hex chars)\n const FNV_PRIME = 0x01_00_01_93;\n const FNV_OFFSET = 0x81_1c_9d_c5;\n\n // Generate 4 32-bit hashes to produce 32 hex chars\n const hashes: number[] = [];\n for (let round = 0; round < 4; round++) {\n let hash = FNV_OFFSET;\n for (let i = 0; i < value.length; i++) {\n hash ^= (value.codePointAt(i) ?? 0) + round;\n hash = Math.imul(hash, FNV_PRIME);\n }\n hashes.push(hash >>> 0); // Convert to unsigned\n }\n\n return `hash_${hashes.map((h) => h.toString(16).padStart(8, '0')).join('')}`;\n}\n\nfunction truncateValue(key: string, value: string, maxLength: number): string {\n if (value.length <= maxLength) {\n return value;\n }\n return value.slice(0, maxLength - 3) + '...';\n}\n\nfunction normalizeHTTPMethod(method: string): string {\n const upper = method.toUpperCase();\n if (HTTP_METHODS.has(upper)) {\n return upper;\n }\n return upper;\n}\n\nexport function checkDeprecatedAttribute(\n key: string,\n policy: AttributePolicy = {},\n): string | null {\n const { guardrails = {}, deprecatedWarnings = {} } = policy;\n const { warnDeprecated = true } = guardrails;\n\n if (!warnDeprecated) {\n return null;\n }\n\n // Check if the key exists in the deprecated attributes map\n const isDeprecated = key in DEPRECATED_ATTRIBUTES;\n if (isDeprecated) {\n const replacement =\n DEPRECATED_ATTRIBUTES[key as keyof typeof DEPRECATED_ATTRIBUTES];\n if (replacement === undefined) {\n // Deprecated with no replacement (e.g., enduser.scope)\n console.warn(\n `[autotel/attributes] Attribute \"${key}\" is deprecated and has no replacement. ` +\n `Remove or find a replacement in OpenTelemetry semantic conventions.`,\n );\n } else {\n // Deprecated with a known replacement\n console.warn(\n `[autotel/attributes] Attribute \"${key}\" is deprecated. Use \"${replacement}\" instead.`,\n );\n }\n }\n\n if (deprecatedWarnings[key]) {\n console.warn(`[autotel/attributes] ${deprecatedWarnings[key]}`);\n }\n\n const replacement =\n DEPRECATED_ATTRIBUTES[key as keyof typeof DEPRECATED_ATTRIBUTES];\n return replacement ?? null;\n}\n\nexport function autoRedactPII(\n attributes: Record<string, unknown>,\n policy: AttributePolicy = {},\n): Record<string, unknown> {\n const { guardrails = { pii: 'redact' } } = policy;\n\n const redacted: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(attributes)) {\n redacted[key] = validateAttribute(key, value, { guardrails });\n }\n return redacted;\n}\n\nexport function defaultGuardrails(): AttributeGuardrails {\n return {\n pii: 'redact',\n maxLength: 255,\n validateEnum: true,\n warnDeprecated: true,\n };\n}\n","/**\n * Attribute utility functions\n */\n\nimport type { AttributeValue } from '../trace-context';\nimport {\n validateAttribute,\n autoRedactPII,\n defaultGuardrails,\n checkDeprecatedAttribute,\n type AttributePolicy,\n} from './validators';\n\n// Type for objects that have setAttributes method (spans or contexts)\n// Using a generic parameter to accommodate different AttributeValue types\ntype AttributeSetter = {\n setAttributes: (attrs: Record<string, AttributeValue>) => void;\n};\n\nexport function mergeAttrs(\n ...attrSets: Array<Record<string, unknown> | undefined>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const attrSet of attrSets) {\n if (attrSet) {\n Object.assign(result, attrSet);\n }\n }\n return result;\n}\n\nexport function safeSetAttributes(\n span: AttributeSetter,\n attrs: Record<string, unknown>,\n policy?: AttributePolicy,\n): void {\n // Merge user-supplied guardrails with defaults so callers can tweak\n // a single option without opting out of the rest\n const mergedGuardrails = {\n ...defaultGuardrails(),\n ...policy?.guardrails,\n };\n const effectivePolicy: AttributePolicy = {\n ...policy,\n guardrails: mergedGuardrails,\n };\n\n const validated = autoRedactPII(attrs, effectivePolicy);\n\n const sanitizedAttrs: Record<string, AttributeValue> = {};\n for (const [key, value] of Object.entries(validated)) {\n if (value !== undefined) {\n // Check for deprecated attributes and log warnings\n checkDeprecatedAttribute(key, effectivePolicy);\n const validatedValue = validateAttribute(key, value, effectivePolicy);\n if (validatedValue !== undefined) {\n // Cast to AttributeValue since validateAttribute ensures valid types\n sanitizedAttrs[key] = validatedValue as AttributeValue;\n }\n }\n }\n\n span.setAttributes(sanitizedAttrs);\n}\n","/**\n * Signal attachment helpers\n * These functions know WHERE to attach attributes automatically\n * They handle span, resource, and log signals correctly\n */\n\nimport type { Span, Attributes } from '@opentelemetry/api';\nimport {\n resourceFromAttributes,\n type Resource,\n} from '@opentelemetry/resources';\nimport type { TraceContext } from '../trace-context';\nimport { attrs } from './builders';\nimport { safeSetAttributes } from './utils';\n\nexport function setUser(\n spanOrContext: Span | TraceContext,\n data: import('./types').UserAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.user.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function setSession(\n spanOrContext: Span | TraceContext,\n data: import('./types').SessionAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.session.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function setDevice(\n spanOrContext: Span | TraceContext,\n data: import('./types').DeviceAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.device.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function httpServer(\n spanOrContext: Span | TraceContext,\n data: import('./types').HTTPServerAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.http.server(data);\n\n if ('updateName' in spanOrContext && data.method && data.route) {\n const span = spanOrContext as Span;\n span.updateName(`HTTP ${data.method} ${data.route}`);\n }\n\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function httpClient(\n spanOrContext: Span | TraceContext,\n data: import('./types').HTTPClientAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.http.client(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function dbClient(\n spanOrContext: Span | TraceContext,\n data: import('./types').DBAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.db.client.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\n/**\n * Merge service attributes into a Resource and return a new Resource.\n *\n * Resource.attributes is readonly, so this function returns a new merged\n * Resource rather than mutating the input.\n *\n * @param resource - The existing resource to merge with\n * @param data - Service attributes to add\n * @returns A new Resource with the merged attributes\n *\n * @example\n * ```typescript\n * const baseResource = Resource.default();\n * const enrichedResource = mergeServiceResource(baseResource, {\n * name: 'my-service',\n * version: '1.0.0',\n * });\n * ```\n */\nexport function mergeServiceResource(\n resource: Resource,\n data: import('./types').ServiceAttrs,\n): Resource {\n const attributes = attrs.service.data(data);\n return resource.merge(resourceFromAttributes(attributes as Attributes));\n}\n\nexport function identify(\n spanOrContext: Span | TraceContext,\n data: {\n user?: import('./types').UserAttrs;\n session?: import('./types').SessionAttrs;\n device?: import('./types').DeviceAttrs;\n },\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const allAttrs = [];\n\n if (data.user) {\n allAttrs.push(attrs.user.data(data.user));\n }\n if (data.session) {\n allAttrs.push(attrs.session.data(data.session));\n }\n if (data.device) {\n allAttrs.push(attrs.device.data(data.device));\n }\n\n const merged: Record<string, unknown> = {};\n for (const attrSet of allAttrs) {\n Object.assign(merged, attrSet);\n }\n\n safeSetAttributes(spanOrContext, merged, guardrails);\n}\n\nexport function request(\n spanOrContext: Span | TraceContext,\n data: import('./types').HTTPServerAttrs & {\n clientIp?: string;\n },\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const httpAttrs = attrs.http.server(data);\n const networkAttrs = attrs.network.peerAddress(data.clientIp || '');\n const merged = { ...httpAttrs, ...networkAttrs };\n safeSetAttributes(spanOrContext, merged, guardrails);\n}\n\nexport function setError(\n spanOrContext: Span | TraceContext,\n data: import('./types').ErrorAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.error.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n\nexport function setException(\n spanOrContext: Span | TraceContext,\n data: import('./types').ExceptionAttrs,\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const attributes = attrs.exception.data(data);\n safeSetAttributes(spanOrContext, attributes, guardrails);\n}\n","/**\n * Domain helpers for common attribute patterns\n * These bundle multiple attribute groups into semantic helpers\n */\n\nimport { attrs } from './builders';\nimport { safeSetAttributes } from './utils';\n\nexport function transaction(\n spanOrContext: import('../trace-context').TraceContext,\n config: {\n user?: import('./types').UserAttrs;\n session?: import('./types').SessionAttrs;\n method?: string;\n route?: string;\n statusCode?: number;\n clientIp?: string;\n },\n guardrails?: import('./validators').AttributePolicy,\n): void {\n const userAttrs = attrs.user.data(config.user || {});\n const sessionAttrs = attrs.session.data(config.session || {});\n const httpAttrs = attrs.http.server({\n method: config.method,\n route: config.route,\n statusCode: config.statusCode,\n });\n const networkAttrs = attrs.network.peerAddress(config.clientIp || '');\n\n const merged = {\n ...userAttrs,\n ...sessionAttrs,\n ...httpAttrs,\n ...networkAttrs,\n };\n\n if (config.method && config.route && 'updateName' in spanOrContext) {\n spanOrContext.updateName(`HTTP ${config.method} ${config.route}`);\n }\n\n safeSetAttributes(spanOrContext, merged, guardrails);\n}\n"],"mappings":"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"}