@ai-sdk/otel 1.0.0-beta.6 → 1.0.0-beta.61

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.
@@ -1,38 +1,39 @@
1
- import { LanguageModelV4Prompt } from '@ai-sdk/provider';
1
+ import type { LanguageModelV4Prompt } from '@ai-sdk/provider';
2
+ import type { Context as AISDKContext } from '@ai-sdk/provider-utils';
2
3
  import {
3
- Attributes,
4
- AttributeValue,
5
4
  context,
6
- Context,
7
- Span,
8
5
  SpanStatusCode,
9
6
  trace,
10
- Tracer,
7
+ type Attributes,
8
+ type AttributeValue,
9
+ type Context as OpenTelemetryContext,
10
+ type Span,
11
+ type Tracer,
11
12
  } from '@opentelemetry/api';
12
13
  import type {
13
- EmbedFinishEvent,
14
- EmbedOnFinishEvent,
15
- EmbedOnStartEvent,
14
+ EmbeddingModelCallEndEvent,
15
+ EmbedEndEvent,
16
16
  EmbedStartEvent,
17
- GenerationContext,
18
- ObjectOnFinishEvent,
19
- ObjectOnStartEvent,
20
- ObjectOnStepFinishEvent,
21
- ObjectOnStepStartEvent,
22
- OnChunkEvent,
23
- OnFinishEvent,
24
- OnStartEvent,
25
- OnStepFinishEvent,
26
- OnStepStartEvent,
27
- OnToolCallFinishEvent,
28
- OnToolCallStartEvent,
17
+ EmbeddingModelCallStartEvent,
18
+ GenerateObjectEndEvent,
19
+ GenerateObjectStartEvent,
20
+ GenerateObjectStepEndEvent,
21
+ GenerateObjectStepStartEvent,
22
+ StreamTextChunkEvent,
23
+ GenerateTextEndEvent,
24
+ GenerateTextStartEvent,
25
+ GenerateTextStepEndEvent,
26
+ GenerateTextStepStartEvent,
27
+ ToolExecutionEndEvent,
28
+ ToolExecutionStartEvent,
29
29
  OutputInterface as Output,
30
- RerankFinishEvent,
31
- RerankOnFinishEvent,
32
- RerankOnStartEvent,
30
+ RerankingModelCallEndEvent,
31
+ RerankEndEvent,
33
32
  RerankStartEvent,
34
- TelemetryIntegration,
35
- TelemetrySettings,
33
+ RerankingModelCallStartEvent,
34
+ InferTelemetryEvent,
35
+ Telemetry,
36
+ TelemetryOptions,
36
37
  ToolSet,
37
38
  } from 'ai';
38
39
  import { assembleOperationName } from './assemble-operation-name';
@@ -56,13 +57,13 @@ function recordSpanError(span: Span, error: unknown): void {
56
57
  }
57
58
 
58
59
  function shouldRecord(
59
- telemetry: TelemetrySettings | undefined,
60
- ): telemetry is TelemetrySettings {
61
- return telemetry?.isEnabled === true;
60
+ telemetry: TelemetryOptions | undefined,
61
+ ): telemetry is TelemetryOptions {
62
+ return telemetry?.isEnabled !== false;
62
63
  }
63
64
 
64
65
  function selectAttributes(
65
- telemetry: TelemetrySettings | undefined,
66
+ telemetry: TelemetryOptions | undefined,
66
67
  attributes: Record<
67
68
  string,
68
69
  | AttributeValue
@@ -110,9 +111,9 @@ function selectAttributes(
110
111
 
111
112
  interface OtelStepStartEvent<
112
113
  TOOLS extends ToolSet = ToolSet,
113
- CONTEXT extends GenerationContext<TOOLS> = GenerationContext<TOOLS>,
114
+ RUNTIME_CONTEXT extends AISDKContext = AISDKContext,
114
115
  OUTPUT extends Output = Output,
115
- > extends OnStepStartEvent<TOOLS, CONTEXT, OUTPUT> {
116
+ > extends GenerateTextStepStartEvent<TOOLS, RUNTIME_CONTEXT, OUTPUT> {
116
117
  readonly promptMessages?: LanguageModelV4Prompt;
117
118
  readonly stepTools?: ReadonlyArray<Record<string, unknown>>;
118
119
  readonly stepToolChoice?: unknown;
@@ -120,19 +121,19 @@ interface OtelStepStartEvent<
120
121
 
121
122
  interface CallState {
122
123
  operationId: string;
123
- telemetry: TelemetrySettings | undefined;
124
+ telemetry: TelemetryOptions | undefined;
124
125
  rootSpan: Span | undefined;
125
- rootContext: Context | undefined;
126
+ rootContext: OpenTelemetryContext | undefined;
126
127
  stepSpan: Span | undefined;
127
- stepContext: Context | undefined;
128
- embedSpans: Map<string, { span: Span; context: Context }>;
129
- rerankSpan: { span: Span; context: Context } | undefined;
130
- toolSpans: Map<string, { span: Span; context: Context }>;
128
+ stepContext: OpenTelemetryContext | undefined;
129
+ embedSpans: Map<string, { span: Span; context: OpenTelemetryContext }>;
130
+ rerankSpan: { span: Span; context: OpenTelemetryContext } | undefined;
131
+ toolSpans: Map<string, { span: Span; context: OpenTelemetryContext }>;
131
132
  baseTelemetryAttributes: Attributes;
132
133
  settings: Record<string, unknown>;
133
134
  }
134
135
 
135
- export class OpenTelemetryIntegration implements TelemetryIntegration {
136
+ export class LegacyOpenTelemetry implements Telemetry {
136
137
  private readonly callStates = new Map<string, CallState>();
137
138
 
138
139
  /**
@@ -176,23 +177,23 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
176
177
 
177
178
  onStart(
178
179
  event:
179
- | OnStartEvent<ToolSet, Output>
180
- | ObjectOnStartEvent
181
- | EmbedOnStartEvent
182
- | RerankOnStartEvent,
180
+ | InferTelemetryEvent<GenerateTextStartEvent>
181
+ | InferTelemetryEvent<GenerateObjectStartEvent>
182
+ | InferTelemetryEvent<EmbedStartEvent>
183
+ | InferTelemetryEvent<RerankStartEvent>,
183
184
  ): void {
184
- if (event.isEnabled !== true) return;
185
-
186
185
  if (
187
186
  event.operationId === 'ai.embed' ||
188
187
  event.operationId === 'ai.embedMany'
189
188
  ) {
190
- this.onEmbedOperationStart(event as EmbedOnStartEvent);
189
+ this.onEmbedOperationStart(event as InferTelemetryEvent<EmbedStartEvent>);
191
190
  return;
192
191
  }
193
192
 
194
193
  if (event.operationId === 'ai.rerank') {
195
- this.onRerankOperationStart(event as RerankOnStartEvent);
194
+ this.onRerankOperationStart(
195
+ event as InferTelemetryEvent<RerankStartEvent>,
196
+ );
196
197
  return;
197
198
  }
198
199
 
@@ -200,20 +201,22 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
200
201
  event.operationId === 'ai.generateObject' ||
201
202
  event.operationId === 'ai.streamObject'
202
203
  ) {
203
- this.onObjectOperationStart(event as ObjectOnStartEvent);
204
+ this.onObjectOperationStart(
205
+ event as InferTelemetryEvent<GenerateObjectStartEvent>,
206
+ );
204
207
  return;
205
208
  }
206
209
 
207
- this.onGenerateStart(event as OnStartEvent<ToolSet, Output>);
210
+ this.onGenerateStart(event as InferTelemetryEvent<GenerateTextStartEvent>);
208
211
  }
209
212
 
210
- private onGenerateStart(event: OnStartEvent<ToolSet, Output>): void {
211
- const telemetry: TelemetrySettings = {
212
- isEnabled: event.isEnabled,
213
+ private onGenerateStart(
214
+ event: InferTelemetryEvent<GenerateTextStartEvent>,
215
+ ): void {
216
+ const telemetry: TelemetryOptions = {
213
217
  recordInputs: event.recordInputs,
214
218
  recordOutputs: event.recordOutputs,
215
219
  functionId: event.functionId,
216
- metadata: event.metadata,
217
220
  };
218
221
 
219
222
  const settings: Record<string, unknown> = {
@@ -230,9 +233,9 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
230
233
 
231
234
  const baseTelemetryAttributes = getBaseTelemetryAttributes({
232
235
  model: { provider: event.provider, modelId: event.modelId },
233
- telemetry,
234
236
  headers: event.headers,
235
237
  settings,
238
+ context: event.runtimeContext as Record<string, unknown> | undefined,
236
239
  });
237
240
 
238
241
  const attributes = selectAttributes(telemetry, {
@@ -247,7 +250,6 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
247
250
  input: () =>
248
251
  JSON.stringify({
249
252
  system: event.system,
250
- prompt: event.prompt,
251
253
  messages: event.messages,
252
254
  }),
253
255
  },
@@ -271,13 +273,13 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
271
273
  });
272
274
  }
273
275
 
274
- private onObjectOperationStart(event: ObjectOnStartEvent): void {
275
- const telemetry: TelemetrySettings = {
276
- isEnabled: event.isEnabled,
276
+ private onObjectOperationStart(
277
+ event: InferTelemetryEvent<GenerateObjectStartEvent>,
278
+ ): void {
279
+ const telemetry: TelemetryOptions = {
277
280
  recordInputs: event.recordInputs,
278
281
  recordOutputs: event.recordOutputs,
279
282
  functionId: event.functionId,
280
- metadata: event.metadata,
281
283
  };
282
284
 
283
285
  const settings: Record<string, unknown> = {
@@ -293,9 +295,9 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
293
295
 
294
296
  const baseTelemetryAttributes = getBaseTelemetryAttributes({
295
297
  model: { provider: event.provider, modelId: event.modelId },
296
- telemetry,
297
298
  headers: event.headers,
298
299
  settings,
300
+ context: undefined,
299
301
  });
300
302
 
301
303
  const attributes = selectAttributes(telemetry, {
@@ -339,7 +341,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
339
341
  }
340
342
 
341
343
  /** @deprecated */
342
- onObjectStepStart(event: ObjectOnStepStartEvent): void {
344
+ onObjectStepStart(event: GenerateObjectStepStartEvent): void {
343
345
  const state = this.getCallState(event.callId);
344
346
  if (!state?.rootSpan || !state.rootContext) return;
345
347
 
@@ -390,7 +392,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
390
392
  }
391
393
 
392
394
  /** @deprecated */
393
- onObjectStepFinish(event: ObjectOnStepFinishEvent): void {
395
+ onObjectStepFinish(event: GenerateObjectStepEndEvent): void {
394
396
  const state = this.getCallState(event.callId);
395
397
  if (!state?.stepSpan) return;
396
398
 
@@ -443,13 +445,13 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
443
445
  state.stepContext = undefined;
444
446
  }
445
447
 
446
- private onEmbedOperationStart(event: EmbedOnStartEvent): void {
447
- const telemetry: TelemetrySettings = {
448
- isEnabled: event.isEnabled,
448
+ private onEmbedOperationStart(
449
+ event: InferTelemetryEvent<EmbedStartEvent>,
450
+ ): void {
451
+ const telemetry: TelemetryOptions = {
449
452
  recordInputs: event.recordInputs,
450
453
  recordOutputs: event.recordOutputs,
451
454
  functionId: event.functionId,
452
- metadata: event.metadata,
453
455
  };
454
456
 
455
457
  const settings: Record<string, unknown> = {
@@ -458,9 +460,9 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
458
460
 
459
461
  const baseTelemetryAttributes = getBaseTelemetryAttributes({
460
462
  model: { provider: event.provider, modelId: event.modelId },
461
- telemetry,
462
463
  headers: event.headers,
463
464
  settings,
465
+ context: undefined,
464
466
  });
465
467
 
466
468
  const value = event.value;
@@ -503,7 +505,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
503
505
  });
504
506
  }
505
507
 
506
- onStepStart(event: OtelStepStartEvent<ToolSet, Output>): void {
508
+ onStepStart(event: OtelStepStartEvent): void {
507
509
  const state = this.getCallState(event.callId);
508
510
  if (!state?.rootSpan || !state.rootContext) return;
509
511
 
@@ -568,7 +570,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
568
570
  state.stepContext = trace.setSpan(state.rootContext, state.stepSpan);
569
571
  }
570
572
 
571
- onToolCallStart(event: OnToolCallStartEvent<ToolSet>): void {
573
+ onToolExecutionStart(event: ToolExecutionStartEvent<ToolSet>): void {
572
574
  const state = this.getCallState(event.callId);
573
575
  if (!state?.stepContext) return;
574
576
 
@@ -600,7 +602,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
600
602
  });
601
603
  }
602
604
 
603
- onToolCallFinish(event: OnToolCallFinishEvent<ToolSet>): void {
605
+ onToolExecutionEnd(event: ToolExecutionEndEvent<ToolSet>): void {
604
606
  const state = this.getCallState(event.callId);
605
607
  if (!state) return;
606
608
 
@@ -610,27 +612,28 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
610
612
  const { span } = toolSpanEntry;
611
613
  const { telemetry } = state;
612
614
 
613
- if (event.success) {
615
+ const { toolOutput } = event;
616
+ if (toolOutput.type === 'tool-result') {
614
617
  try {
615
618
  span.setAttributes(
616
619
  selectAttributes(telemetry, {
617
620
  'ai.toolCall.result': {
618
- output: () => JSON.stringify(event.output),
621
+ output: () => JSON.stringify(toolOutput.output),
619
622
  },
620
623
  }),
621
624
  );
622
- } catch (_ignored) {
625
+ } catch {
623
626
  // JSON.stringify might fail for non-serializable results
624
627
  }
625
628
  } else {
626
- recordSpanError(span, event.error);
629
+ recordSpanError(span, toolOutput.error);
627
630
  }
628
631
 
629
632
  span.end();
630
633
  state.toolSpans.delete(event.toolCall.toolCallId);
631
634
  }
632
635
 
633
- onStepFinish(event: OnStepFinishEvent<ToolSet>): void {
636
+ onStepFinish(event: GenerateTextStepEndEvent<ToolSet>): void {
634
637
  const state = this.getCallState(event.callId);
635
638
  if (!state?.stepSpan) return;
636
639
 
@@ -713,10 +716,10 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
713
716
 
714
717
  onFinish(
715
718
  event:
716
- | OnFinishEvent<ToolSet>
717
- | ObjectOnFinishEvent<unknown>
718
- | EmbedOnFinishEvent
719
- | RerankOnFinishEvent,
719
+ | GenerateTextEndEvent<ToolSet>
720
+ | GenerateObjectEndEvent<unknown>
721
+ | EmbedEndEvent
722
+ | RerankEndEvent,
720
723
  ): void {
721
724
  const state = this.getCallState(event.callId);
722
725
  if (!state?.rootSpan) return;
@@ -725,12 +728,12 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
725
728
  state.operationId === 'ai.embed' ||
726
729
  state.operationId === 'ai.embedMany'
727
730
  ) {
728
- this.onEmbedOperationFinish(event as EmbedOnFinishEvent);
731
+ this.onEmbedOperationFinish(event as EmbedEndEvent);
729
732
  return;
730
733
  }
731
734
 
732
735
  if (state.operationId === 'ai.rerank') {
733
- this.onRerankOperationFinish(event as RerankOnFinishEvent);
736
+ this.onRerankOperationFinish(event as RerankEndEvent);
734
737
  return;
735
738
  }
736
739
 
@@ -738,14 +741,14 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
738
741
  state.operationId === 'ai.generateObject' ||
739
742
  state.operationId === 'ai.streamObject'
740
743
  ) {
741
- this.onObjectOperationFinish(event as ObjectOnFinishEvent<unknown>);
744
+ this.onObjectOperationFinish(event as GenerateObjectEndEvent<unknown>);
742
745
  return;
743
746
  }
744
747
 
745
- this.onGenerateFinish(event as OnFinishEvent<ToolSet>);
748
+ this.onGenerateFinish(event as GenerateTextEndEvent<ToolSet>);
746
749
  }
747
750
 
748
- private onGenerateFinish(event: OnFinishEvent<ToolSet>): void {
751
+ private onGenerateFinish(event: GenerateTextEndEvent<ToolSet>): void {
749
752
  const state = this.getCallState(event.callId);
750
753
  if (!state?.rootSpan) return;
751
754
 
@@ -816,7 +819,9 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
816
819
  this.cleanupCallState(event.callId);
817
820
  }
818
821
 
819
- private onObjectOperationFinish(event: ObjectOnFinishEvent<unknown>): void {
822
+ private onObjectOperationFinish(
823
+ event: GenerateObjectEndEvent<unknown>,
824
+ ): void {
820
825
  const state = this.getCallState(event.callId);
821
826
  if (!state?.rootSpan) return;
822
827
 
@@ -845,7 +850,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
845
850
  this.cleanupCallState(event.callId);
846
851
  }
847
852
 
848
- private onEmbedOperationFinish(event: EmbedOnFinishEvent): void {
853
+ private onEmbedOperationFinish(event: EmbedEndEvent): void {
849
854
  const state = this.getCallState(event.callId);
850
855
  if (!state?.rootSpan) return;
851
856
 
@@ -874,7 +879,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
874
879
  this.cleanupCallState(event.callId);
875
880
  }
876
881
 
877
- onEmbedStart(event: EmbedStartEvent): void {
882
+ onEmbedStart(event: EmbeddingModelCallStartEvent): void {
878
883
  const state = this.getCallState(event.callId);
879
884
  if (!state?.rootSpan || !state.rootContext) return;
880
885
 
@@ -904,7 +909,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
904
909
  });
905
910
  }
906
911
 
907
- onEmbedFinish(event: EmbedFinishEvent): void {
912
+ onEmbedFinish(event: EmbeddingModelCallEndEvent): void {
908
913
  const state = this.getCallState(event.callId);
909
914
  if (!state) return;
910
915
 
@@ -928,13 +933,13 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
928
933
  state.embedSpans.delete(event.embedCallId);
929
934
  }
930
935
 
931
- private onRerankOperationStart(event: RerankOnStartEvent): void {
932
- const telemetry: TelemetrySettings = {
933
- isEnabled: event.isEnabled,
936
+ private onRerankOperationStart(
937
+ event: InferTelemetryEvent<RerankStartEvent>,
938
+ ): void {
939
+ const telemetry: TelemetryOptions = {
934
940
  recordInputs: event.recordInputs,
935
941
  recordOutputs: event.recordOutputs,
936
942
  functionId: event.functionId,
937
- metadata: event.metadata,
938
943
  };
939
944
 
940
945
  const settings: Record<string, unknown> = {
@@ -943,9 +948,9 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
943
948
 
944
949
  const baseTelemetryAttributes = getBaseTelemetryAttributes({
945
950
  model: { provider: event.provider, modelId: event.modelId },
946
- telemetry,
947
951
  headers: event.headers,
948
952
  settings,
953
+ context: undefined,
949
954
  });
950
955
 
951
956
  const attributes = selectAttributes(telemetry, {
@@ -977,7 +982,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
977
982
  });
978
983
  }
979
984
 
980
- private onRerankOperationFinish(event: RerankOnFinishEvent): void {
985
+ private onRerankOperationFinish(event: RerankEndEvent): void {
981
986
  const state = this.getCallState(event.callId);
982
987
  if (!state?.rootSpan) return;
983
988
 
@@ -985,7 +990,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
985
990
  this.cleanupCallState(event.callId);
986
991
  }
987
992
 
988
- onRerankStart(event: RerankStartEvent): void {
993
+ onRerankStart(event: RerankingModelCallStartEvent): void {
989
994
  const state = this.getCallState(event.callId);
990
995
  if (!state?.rootSpan || !state.rootContext) return;
991
996
 
@@ -1012,7 +1017,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
1012
1017
  state.rerankSpan = { span: rerankSpan, context: rerankContext };
1013
1018
  }
1014
1019
 
1015
- onRerankFinish(event: RerankFinishEvent): void {
1020
+ onRerankFinish(event: RerankingModelCallEndEvent): void {
1016
1021
  const state = this.getCallState(event.callId);
1017
1022
  if (!state?.rerankSpan) return;
1018
1023
 
@@ -1032,7 +1037,7 @@ export class OpenTelemetryIntegration implements TelemetryIntegration {
1032
1037
  state.rerankSpan = undefined;
1033
1038
  }
1034
1039
 
1035
- onChunk(event: OnChunkEvent<ToolSet>): void {
1040
+ onChunk(event: StreamTextChunkEvent<ToolSet>): void {
1036
1041
  const chunk = event.chunk as {
1037
1042
  type: string;
1038
1043
  callId?: unknown;
@@ -1,4 +1,4 @@
1
- import {
1
+ import type {
2
2
  AttributeValue,
3
3
  Attributes,
4
4
  Context,
@@ -1,4 +1,4 @@
1
- import { Span, SpanContext, Tracer } from '@opentelemetry/api';
1
+ import type { Span, SpanContext, Tracer } from '@opentelemetry/api';
2
2
 
3
3
  /**
4
4
  * Tracer implementation that does nothing (null object).