@ai-sdk/otel 1.0.0-beta.59 → 1.0.0-beta.60

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.
@@ -0,0 +1,151 @@
1
+ import type { Attributes, Tracer } from '@opentelemetry/api';
2
+ import type { TelemetryOptions } from 'ai';
3
+ import { selectAttributes, type AttributeSpecMap } from './select-attributes';
4
+
5
+ type SupplementalAttributeOption =
6
+ | 'usage'
7
+ | 'providerMetadata'
8
+ | 'embedding'
9
+ | 'reranking'
10
+ | 'runtimeContext'
11
+ | 'headers'
12
+ | 'toolChoice'
13
+ | 'schema';
14
+
15
+ export type SupplementalAttributeOptions = Record<
16
+ SupplementalAttributeOption,
17
+ boolean
18
+ >;
19
+
20
+ export type OpenTelemetryOptions = {
21
+ /**
22
+ * The tracer to use for the telemetry data.
23
+ */
24
+ tracer?: Tracer;
25
+
26
+ /**
27
+ * Emit AI SDK usage details that are not represented by GenAI SemConv.
28
+ */
29
+ usage?: boolean;
30
+
31
+ /**
32
+ * Emit provider metadata on response spans.
33
+ */
34
+ providerMetadata?: boolean;
35
+
36
+ /**
37
+ * Emit embedding input and output values.
38
+ */
39
+ embedding?: boolean;
40
+
41
+ /**
42
+ * Emit reranking input documents and output ranking.
43
+ */
44
+ reranking?: boolean;
45
+
46
+ /**
47
+ * Emit runtime context values.
48
+ */
49
+ runtimeContext?: boolean;
50
+
51
+ /**
52
+ * Emit request headers.
53
+ */
54
+ headers?: boolean;
55
+
56
+ /**
57
+ * Emit selected tool choice information.
58
+ */
59
+ toolChoice?: boolean;
60
+
61
+ /**
62
+ * Emit object generation schema information.
63
+ */
64
+ schema?: boolean;
65
+ };
66
+
67
+ const disabledSupplementalAttributes: SupplementalAttributeOptions = {
68
+ usage: false,
69
+ providerMetadata: false,
70
+ embedding: false,
71
+ reranking: false,
72
+ runtimeContext: false,
73
+ headers: false,
74
+ toolChoice: false,
75
+ schema: false,
76
+ };
77
+
78
+ export function normalizeSupplementalAttributes(
79
+ options: OpenTelemetryOptions,
80
+ ): SupplementalAttributeOptions {
81
+ return {
82
+ ...disabledSupplementalAttributes,
83
+ usage: options.usage ?? false,
84
+ providerMetadata: options.providerMetadata ?? false,
85
+ embedding: options.embedding ?? false,
86
+ reranking: options.reranking ?? false,
87
+ runtimeContext: options.runtimeContext ?? false,
88
+ headers: options.headers ?? false,
89
+ toolChoice: options.toolChoice ?? false,
90
+ schema: options.schema ?? false,
91
+ };
92
+ }
93
+
94
+ export function getRuntimeContextAttributes(
95
+ context: Record<string, unknown> | undefined,
96
+ ): AttributeSpecMap {
97
+ return Object.fromEntries(
98
+ Object.entries(context ?? {})
99
+ .filter(([, value]) => value != null)
100
+ .map(([key, value]) => [`ai.settings.context.${key}`, value]),
101
+ ) as AttributeSpecMap;
102
+ }
103
+
104
+ export function getHeaderAttributes(
105
+ headers: Record<string, string | undefined> | undefined,
106
+ ): AttributeSpecMap {
107
+ return Object.fromEntries(
108
+ Object.entries(headers ?? {})
109
+ .filter(([, value]) => value != null)
110
+ .map(([key, value]) => [`ai.request.headers.${key}`, value]),
111
+ ) as AttributeSpecMap;
112
+ }
113
+
114
+ export function getDetailedUsageAttributes(usage: {
115
+ inputTokenDetails?: {
116
+ noCacheTokens?: number | undefined;
117
+ };
118
+ outputTokenDetails?: {
119
+ textTokens?: number | undefined;
120
+ reasoningTokens?: number | undefined;
121
+ };
122
+ }): AttributeSpecMap {
123
+ return {
124
+ 'ai.usage.inputTokenDetails.noCacheTokens':
125
+ usage.inputTokenDetails?.noCacheTokens,
126
+ 'ai.usage.outputTokenDetails.textTokens':
127
+ usage.outputTokenDetails?.textTokens,
128
+ 'ai.usage.outputTokenDetails.reasoningTokens':
129
+ usage.outputTokenDetails?.reasoningTokens,
130
+ };
131
+ }
132
+
133
+ export function selectSupplementalAttributes(
134
+ telemetry: TelemetryOptions | undefined,
135
+ enabledAttributes: SupplementalAttributeOptions,
136
+ attributes: Partial<Record<SupplementalAttributeOption, AttributeSpecMap>>,
137
+ ): Attributes {
138
+ const result: Attributes = {};
139
+
140
+ for (const [key, value] of Object.entries(attributes) as Array<
141
+ [SupplementalAttributeOption, AttributeSpecMap | undefined]
142
+ >) {
143
+ if (!enabledAttributes[key] || value == null) {
144
+ continue;
145
+ }
146
+
147
+ Object.assign(result, selectAttributes(telemetry, value));
148
+ }
149
+
150
+ return result;
151
+ }