---
title: "Axiom 适配器"
description: "将广泛事件发送到 Axiom，以进行强大的查询、仪表板和告警。零配置设置，使用环境变量和自动批处理。"
canonical_url: "https://evlog.zhcndoc.com/integrate/adapters/cloud/axiom"
---
# Axiom 适配器

> 将广泛事件发送到 Axiom，以进行强大的查询、仪表板和告警。零配置设置，使用环境变量和自动批处理。

[Axiom](https://axiom.co) 是一个云原生日志平台，它会为事件的每个字段建立索引，因此无需架构即可查询其中任意字段。evlog Axiom 适配器会将你的广泛事件直接发送到 Axiom 数据集。

<prompt :actions="["copy","cursor","claude"]" description="添加 Axiom 排水适配器" icon="i-custom-axiom">

添加 Axiom 排水适配器，将 evlog 广泛事件发送到 Axiom。

1. 识别我正在使用的框架，并遵循其 evlog 集成模式
2. 如果尚未安装，请安装 evlog
3. 从 'evlog/axiom' 导入 createAxiomDrain
4. 将 createAxiomDrain() 接入我框架的 drain 配置
5. 在 .env 中设置 AXIOM_API_KEY 和 AXIOM_DATASET 环境变量
6. 通过触发一个请求并检查 Axiom 数据集进行测试

适配器文档：[https://www.evlog.dev/integrate/adapters/cloud/axiom](https://www.evlog.dev/integrate/adapters/cloud/axiom)
框架设置：[https://www.evlog.dev/integrate/frameworks/overview](https://www.evlog.dev/integrate/frameworks/overview)

</prompt>

## 安装

Axiom 适配器已随 evlog 一起打包提供：

```typescript [src/index.ts]
import { createAxiomDrain } from 'evlog/axiom'
```

## 快速开始

### 1. 获取你的 Axiom 凭证

1. 创建一个 [Axiom 账户](https://app.axiom.co)
2. 创建一个用于日志的数据集
3. 生成一个具有写入权限的 API 令牌

### 2. 设置环境变量

```bash [.env]
AXIOM_API_KEY=xaat-your-token-here
AXIOM_DATASET=your-dataset-name
```

<callout color="info" icon="i-lucide-info">

在 Axiom 的仪表板中，这个凭证称为 **API 令牌**（`xaat-...`）。evlog 将配置字段命名为 `apiKey`，以便在各个适配器之间保持一致。旧的 `token` / `AXIOM_TOKEN` 仍然可用，直到下一个主要版本发布。

</callout>

### 3. 将 drain 接入你的框架

<framework-tabs>

```typescript [Nuxt]server/plugins/evlog-drain.ts
import { createAxiomDrain } from 'evlog/axiom'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createAxiomDrain())
})
```

```typescript [Nitro]server/plugins/evlog-drain.ts
import { definePlugin } from 'nitro'
import { createAxiomDrain } from 'evlog/axiom'

export default definePlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createAxiomDrain())
})
```

```typescript [Next.js]lib/evlog.ts
import { createEvlog } from 'evlog/next'
import { createAxiomDrain } from 'evlog/axiom'

export const { withEvlog, useLogger, log, createError } = createEvlog({
  service: 'my-app',
  drain: createAxiomDrain(),
})
```

```typescript [SvelteKit]src/hooks.server.ts
import { createEvlogHooks } from 'evlog/sveltekit'
import { createAxiomDrain } from 'evlog/axiom'

export const { handle, handleError } = createEvlogHooks({ drain: createAxiomDrain() })
```

```typescript [TanStack Start]server/plugins/evlog-drain.ts
import { definePlugin } from 'nitro'
import { createAxiomDrain } from 'evlog/axiom'

export default definePlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createAxiomDrain())
})
```

```typescript [React Router]app/root.tsx
import { evlog } from 'evlog/react-router'
import { createAxiomDrain } from 'evlog/axiom'

export const middleware: Route.MiddlewareFunction[] = [
  evlog({ drain: createAxiomDrain() }),
]
```

```typescript [Hono]src/index.ts
import { createAxiomDrain } from 'evlog/axiom'

app.use(evlog({ drain: createAxiomDrain() }))
```

```typescript [Express]src/index.ts
import { createAxiomDrain } from 'evlog/axiom'

app.use(evlog({ drain: createAxiomDrain() }))
```

```typescript [Fastify]src/index.ts
import { createAxiomDrain } from 'evlog/axiom'

await app.register(evlog, { drain: createAxiomDrain() })
```

```typescript [Elysia]src/index.ts
import { createAxiomDrain } from 'evlog/axiom'

app.use(evlog({ drain: createAxiomDrain() }))
```

```typescript [NestJS]src/app.module.ts
import { createAxiomDrain } from 'evlog/axiom'

EvlogModule.forRoot({ drain: createAxiomDrain() })
```

```typescript [oRPC]server/orpc.ts
import { withEvlog } from 'evlog/orpc'
import { createAxiomDrain } from 'evlog/axiom'

const handler = withEvlog(new RPCHandler(router), { drain: createAxiomDrain() })
```

```typescript [Cloudflare Workers]src/worker.ts
import { withEvlog } from 'evlog/workers'
import { createAxiomDrain } from 'evlog/axiom'

export default withEvlog(handler, { drain: createAxiomDrain() })
```

```typescript [Standalone]
import { createAxiomDrain } from 'evlog/axiom'

initLogger({ drain: createAxiomDrain() })
```

</framework-tabs>

就是这样！你的日志现在会显示在 Axiom 中。

## 配置

该适配器从多个来源读取配置（优先级从高到低）：

1. **覆盖项** 传递给 `createAxiomDrain()`
2. **运行时配置** 位于 `runtimeConfig.axiom`（仅限 Nuxt/Nitro）
3. **环境变量**（`AXIOM_*`）

### 环境变量

<table>
<thead>
  <tr>
    <th>
      变量
    </th>
    
    <th>
      说明
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        AXIOM_API_KEY
      </code>
    </td>
    
    <td>
      具有写入权限的 Axiom API 令牌
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        AXIOM_DATASET
      </code>
    </td>
    
    <td>
      用于导入日志的数据集名称
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        AXIOM_ORG_ID
      </code>
    </td>
    
    <td>
      组织 ID（个人访问令牌必填）
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        AXIOM_EDGE_URL
      </code>
    </td>
    
    <td>
      用于导入/查询的边缘基础 URL（适用于边缘部署）
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        AXIOM_URL
      </code>
    </td>
    
    <td>
      API 基础 URL（旧版/默认导入端点）
    </td>
  </tr>
</tbody>
</table>

### 运行时配置（仅限 Nuxt）

通过 `nuxt.config.ts` 进行类型安全的配置：

```typescript [nuxt.config.ts]
export default defineNuxtConfig({
  runtimeConfig: {
    axiom: {
      apiKey: '', // 通过 AXIOM_API_KEY 设置
      dataset: '', // 通过 AXIOM_DATASET 设置
    },
  },
})
```

### 覆盖选项

直接传递选项以覆盖任何配置：

<framework-tabs>

```typescript [Nuxt]server/plugins/evlog-drain.ts
import { createAxiomDrain } from 'evlog/axiom'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }))
})
```

```typescript [Nitro]server/plugins/evlog-drain.ts
import { definePlugin } from 'nitro'
import { createAxiomDrain } from 'evlog/axiom'

export default definePlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }))
})
```

```typescript [Next.js]lib/evlog.ts
import { createEvlog } from 'evlog/next'
import { createAxiomDrain } from 'evlog/axiom'

export const { withEvlog, useLogger, log, createError } = createEvlog({
  service: 'my-app',
  drain: createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }),
})
```

```typescript [SvelteKit]src/hooks.server.ts
import { createEvlogHooks } from 'evlog/sveltekit'
import { createAxiomDrain } from 'evlog/axiom'

export const { handle, handleError } = createEvlogHooks({
  drain: createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }),
})
```

```typescript [TanStack Start]server/plugins/evlog-drain.ts
import { definePlugin } from 'nitro'
import { createAxiomDrain } from 'evlog/axiom'

export default definePlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }))
})
```

```typescript [React Router]app/root.tsx
import { evlog } from 'evlog/react-router'
import { createAxiomDrain } from 'evlog/axiom'

export const middleware: Route.MiddlewareFunction[] = [
  evlog({
      drain: createAxiomDrain({
        dataset: 'production-logs',
        timeout: 10000,
      }),
    }),
]
```

```typescript [Hono]src/index.ts
import { evlog } from 'evlog/hono'
import { createAxiomDrain } from 'evlog/axiom'

app.use(evlog({
  drain: createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }),
}))
```

```typescript [Express]src/index.ts
import { evlog } from 'evlog/express'
import { createAxiomDrain } from 'evlog/axiom'

app.use(evlog({
  drain: createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }),
}))
```

```typescript [Fastify]src/index.ts
import { evlog } from 'evlog/fastify'
import { createAxiomDrain } from 'evlog/axiom'

await app.register(evlog, {
  drain: createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }),
})
```

```typescript [Elysia]src/index.ts
import { evlog } from 'evlog/elysia'
import { createAxiomDrain } from 'evlog/axiom'

app.use(evlog({
  drain: createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }),
}))
```

```typescript [NestJS]src/app.module.ts
import { EvlogModule } from 'evlog/nestjs'
import { createAxiomDrain } from 'evlog/axiom'

EvlogModule.forRoot({
  drain: createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }),
})
```

```typescript [oRPC]server/orpc.ts
import { withEvlog } from 'evlog/orpc'
import { createAxiomDrain } from 'evlog/axiom'

const handler = withEvlog(new RPCHandler(router), {
  drain: createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }),
})
```

```typescript [Cloudflare Workers]src/worker.ts
import { withEvlog } from 'evlog/workers'
import { createAxiomDrain } from 'evlog/axiom'

export default withEvlog(handler, {
  drain: createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }),
})
```

```typescript [Standalone]src/index.ts
import { initLogger } from 'evlog'
import { createAxiomDrain } from 'evlog/axiom'

initLogger({
  drain: createAxiomDrain({
    dataset: 'production-logs',
    timeout: 10000,
  }),
})
```

</framework-tabs>

### 完整配置参考

<table>
<thead>
  <tr>
    <th>
      选项
    </th>
    
    <th>
      类型
    </th>
    
    <th>
      默认值
    </th>
    
    <th>
      说明
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        apiKey
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      -
    </td>
    
    <td>
      Axiom API 令牌（必填）
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        token
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      -
    </td>
    
    <td>
      <strong>
        已弃用。
      </strong>
      
       请改用 <code>
        apiKey
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        dataset
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      -
    </td>
    
    <td>
      数据集名称（必填）
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        orgId
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      -
    </td>
    
    <td>
      组织 ID（用于 PAT 令牌）
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        edgeUrl
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      -
    </td>
    
    <td>
      用于导入的边缘 URL。未提供路径时使用 <code>
        /v1/ingest/{dataset}
      </code>
      
      ；自定义路径按原样使用（会去除末尾斜杠）。不能与 <code>
        baseUrl
      </code>
      
       同时使用
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        baseUrl
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        https://api.axiom.co
      </code>
    </td>
    
    <td>
      API 基础 URL（<code>
        /v1/datasets/{dataset}/ingest
      </code>
      
      ），不能与 <code>
        edgeUrl
      </code>
      
       同时使用
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        timeout
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        5000
      </code>
    </td>
    
    <td>
      请求超时时间，单位为毫秒
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        retries
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        2
      </code>
    </td>
    
    <td>
      瞬时故障时的重试次数
    </td>
  </tr>
</tbody>
</table>

### 时间戳

Axiom 的事件时间戳字段是 `_time`。适配器会通过 `timestamp-field` 导入参数，将事件自身的 `timestamp` 字段作为时间戳发送，因此即使事件经过批处理或重试，也能保留其原始时间。基于时间的查询和监控应使用 `_time` 进行分桶。

## 在 Axiom 中查询日志

evlog 发送结构化广泛事件，非常适合 Axiom 的 APL 查询语言：

```apl [Axiom APL 查询]
// 查找慢速请求
['your-dataset']
| where durationMs > 1000
| project _time, path, durationMs, status

// 按端点统计错误率
['your-dataset']
| where level == "error"
| summarize count() by path
| order by count_ desc

// 随时间统计请求量
['your-dataset']
| summarize count() by bin(_time, 1h)
| render timechart
```

## 故障排除

### 缺少数据集或 apiKey 错误

```text [Console]
[evlog/axiom] Missing dataset or apiKey. Set AXIOM_API_KEY/AXIOM_DATASET env vars or pass to createAxiomDrain()
```

请确保已设置环境变量并在添加后重新启动服务器。

### 401 未授权

你的令牌可能无效或已过期。在 Axiom 仪表板中生成一个具有 **写入** 权限的新令牌。

### 403 禁止（使用个人访问令牌）

个人访问令牌需要组织 ID：

```bash [.env]
AXIOM_ORG_ID=your-org-id
```

## 直接 API 使用

对于高级用例，你可以使用更低层级的函数：

```typescript [server/utils/axiom.ts]
import { sendToAxiom, sendBatchToAxiom } from 'evlog/axiom'

// 发送单个事件
await sendToAxiom(event, {
  apiKey: 'xaat-xxx',
  dataset: 'logs',
})

// 批量发送多个事件
await sendBatchToAxiom(events, {
  apiKey: 'xaat-xxx',
  dataset: 'logs',
})
```

## 下一步

- [OTLP 适配器](https://evlog.zhcndoc.com/integrate/adapters/hybrid/otlp) - 通过 OpenTelemetry 协议发送日志
- [PostHog 适配器](https://evlog.zhcndoc.com/integrate/adapters/cloud/posthog) - 将日志发送到 PostHog
- [自定义适配器](https://evlog.zhcndoc.com/extend/custom-drains) - 构建您自己的适配器
- [最佳实践](https://evlog.zhcndoc.com/reference/best-practices) - 安全性和生产环境提示。

---

- [Axiom 仪表板](https://app.axiom.co)
- [OTLP 适配器](https://evlog.zhcndoc.com/integrate/adapters/hybrid/otlp)


## Sitemap

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