autotel 3.7.0 → 4.0.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.
- package/dist/{attributes-ksn4HVbd.js → attributes-CmYpdqCN.js} +2 -11
- package/dist/attributes-CmYpdqCN.js.map +1 -0
- package/dist/{attributes-D3etyRVc.cjs → attributes-PZ5doLgw.cjs} +2 -11
- package/dist/attributes-PZ5doLgw.cjs.map +1 -0
- package/dist/attributes.cjs +1 -1
- package/dist/attributes.d.cts +2 -2
- package/dist/attributes.d.ts +2 -2
- package/dist/attributes.js +1 -1
- package/dist/{index-CX0aG1Uh.d.ts → index-Ck06vlW2.d.ts} +2 -32
- package/dist/index-Ck06vlW2.d.ts.map +1 -0
- package/dist/{index-DIWZFKUS.d.cts → index-eKuioqT1.d.cts} +2 -32
- package/dist/index-eKuioqT1.d.cts.map +1 -0
- package/dist/index.cjs +2 -346
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -171
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +3 -171
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -333
- package/dist/index.js.map +1 -1
- package/dist/{registry-DfXA3R1L.js → registry-DVSmWg6Y.js} +2 -11
- package/dist/registry-DVSmWg6Y.js.map +1 -0
- package/dist/{registry-JZg2J3RZ.cjs → registry-DYgvb62e.cjs} +1 -16
- package/dist/registry-DYgvb62e.cjs.map +1 -0
- package/dist/semantic-conventions.cjs +1 -1
- package/dist/semantic-conventions.js +1 -1
- package/dist/semantic-helpers.cjs +0 -113
- package/dist/semantic-helpers.cjs.map +1 -1
- package/dist/semantic-helpers.d.cts +1 -114
- package/dist/semantic-helpers.d.cts.map +1 -1
- package/dist/semantic-helpers.d.ts +1 -114
- package/dist/semantic-helpers.d.ts.map +1 -1
- package/dist/semantic-helpers.js +1 -113
- package/dist/semantic-helpers.js.map +1 -1
- package/package.json +1 -1
- package/skills/analyze-traces/SKILL.md +14 -12
- package/skills/review-otel-patterns/SKILL.md +4 -2
- package/skills/tune-sampling/SKILL.md +8 -3
- package/src/attributes/builders.ts +2 -20
- package/src/attributes/index.ts +0 -1
- package/src/attributes/registry.ts +2 -9
- package/src/attributes/types.ts +0 -8
- package/src/index.ts +4 -41
- package/src/semantic-helpers.test.ts +2 -87
- package/src/semantic-helpers.ts +0 -146
- package/dist/attributes-D3etyRVc.cjs.map +0 -1
- package/dist/attributes-ksn4HVbd.js.map +0 -1
- package/dist/index-CX0aG1Uh.d.ts.map +0 -1
- package/dist/index-DIWZFKUS.d.cts.map +0 -1
- package/dist/registry-DfXA3R1L.js.map +0 -1
- package/dist/registry-JZg2J3RZ.cjs.map +0 -1
- package/src/gen-ai-cost.test.ts +0 -81
- package/src/gen-ai-cost.ts +0 -145
- package/src/gen-ai-events.test.ts +0 -135
- package/src/gen-ai-events.ts +0 -208
- package/src/gen-ai-metrics.test.ts +0 -96
- package/src/gen-ai-metrics.ts +0 -128
|
@@ -90,7 +90,7 @@ Key conventions to recognise:
|
|
|
90
90
|
- **Sequential awaits that should be parallel** — sibling spans run end-to-end instead of overlapping.
|
|
91
91
|
- **N+1 queries** — many short same-named spans (`SELECT * FROM …`) under one parent.
|
|
92
92
|
- **Cold starts** — `faas.coldstart=true` in Workers or Lambda.
|
|
93
|
-
- **Tool retries** — gen-ai spans with `gen_ai.response.
|
|
93
|
+
- **Tool retries** — gen-ai spans with `gen_ai.response.finish_reasons` containing `error` followed by another call.
|
|
94
94
|
|
|
95
95
|
### "Follow this user across services"
|
|
96
96
|
|
|
@@ -137,21 +137,23 @@ init({ service: 'my-app', debug: 'pretty', spanDumpPath: '.autotel/spans' });
|
|
|
137
137
|
|
|
138
138
|
LLM calls produce a parent span (kind `CLIENT`) with children for each tool call:
|
|
139
139
|
|
|
140
|
-
| Attribute
|
|
141
|
-
|
|
|
142
|
-
| `gen_ai.system`
|
|
143
|
-
| `gen_ai.request.model`
|
|
144
|
-
| `gen_ai.usage.input_tokens` / `output_tokens`
|
|
145
|
-
| `gen_ai.usage.
|
|
146
|
-
| `gen_ai.response.
|
|
147
|
-
| `gen_ai.tool.name`
|
|
148
|
-
| `gen_ai.cost.usd`
|
|
140
|
+
| Attribute | Meaning |
|
|
141
|
+
| ---------------------------------------------------------------------- | ---------------------------------------- |
|
|
142
|
+
| `gen_ai.provider.name` (legacy: `gen_ai.system`) | Provider (`openai`, `anthropic`, …) |
|
|
143
|
+
| `gen_ai.request.model` | Model id |
|
|
144
|
+
| `gen_ai.usage.input_tokens` / `output_tokens` | Token count |
|
|
145
|
+
| `gen_ai.usage.cache_read.input_tokens` / `cache_creation.input_tokens` | Cache hits |
|
|
146
|
+
| `gen_ai.response.finish_reasons` | `stop`, `tool_calls`, `length`, `error` |
|
|
147
|
+
| `gen_ai.tool.name` | Tool invoked (on tool-call child spans) |
|
|
148
|
+
| `gen_ai.usage.cost.usd` | Estimated cost (if pricing map provided) |
|
|
149
|
+
|
|
150
|
+
These canonical `gen_ai.*` attributes are emitted by the `autotel-genai` package (third-party instrumentations may still emit the deprecated `gen_ai.system`).
|
|
149
151
|
|
|
150
152
|
Common findings:
|
|
151
153
|
|
|
152
|
-
- High `gen_ai.usage.input_tokens` with low `
|
|
154
|
+
- High `gen_ai.usage.input_tokens` with low `gen_ai.usage.cache_read.input_tokens` → enable prompt caching.
|
|
153
155
|
- Many sequential tool-call spans → consider parallel tool calls if the model supports it.
|
|
154
|
-
- `gen_ai.response.
|
|
156
|
+
- `gen_ai.response.finish_reasons` contains `length` → bump `max_tokens`.
|
|
155
157
|
|
|
156
158
|
## When the trace is missing
|
|
157
159
|
|
|
@@ -385,7 +385,9 @@ Compose them at build time with `composeSpanProcessors([...])` — no boilerplat
|
|
|
385
385
|
|
|
386
386
|
## AI SDK integration (gen-ai semantic conventions)
|
|
387
387
|
|
|
388
|
-
autotel implements the **OTel gen-ai semantic conventions** out of the box. Token usage, tool calls, model info, latency, cost — captured as standard attributes (`gen_ai.usage.input_tokens`, `gen_ai.tool.name`, `gen_ai.response.
|
|
388
|
+
autotel implements the **OTel gen-ai semantic conventions** out of the box. Token usage, tool calls, model info, latency, cost — captured as standard attributes (`gen_ai.usage.input_tokens`, `gen_ai.tool.name`, `gen_ai.response.finish_reasons`, …) so any backend that understands OTel can render LLM telemetry without custom mapping.
|
|
389
|
+
|
|
390
|
+
> Node.js apps get the same canonical `gen_ai.*` conventions (plus cost, metric views, and agent governance) from the `autotel-genai` package — `traceGenAI` / `recordGenAiUsage` from `autotel-genai/trace` and `genAiMetricViews` from `autotel-genai/metrics`. `withAiTelemetry` below is the edge-runtime entry point.
|
|
389
391
|
|
|
390
392
|
```typescript
|
|
391
393
|
import { trace } from 'autotel';
|
|
@@ -402,7 +404,7 @@ const handler = trace(async (req) => {
|
|
|
402
404
|
});
|
|
403
405
|
```
|
|
404
406
|
|
|
405
|
-
Captured attributes per call: `gen_ai.
|
|
407
|
+
Captured attributes per call: `gen_ai.provider.name`, `gen_ai.request.model`, `gen_ai.usage.input_tokens` / `output_tokens` / `reasoning.output_tokens` / `cache_read.input_tokens`, `gen_ai.response.finish_reasons`, `gen_ai.response.id`, plus per-tool spans with `gen_ai.tool.name`. Cost estimation (`gen_ai.usage.cost.usd`) comes for free if you pass a pricing map to `withAiTelemetry`.
|
|
406
408
|
|
|
407
409
|
Anti-patterns to detect:
|
|
408
410
|
|
|
@@ -108,7 +108,12 @@ const tail = new TailSamplingProcessor({
|
|
|
108
108
|
|
|
109
109
|
// 4. Always keep AI traces (rare + expensive — full visibility helps)
|
|
110
110
|
if (
|
|
111
|
-
trace.spans.some(
|
|
111
|
+
trace.spans.some(
|
|
112
|
+
(s) =>
|
|
113
|
+
typeof s.attributes['gen_ai.provider.name'] === 'string' ||
|
|
114
|
+
// legacy: third-party instrumentations may still emit gen_ai.system
|
|
115
|
+
typeof s.attributes['gen_ai.system'] === 'string',
|
|
116
|
+
)
|
|
112
117
|
)
|
|
113
118
|
return true;
|
|
114
119
|
|
|
@@ -142,8 +147,8 @@ keep: (trace) => {
|
|
|
142
147
|
const cost = trace.spans.reduce(
|
|
143
148
|
(acc, s) =>
|
|
144
149
|
acc +
|
|
145
|
-
(typeof s.attributes['gen_ai.cost.usd'] === 'number'
|
|
146
|
-
? (s.attributes['gen_ai.cost.usd'] as number)
|
|
150
|
+
(typeof s.attributes['gen_ai.usage.cost.usd'] === 'number'
|
|
151
|
+
? (s.attributes['gen_ai.usage.cost.usd'] as number)
|
|
147
152
|
: 0),
|
|
148
153
|
0,
|
|
149
154
|
);
|
|
@@ -38,7 +38,6 @@ import {
|
|
|
38
38
|
FaaSAttributes,
|
|
39
39
|
FeatureFlagAttributes,
|
|
40
40
|
MessagingAttributes,
|
|
41
|
-
GenAIAttributes,
|
|
42
41
|
RPCAttributes,
|
|
43
42
|
GraphQLAttributes,
|
|
44
43
|
OTelAttributes,
|
|
@@ -477,25 +476,8 @@ export const attrs = {
|
|
|
477
476
|
},
|
|
478
477
|
},
|
|
479
478
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
requestModel: (value: string) => ({
|
|
483
|
-
[GenAIAttributes.requestModel]: value,
|
|
484
|
-
}),
|
|
485
|
-
responseModel: (value: string) => ({
|
|
486
|
-
[GenAIAttributes.responseModel]: value,
|
|
487
|
-
}),
|
|
488
|
-
operationName: (value: 'chat' | 'completion' | 'embedding') => ({
|
|
489
|
-
[GenAIAttributes.operationName]: value,
|
|
490
|
-
}),
|
|
491
|
-
usagePromptTokens: (value: number) => ({
|
|
492
|
-
[GenAIAttributes.usagePromptTokens]: value,
|
|
493
|
-
}),
|
|
494
|
-
usageCompletionTokens: (value: number) => ({
|
|
495
|
-
[GenAIAttributes.usageCompletionTokens]: value,
|
|
496
|
-
}),
|
|
497
|
-
provider: (value: string) => ({ [GenAIAttributes.provider]: value }),
|
|
498
|
-
},
|
|
479
|
+
// GenAI/LLM attribute builders moved to the `autotel-genai` package
|
|
480
|
+
// (canonical `gen_ai.*` semantic conventions).
|
|
499
481
|
|
|
500
482
|
rpc: {
|
|
501
483
|
system: (value: string) => ({ [RPCAttributes.system]: value }),
|
package/src/attributes/index.ts
CHANGED
|
@@ -155,15 +155,8 @@ export const MessagingAttributes = {
|
|
|
155
155
|
consumerGroup: 'messaging.consumer.group' as const,
|
|
156
156
|
} as const;
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
requestModel: 'gen.ai.request.model' as const,
|
|
161
|
-
responseModel: 'gen.ai.response.model' as const,
|
|
162
|
-
operationName: 'gen.ai.operation.name' as const,
|
|
163
|
-
usagePromptTokens: 'gen.ai.usage.prompt_tokens' as const,
|
|
164
|
-
usageCompletionTokens: 'gen.ai.usage.completion_tokens' as const,
|
|
165
|
-
provider: 'gen.ai.provider' as const,
|
|
166
|
-
} as const;
|
|
158
|
+
// GenAI attribute registry moved to the `autotel-genai` package, which uses the
|
|
159
|
+
// canonical `gen_ai.*` namespace (these legacy `gen.ai.*` keys were non-spec).
|
|
167
160
|
|
|
168
161
|
export const RPCAttributes = {
|
|
169
162
|
system: 'rpc.system' as const,
|
package/src/attributes/types.ts
CHANGED
|
@@ -155,14 +155,6 @@ export interface ThreadAttrs {
|
|
|
155
155
|
name?: string;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
export interface GenAIAttrs {
|
|
159
|
-
system?: string;
|
|
160
|
-
requestModel?: string;
|
|
161
|
-
responseModel?: string;
|
|
162
|
-
operationName?: 'chat' | 'completion' | 'embedding';
|
|
163
|
-
provider?: string;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
158
|
export interface RPCAttrs {
|
|
167
159
|
system?: string;
|
|
168
160
|
service?: string;
|
package/src/index.ts
CHANGED
|
@@ -241,43 +241,9 @@ export {
|
|
|
241
241
|
createObservableGauge,
|
|
242
242
|
} from './metric-helpers';
|
|
243
243
|
|
|
244
|
-
// LLM
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
GEN_AI_DURATION_BUCKETS_SECONDS,
|
|
248
|
-
GEN_AI_TOKEN_USAGE_BUCKETS,
|
|
249
|
-
GEN_AI_COST_USD_BUCKETS,
|
|
250
|
-
genAiMetricViews,
|
|
251
|
-
llmHistogramAdvice,
|
|
252
|
-
} from './gen-ai-metrics';
|
|
253
|
-
|
|
254
|
-
// OTel GenAI span event helpers — record prompt-sent / response-received
|
|
255
|
-
// / retry / tool-call / stream-first-token as timestamped events aligned
|
|
256
|
-
// with the published GenAI semantic conventions.
|
|
257
|
-
export {
|
|
258
|
-
recordPromptSent,
|
|
259
|
-
recordResponseReceived,
|
|
260
|
-
recordRetry,
|
|
261
|
-
recordToolCall,
|
|
262
|
-
recordStreamFirstToken,
|
|
263
|
-
type PromptSentEvent,
|
|
264
|
-
type ResponseReceivedEvent,
|
|
265
|
-
type RetryEvent,
|
|
266
|
-
type ToolCallEvent,
|
|
267
|
-
type StreamFirstTokenEvent,
|
|
268
|
-
} from './gen-ai-events';
|
|
269
|
-
|
|
270
|
-
// Per-model LLM cost estimation — estimate USD cost from token usage and
|
|
271
|
-
// record it as the gen_ai.usage.cost.usd span attribute.
|
|
272
|
-
export {
|
|
273
|
-
estimateLLMCost,
|
|
274
|
-
recordLLMCost,
|
|
275
|
-
MODEL_PRICING,
|
|
276
|
-
GEN_AI_COST_ATTRIBUTE,
|
|
277
|
-
type ModelPricing,
|
|
278
|
-
type TokenUsage,
|
|
279
|
-
type EstimateCostOptions,
|
|
280
|
-
} from './gen-ai-cost';
|
|
244
|
+
// GenAI / LLM instrumentation (cost, token usage, metric buckets, span event
|
|
245
|
+
// helpers, traceLLM) lives in the dedicated `autotel-genai` package — canonical
|
|
246
|
+
// `gen_ai.*` semantic conventions. Core stays generic and AI-free.
|
|
281
247
|
|
|
282
248
|
// Tracer helpers for custom spans
|
|
283
249
|
export {
|
|
@@ -303,13 +269,11 @@ export {
|
|
|
303
269
|
getAutotelTracer,
|
|
304
270
|
} from './tracer-provider';
|
|
305
271
|
|
|
306
|
-
// Semantic convention helpers
|
|
272
|
+
// Semantic convention helpers (GenAI/LLM helpers moved to `autotel-genai`).
|
|
307
273
|
export {
|
|
308
|
-
traceLLM,
|
|
309
274
|
traceDB,
|
|
310
275
|
traceHTTP,
|
|
311
276
|
traceMessaging,
|
|
312
|
-
type LLMConfig,
|
|
313
277
|
type DBConfig,
|
|
314
278
|
type HTTPConfig,
|
|
315
279
|
type MessagingConfig,
|
|
@@ -389,7 +353,6 @@ export {
|
|
|
389
353
|
type K8sAttrs,
|
|
390
354
|
type FaaSAttrs,
|
|
391
355
|
type ThreadAttrs,
|
|
392
|
-
type GenAIAttrs,
|
|
393
356
|
type RPCAttrs,
|
|
394
357
|
type GraphQLAttrs,
|
|
395
358
|
type ClientAttrs,
|
|
@@ -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
|
-
|
|
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',
|
package/src/semantic-helpers.ts
CHANGED
|
@@ -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
|
*
|
|
@@ -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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"}
|