@ai-sdk/otel 1.0.159 → 1.0.161

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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @ai-sdk/otel
2
2
 
3
+ ## 1.0.161
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [51ca5b7]
8
+ - Updated dependencies [51ca5b7]
9
+ - Updated dependencies [51ca5b7]
10
+ - ai@7.0.161
11
+
12
+ ## 1.0.160
13
+
14
+ ### Patch Changes
15
+
16
+ - 5946558: Record the `gen_ai.client.inference.duration` OpenTelemetry histogram in seconds for `generateText` and `streamText` model calls, including errors, cancellation, and failed stream retry attempts, so configured metric exporters can report inference latency.
17
+ - Updated dependencies [a71172d]
18
+ - Updated dependencies [cf27969]
19
+ - Updated dependencies [17b6923]
20
+ - ai@7.0.160
21
+
3
22
  ## 1.0.159
4
23
 
5
24
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -86,6 +86,7 @@ export declare class OpenTelemetry implements Telemetry {
86
86
  constructor(options?: OpenTelemetryOptions);
87
87
  private getCallState;
88
88
  private cleanupCallState;
89
+ private recordInferenceDuration;
89
90
  private getAgentSpanName;
90
91
  private getSpanAttributes;
91
92
  executeTool<T>({ callId, toolCallId, execute }: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":["OtelStepStartEvent","StreamTranscriptionStartEvent","StreamTranscriptionEndEvent","DecideStartEvent","DecideEndEvent","DecisionModelCallStartEvent","DecisionModelCallEndEvent","AISDKContext","StreamTranscriptionStartEvent","StreamTranscriptionEndEvent","DecideStartEvent","DecideEndEvent","DecisionModelCallStartEvent","DecisionModelCallEndEvent"],"sources":["../src/supplemental-attributes.ts","../src/open-telemetry.ts","../../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/schemas.d.cts","../../provider-utils/dist/index.d.ts","../src/legacy-open-telemetry.ts"],"x_google_ignoreList":[2],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":["OtelStepStartEvent","StreamTranscriptionStartEvent","StreamTranscriptionEndEvent","DecideStartEvent","DecideEndEvent","DecisionModelCallStartEvent","DecisionModelCallEndEvent","AISDKContext","StreamTranscriptionStartEvent","StreamTranscriptionEndEvent","DecideStartEvent","DecideEndEvent","DecisionModelCallStartEvent","DecisionModelCallEndEvent"],"sources":["../src/supplemental-attributes.ts","../src/open-telemetry.ts","../../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/schemas.d.cts","../../provider-utils/dist/index.d.ts","../src/legacy-open-telemetry.ts"],"x_google_ignoreList":[2],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { SpanKind, SpanStatusCode, context, trace } from "@opentelemetry/api";
1
+ import { SpanKind, SpanStatusCode, context, metrics, trace } from "@opentelemetry/api";
2
2
  import { RetryError, convertDataContentToBase64String } from "ai";
3
3
  import { APICallError } from "@ai-sdk/provider";
4
4
  //#region src/gen-ai-format-messages.ts
@@ -693,6 +693,37 @@ var OpenTelemetry = class {
693
693
  cleanupCallState(callId) {
694
694
  this.callStates.delete(callId);
695
695
  }
696
+ recordInferenceDuration(state, { responseTimeMs, provider, responseModelId, errorType } = {}) {
697
+ const inference = state.inferenceMetrics;
698
+ if (inference == null) return;
699
+ state.inferenceMetrics = void 0;
700
+ metrics.getMeter("gen_ai").createHistogram("gen_ai.client.inference.duration", {
701
+ description: "GenAI client inference operation duration.",
702
+ unit: "s",
703
+ advice: { explicitBucketBoundaries: [
704
+ .01,
705
+ .02,
706
+ .04,
707
+ .08,
708
+ .16,
709
+ .32,
710
+ .64,
711
+ 1.28,
712
+ 2.56,
713
+ 5.12,
714
+ 10.24,
715
+ 20.48,
716
+ 40.96,
717
+ 81.92
718
+ ] }
719
+ }).record((responseTimeMs ?? performance.now() - inference.startTime) / 1e3, selectAttributes$1(state.telemetry, {
720
+ "gen_ai.operation.name": "chat",
721
+ "gen_ai.provider.name": mapProviderName(provider ?? inference.provider),
722
+ "gen_ai.request.model": inference.modelId,
723
+ "gen_ai.response.model": responseModelId,
724
+ "error.type": errorType
725
+ }), state.inferenceContext);
726
+ }
696
727
  getAgentSpanName({ operationName, modelId, functionId }) {
697
728
  const defaultName = `${operationName} ${modelId}`;
698
729
  if (operationName !== "invoke_agent") return defaultName;
@@ -1135,9 +1166,15 @@ var OpenTelemetry = class {
1135
1166
  onLanguageModelCallStart(event) {
1136
1167
  const state = this.getCallState(event.callId);
1137
1168
  if (!state?.stepContext) return;
1169
+ this.recordInferenceDuration(state, { errorType: "_OTHER" });
1138
1170
  const { telemetry } = state;
1139
1171
  const providerName = mapProviderName(event.provider);
1140
1172
  state.inferenceToolDefinitions = event.tools;
1173
+ state.inferenceMetrics = {
1174
+ startTime: performance.now(),
1175
+ provider: event.provider,
1176
+ modelId: event.modelId
1177
+ };
1141
1178
  const inferenceAttributes = selectAttributes$1(telemetry, {
1142
1179
  "gen_ai.operation.name": "chat",
1143
1180
  "gen_ai.provider.name": providerName,
@@ -1174,6 +1211,12 @@ var OpenTelemetry = class {
1174
1211
  onLanguageModelCallEnd(event) {
1175
1212
  const state = this.getCallState(event.callId);
1176
1213
  if (!state?.inferenceSpan) return;
1214
+ this.recordInferenceDuration(state, {
1215
+ responseTimeMs: event.performance.responseTimeMs,
1216
+ provider: event.provider,
1217
+ responseModelId: event.modelId,
1218
+ errorType: event.finishReason === "error" ? "_OTHER" : void 0
1219
+ });
1177
1220
  if (event.finishReason === "error") state.inferenceSpan.setStatus({ code: SpanStatusCode.ERROR });
1178
1221
  const { telemetry } = state;
1179
1222
  const providerName = mapProviderName(event.provider);
@@ -1296,6 +1339,7 @@ var OpenTelemetry = class {
1296
1339
  onStepEnd(event) {
1297
1340
  const state = this.getCallState(event.callId);
1298
1341
  if (!state?.stepSpan) return;
1342
+ this.recordInferenceDuration(state, { errorType: event.finishReason === "error" ? "_OTHER" : void 0 });
1299
1343
  if (event.finishReason === "error") state.stepSpan.setStatus({ code: SpanStatusCode.ERROR });
1300
1344
  const { telemetry } = state;
1301
1345
  state.stepSpan.setAttributes(selectSupplementalAttributes(telemetry, this.supplementalAttributes, {
@@ -1313,6 +1357,7 @@ var OpenTelemetry = class {
1313
1357
  onStepError(event) {
1314
1358
  const state = this.getCallState(event.callId);
1315
1359
  if (!state?.stepSpan) return;
1360
+ this.recordInferenceDuration(state, { errorType: event.error instanceof Error ? event.error.name : "_OTHER" });
1316
1361
  if (state.inferenceSpan) {
1317
1362
  recordErrorOnSpan(state.inferenceSpan, event.error);
1318
1363
  state.inferenceSpan.end();
@@ -1704,6 +1749,7 @@ var OpenTelemetry = class {
1704
1749
  onAbort(event) {
1705
1750
  const state = this.getCallState(event.callId);
1706
1751
  if (!state?.rootSpan) return;
1752
+ this.recordInferenceDuration(state, { errorType: "AbortError" });
1707
1753
  for (const { span: toolSpan } of state.toolSpans.values()) toolSpan.end();
1708
1754
  state.toolSpans.clear();
1709
1755
  if (state.inferenceSpan) {
@@ -1735,6 +1781,7 @@ var OpenTelemetry = class {
1735
1781
  const state = this.getCallState(event.callId);
1736
1782
  if (!state?.rootSpan) return;
1737
1783
  const actualError = event.error ?? error;
1784
+ this.recordInferenceDuration(state, { errorType: actualError instanceof Error ? actualError.name : "_OTHER" });
1738
1785
  for (const { span: toolSpan } of state.toolSpans.values()) {
1739
1786
  recordErrorOnSpan(toolSpan, actualError);
1740
1787
  toolSpan.end();