---
title: "更深入的遥测"
description: "使用 createEvlogIntegration 添加工具执行耗时和总墙钟时间。可与 supermemory 或 guardrails 等其他中间件组合使用。"
canonical_url: "https://evlog.zhcndoc.com/use-cases/ai-sdk/telemetry"
---
# 更深入的遥测

> 使用 createEvlogIntegration 添加工具执行耗时和总墙钟时间。可与 supermemory 或 guardrails 等其他中间件组合使用。

`createAILogger` 会记录 token、模型信息和流式指标。若需要更深入的可观测性（按工具统计执行耗时、成功／失败跟踪以及生成的总墙钟时间），请在此基础上添加 `createEvlogIntegration()`。它实现了 AI SDK 遥测接口（v6 `TelemetryIntegration`、v7 `Telemetry`），并能捕获仅凭数据中间件无法看到的数据。

在 AI SDK v7 中，该集成还会通过 `onEmbedEnd` 自动捕获嵌入，通过 `onAbort` 记录流中止，并通过 `onError` 提供无法恢复的错误。

## 与中间件组合使用（推荐）

当传入 `AILogger` 时，该集成会共享其累加器。两条路径都会写入同一个 `ai.*` 字段：

<framework-tabs>

```typescript [Nuxt]server/api/agent.post.ts
import { useLogger } from 'evlog'
import { generateText } from 'ai'
import { createAILogger, createEvlogIntegration } from 'evlog/ai'

export default defineEventHandler(async (event) => {
  const log = useLogger(event)

  const ai = createAILogger(log)

  const result = await generateText({
    model: ai.wrap('anthropic/claude-sonnet-4.6'),
    tools: { getWeather, searchDB },
    telemetry: {
      integrations: [createEvlogIntegration(ai)],
    },
  })

  return { text: result.text }
})
```

```typescript [Nitro]routes/api/agent.post.ts
import { defineHandler } from 'nitro/h3'
import { useLogger } from 'evlog/nitro/v3'
import { generateText } from 'ai'
import { createAILogger, createEvlogIntegration } from 'evlog/ai'

export default defineHandler(async (event) => {
  const log = useLogger(event)

  const ai = createAILogger(log)

  const result = await generateText({
    model: ai.wrap('anthropic/claude-sonnet-4.6'),
    tools: { getWeather, searchDB },
    telemetry: {
      integrations: [createEvlogIntegration(ai)],
    },
  })

  return { text: result.text }
})
```

```typescript [Next.js]app/api/agent/route.ts
import { withEvlog, useLogger } from '@/lib/evlog'
import { generateText } from 'ai'
import { createAILogger, createEvlogIntegration } from 'evlog/ai'

export const POST = withEvlog(async () => {
  const log = useLogger()

  const ai = createAILogger(log)

  const result = await generateText({
    model: ai.wrap('anthropic/claude-sonnet-4.6'),
    tools: { getWeather, searchDB },
    telemetry: {
      integrations: [createEvlogIntegration(ai)],
    },
  })

  return Response.json({ text: result.text })
})
```

```typescript [Hono]src/index.ts
import { generateText } from 'ai'
import { createAILogger, createEvlogIntegration } from 'evlog/ai'

app.post('/api/agent', async (c) => {
  const log = c.get('log')

  const ai = createAILogger(log)

  const result = await generateText({
    model: ai.wrap('anthropic/claude-sonnet-4.6'),
    tools: { getWeather, searchDB },
    telemetry: {
      integrations: [createEvlogIntegration(ai)],
    },
  })

  return c.json({ text: result.text })
})
```

```typescript [Express]src/index.ts
import { generateText } from 'ai'
import { createAILogger, createEvlogIntegration } from 'evlog/ai'

app.post('/api/agent', async (req, res) => {
  const log = req.log

  const ai = createAILogger(log)

  const result = await generateText({
    model: ai.wrap('anthropic/claude-sonnet-4.6'),
    tools: { getWeather, searchDB },
    telemetry: {
      integrations: [createEvlogIntegration(ai)],
    },
  })

  return res.json({ text: result.text })
})
```

</framework-tabs>

你的宽事件现在包含了按工具统计的耗时：

```json [Wide Event]
{
  "ai": {
    "calls": 2,
    "steps": 2,
    "model": "claude-sonnet-4.6",
    "provider": "anthropic",
    "inputTokens": 3500,
    "outputTokens": 800,
    "totalTokens": 4300,
    "toolCalls": ["getWeather", "searchDB"],
    "tools": [
      { "name": "getWeather", "durationMs": 150, "success": true },
      { "name": "searchDB", "durationMs": 45, "success": true }
    ],
    "totalDurationMs": 2340,
    "msToFirstChunk": 180,
    "msToFinish": 2100,
    "tokensPerSecond": 380
  }
}
```

## 独立使用（不带中间件）

如果你的模型已经被包装过了（例如被另一个中间件包装），请直接传入请求日志器：

```typescript [server/api/chat.post.ts]
import { createEvlogIntegration } from 'evlog/ai'

const integration = createEvlogIntegration(log)

const result = await generateText({
  model: somePreWrappedModel,
  telemetry: {
    integrations: [integration],
  },
})
```

## 宽事件中会记录的内容

<table>
<thead>
  <tr>
    <th>
      数据
    </th>
    
    <th>
      来源
    </th>
    
    <th>
      描述
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        ai.tools[]
      </code>
    </td>
    
    <td>
      <code>
        onToolExecutionEnd
      </code>
      
       (v7) / <code>
        onToolCallFinish
      </code>
      
       (v6)
    </td>
    
    <td>
      每个工具的 <code>
        name
      </code>
      
      、<code>
        durationMs
      </code>
      
      、<code>
        success
      </code>
      
      ，以及失败时的 <code>
        error
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ai.totalDurationMs
      </code>
    </td>
    
    <td>
      <code>
        onStart
      </code>
      
       → <code>
        onEnd
      </code>
      
       (v7) / <code>
        onFinish
      </code>
      
       (v6)
    </td>
    
    <td>
      从生成开始到完成的总墙钟时间
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ai.embedding
      </code>
    </td>
    
    <td>
      <code>
        onEmbedEnd
      </code>
      
       (v7)
    </td>
    
    <td>
      启用遥测后，自动从 <code>
        embed()
      </code>
      
       / <code>
        embedMany()
      </code>
      
       中捕获
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ai.finishReason: 'abort'
      </code>
    </td>
    
    <td>
      <code>
        onAbort
      </code>
      
       (v7)
    </td>
    
    <td>
      流式生成中止时设置
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ai.error
      </code>
    </td>
    
    <td>
      <code>
        onAbort
      </code>
      
       / <code>
        onError
      </code>
      
       (v7)
    </td>
    
    <td>
      中止原因或无法恢复的生成错误
    </td>
  </tr>
</tbody>
</table>

中间件会捕获 token、模型信息和流式指标。该集成会捕获工具执行耗时。两者结合，能为你提供完整的 AI 可观测性。

## 与其他部分组合

`ai.wrap()` 可与已被其他工具包装的模型配合使用。如果你使用 supermemory、guardrails 中间件或其他任何模型包装器，请将包装后的模型传入 `ai.wrap()`：

```typescript [server/api/chat.post.ts]
import { createAILogger } from 'evlog/ai'
import { withSupermemory } from '@supermemory/tools/ai-sdk'
import { createGateway } from 'ai'

const gateway = createGateway({ ... })
const ai = createAILogger(log)
const base = gateway('anthropic/claude-sonnet-4.6')
const model = ai.wrap(withSupermemory(base, 'your-org-id', { mode: 'full' }))
```

对于显式的中间件组合，请使用 `createAIMiddleware` 获取原始中间件，然后通过 `wrapLanguageModel` 自行组合：

```typescript [server/api/chat.post.ts]
import { createAIMiddleware } from 'evlog/ai'
import { wrapLanguageModel } from 'ai'

const model = wrapLanguageModel({
  model: base,
  middleware: [createAIMiddleware(log, { toolInputs: true }), otherMiddleware],
})
```

`createAIMiddleware` 返回的中间件与 `createAILogger` 内部使用的是同一个。区别在于：`createAIMiddleware` 不包含 `captureEmbed`（嵌入模型不使用中间件）。当你需要完整 API 时使用 `createAILogger`；当你需要显式的中间件顺序时使用 `createAIMiddleware`。

---

- [概览](https://evlog.zhcndoc.com/use-cases/ai-sdk/overview)
- [使用模式](https://evlog.zhcndoc.com/use-cases/ai-sdk/usage)


## Sitemap

See the full [sitemap](https://evlog.zhcndoc.com/sitemap.md) for all pages.
