Skip to content

Commit 333e8b9

Browse files
petyosiclaude
andauthored
docs: update Vercel AI SDK v7 telemetry setup (#169)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8fd307f commit 333e8b9

1 file changed

Lines changed: 69 additions & 21 deletions

File tree

docs/frameworks/vercel-ai.md

Lines changed: 69 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ description: Capture Vercel AI SDK OpenTelemetry spans in Logfire from Node.js a
77

88
The Vercel AI SDK can emit OpenTelemetry spans for model calls, tools, token usage, and streaming operations. Logfire can receive those spans through either `@pydantic/logfire-node` in Node.js scripts or `@vercel/otel` in Next.js applications.
99

10-
## Node.js Scripts
10+
Since **AI SDK v7**, the recommended telemetry path is the [`@ai-sdk/otel`](https://ai-sdk.dev/docs/ai-sdk-core/telemetry) package, which emits spans that follow the OpenTelemetry GenAI semantic conventions (`gen_ai.*`). **AI SDK v6 and earlier** used the per-call `experimental_telemetry` option and the legacy `ai.*` attribute shape. Logfire recognizes both, so existing instrumentation keeps working — the sections below cover each path.
11+
12+
## Node.js Scripts (AI SDK v7)
1113

1214
```bash
13-
npm install @pydantic/logfire-node ai @ai-sdk/openai
15+
npm install @pydantic/logfire-node ai @ai-sdk/otel @ai-sdk/openai
1416
```
1517

1618
Replace `@ai-sdk/openai` with the provider package you use, such as `@ai-sdk/anthropic` or `@ai-sdk/google`.
@@ -25,33 +27,41 @@ logfire.configure({
2527
})
2628
```
2729

28-
Enable telemetry on AI SDK calls:
30+
Register the `@ai-sdk/otel` integration once at startup. After that, every AI SDK call emits telemetry — you do not set `experimental_telemetry` per call:
2931

3032
```ts
3133
import './instrumentation.ts'
34+
import { OpenTelemetry } from '@ai-sdk/otel'
3235
import { openai } from '@ai-sdk/openai'
33-
import { generateText } from 'ai'
36+
import { generateText, registerTelemetry } from 'ai'
37+
38+
// Register once for the whole process.
39+
registerTelemetry(new OpenTelemetry())
3440

3541
const result = await generateText({
3642
model: openai('gpt-4.1-mini'),
3743
prompt: 'Write a short haiku about traces.',
38-
experimental_telemetry: { isEnabled: true },
3944
})
4045

4146
console.log(result.text)
4247
```
4348

49+
`@ai-sdk/otel` exports two integrations:
50+
51+
- `OpenTelemetry` — emits GenAI semantic-convention spans (`gen_ai.*`). Recommended, and what Logfire renders and prices best.
52+
- `LegacyOpenTelemetry` — emits the older AI SDK (`ai.*`) span shape for tools that have not migrated.
53+
4454
## Next.js
4555

46-
In Next.js, configure `@vercel/otel` as shown in [Next.js](nextjs.md), then enable the same `experimental_telemetry` option on AI SDK calls. The `instrumentation.ts` file must live in the project root, or in `src` if your Next.js app uses `src`.
56+
In Next.js, configure `@vercel/otel` as shown in [Next.js](nextjs.md), then register `@ai-sdk/otel` in the same `instrumentation.ts`. The `instrumentation.ts` file must live in the project root, or in `src` if your Next.js app uses `src`.
4757

4858
```bash
49-
npm install @vercel/otel @opentelemetry/api ai @ai-sdk/openai
59+
npm install @vercel/otel @opentelemetry/api ai @ai-sdk/otel @ai-sdk/openai
5060
```
5161

52-
## Enabling Telemetry
62+
## Legacy Telemetry (AI SDK v6 and earlier)
5363

54-
The Vercel AI SDK emits OpenTelemetry spans when `experimental_telemetry.isEnabled` is set:
64+
Before v7, the Vercel AI SDK emitted spans only when `experimental_telemetry.isEnabled` was set on each call:
5565

5666
```ts
5767
const result = await generateText({
@@ -61,22 +71,27 @@ const result = await generateText({
6171
})
6272
```
6373

64-
This works with the AI SDK core functions that emit telemetry, including:
74+
This still works and covers the AI SDK core functions that emit telemetry, including:
6575

6676
- `generateText` and `streamText`
6777
- `generateObject` and `streamObject`
6878
- `embed` and `embedMany`
6979

80+
These calls produce the legacy `ai.*` attribute shape (for example `ai.model.provider`, `ai.response.model`, `ai.usage.promptTokens`). Logfire maps both the legacy `ai.*` attributes and the v7 `gen_ai.*` attributes, so spans from either version are recognized as LLM spans.
81+
7082
## Example: Text Generation With Tools
7183

7284
```ts
85+
import './instrumentation.ts'
86+
import { OpenTelemetry } from '@ai-sdk/otel'
7387
import { openai } from '@ai-sdk/openai'
74-
import { generateText, tool } from 'ai'
88+
import { generateText, registerTelemetry, tool } from 'ai'
7589
import { z } from 'zod'
7690

91+
registerTelemetry(new OpenTelemetry())
92+
7793
const result = await generateText({
7894
model: openai('gpt-4.1-mini'),
79-
experimental_telemetry: { isEnabled: true },
8095
tools: {
8196
weather: tool({
8297
description: 'Get the weather in a location',
@@ -99,20 +114,55 @@ For Node.js scripts, import your Logfire instrumentation file before importing o
99114

100115
## What You Will See
101116

102-
When telemetry is enabled, Logfire captures a trace for each AI operation. Depending on the AI SDK provider and call type, traces can include:
117+
When telemetry is enabled, Logfire captures a trace for each AI operation. With `@ai-sdk/otel` (v7), **span names include the model name**, so a single `generateText` call with a tool produces spans such as:
103118

104-
- parent spans such as `ai.generateText`
105-
- provider call spans for the model request
106-
- tool call spans
107-
- model and provider details
119+
- `invoke_agent gpt-4.1-mini` — the root agent span
120+
- `chat gpt-4.1-mini` — the provider/model call
121+
- `execute_tool weather` — a tool call
122+
123+
Depending on the AI SDK provider and call type, traces can also include:
124+
125+
- model and provider details (`gen_ai.provider.name`, `gen_ai.request.model` / `gen_ai.response.model`)
108126
- input and output token usage
109127
- timing information
110128
- tool call arguments and results
111-
- prompts and responses when the AI SDK emits them
129+
- prompts and responses (`gen_ai.input.messages` / `gen_ai.output.messages`) when the AI SDK emits them
130+
131+
Prompts and responses may contain sensitive data. To emit telemetry without recording inputs or outputs for a v7 call, set both options to `false`:
132+
133+
```ts
134+
await generateText({
135+
model,
136+
prompt,
137+
telemetry: {
138+
recordInputs: false,
139+
recordOutputs: false,
140+
},
141+
})
142+
```
143+
144+
Set `telemetry.isEnabled` to `false` to disable telemetry entirely for an individual call.
112145

113146
## Metadata
114147

115-
Use `functionId` and `metadata` to make traces easier to query:
148+
Use `functionId` and `metadata` to make traces easier to query. In v7, pass them through the per-call `telemetry` option:
149+
150+
```ts
151+
await generateText({
152+
model,
153+
prompt,
154+
telemetry: {
155+
functionId: 'support-reply',
156+
metadata: {
157+
tenant: 'acme',
158+
},
159+
},
160+
})
161+
```
162+
163+
`functionId` identifies the agent or use case behind a call. Logfire uses it as the agent identity when grouping runs (for example on the AI Engineering agent pages), rather than it only appearing in span names — in v7 the span name carries the model, not the `functionId`. `metadata` attaches custom key-value pairs to the emitted telemetry spans.
164+
165+
For AI SDK v6 and earlier, pass the same fields inside `experimental_telemetry`:
116166

117167
```ts
118168
await generateText({
@@ -127,5 +177,3 @@ await generateText({
127177
},
128178
})
129179
```
130-
131-
`functionId` appears in span names and helps distinguish use cases. `metadata` attaches custom key-value pairs to the emitted telemetry spans.

0 commit comments

Comments
 (0)