create-evlog-adapter

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Create evlog Adapter

创建evlog适配器

Add a new built-in adapter to evlog. Every adapter follows the same architecture. This skill walks through all 8 touchpoints. Every single touchpoint is mandatory -- do not skip any.
为evlog添加一个新的内置适配器。所有适配器遵循相同的架构。本指南将带你完成全部8个关键步骤,每一个步骤都是必填项——请勿跳过任何一项

PR Title

PR标题

Recommended format for the pull request title:
feat: add {name} adapter
The exact wording may vary depending on the adapter (e.g.,
feat: add OTLP adapter
,
feat: add Axiom drain adapter
), but it should always follow the
feat:
conventional commit prefix.
拉取请求标题的推荐格式:
feat: add {name} adapter
具体措辞可根据适配器调整(例如
feat: add OTLP adapter
feat: add Axiom drain adapter
),但必须始终遵循
feat:
的约定式提交前缀。

Touchpoints Checklist

关键步骤清单

#FileAction
1
packages/evlog/src/adapters/{name}.ts
Create adapter source
2
packages/evlog/tsdown.config.ts
Add build entry
3
packages/evlog/package.json
Add
exports
+
typesVersions
entries
4
packages/evlog/test/adapters/{name}.test.ts
Create tests
5
apps/docs/content/3.adapters/{n}.{name}.md
Create adapter doc page (before
custom.md
)
6
apps/docs/content/3.adapters/1.overview.md
Add adapter to overview (links, card, env vars)
7
AGENTS.md
Add adapter to the "Built-in Adapters" table
8Renumber
custom.md
Ensure
custom.md
stays last after the new adapter
Important: Do NOT consider the task complete until all 8 touchpoints have been addressed.
序号文件操作
1
packages/evlog/src/adapters/{name}.ts
创建适配器源代码
2
packages/evlog/tsdown.config.ts
添加构建入口
3
packages/evlog/package.json
添加
exports
+
typesVersions
配置项
4
packages/evlog/test/adapters/{name}.test.ts
创建测试用例
5
apps/docs/content/3.adapters/{n}.{name}.md
创建适配器文档页面(放在
custom.md
之前)
6
apps/docs/content/3.adapters/1.overview.md
在概览中添加适配器(链接、卡片、环境变量)
7
AGENTS.md
在“内置适配器”表格中添加该适配器
8重命名
custom.md
确保添加新适配器后
custom.md
仍处于最后位置
重要提示:只有完成全部8个步骤,任务才算完成。

Naming Conventions

命名规范

Use these placeholders consistently:
PlaceholderExample (Datadog)Usage
{name}
datadog
File names, import paths, env var suffix
{Name}
Datadog
PascalCase in function/interface names
{NAME}
DATADOG
SCREAMING_CASE in env var prefixes
请统一使用以下占位符:
占位符示例(Datadog)用途
{name}
datadog
文件名、导入路径、环境变量后缀
{Name}
Datadog
函数/接口名称使用大驼峰命名
{NAME}
DATADOG
环境变量前缀使用全大写加下划线命名

Step 1: Adapter Source

步骤1:适配器源代码

Create
packages/evlog/src/adapters/{name}.ts
.
Read references/adapter-template.md for the full annotated template.
Key architecture rules:
  1. Config interface -- service-specific fields (API key, endpoint, etc.) plus optional
    timeout?: number
  2. getRuntimeConfig()
    -- import from
    ./_utils
    (shared helper, do NOT redefine locally)
  3. Config priority (highest to lowest):
    • Overrides passed to
      create{Name}Drain()
    • runtimeConfig.evlog.{name}
    • runtimeConfig.{name}
    • Environment variables:
      NUXT_{NAME}_*
      then
      {NAME}_*
  4. Factory function --
    create{Name}Drain(overrides?: Partial<Config>)
    returns
    (ctx: DrainContext) => Promise<void>
  5. Exported send functions --
    sendTo{Name}(event, config)
    and
    sendBatchTo{Name}(events, config)
    for direct use and testability
  6. Error handling -- try/catch with
    console.error('[evlog/{name}] ...')
    , never throw from the drain
  7. Timeout --
    AbortController
    with 5000ms default, configurable via
    config.timeout
  8. Event transformation -- if the service needs a specific format, export a
    to{Name}Event()
    converter
创建
packages/evlog/src/adapters/{name}.ts
文件。
可参考references/adapter-template.md获取完整的带注释模板。
核心架构规则:
  1. 配置接口 —— 包含服务特定字段(API密钥、端点等)以及可选的
    timeout?: number
  2. getRuntimeConfig()
    —— 从
    ./_utils
    导入(共享工具函数,请勿在本地重新定义)
  3. 配置优先级(从高到低):
    • 传递给
      create{Name}Drain()
      的覆盖配置
    • runtimeConfig.evlog.{name}
    • runtimeConfig.{name}
    • 环境变量:先
      NUXT_{NAME}_*
      {NAME}_*
  4. 工厂函数 ——
    create{Name}Drain(overrides?: Partial<Config>)
    返回
    (ctx: DrainContext) => Promise<void>
  5. 导出的发送函数 ——
    sendTo{Name}(event, config)
    sendBatchTo{Name}(events, config)
    ,用于直接调用和测试
  6. 错误处理 —— 使用try/catch包裹,并通过
    console.error('[evlog/{name}] ...')
    输出错误,切勿从输出函数中抛出异常
  7. 超时设置 —— 默认5000ms,可通过
    config.timeout
    配置,使用
    AbortController
    实现
  8. 事件转换 —— 如果目标服务需要特定格式,需导出
    to{Name}Event()
    转换函数

Step 2: Build Config

步骤2:构建配置

Add a build entry in
packages/evlog/tsdown.config.ts
alongside the existing adapters:
typescript
'adapters/{name}': 'src/adapters/{name}.ts',
Place it after the last adapter entry (currently
sentry
at line 22).
packages/evlog/tsdown.config.ts
中,在现有适配器旁边添加一个构建入口:
typescript
'adapters/{name}': 'src/adapters/{name}.ts',
将其放在最后一个适配器入口之后(当前最后一个是
sentry
,位于第22行)。

Step 3: Package Exports

步骤3:包导出配置

In
packages/evlog/package.json
, add two entries:
In
exports
(after the last adapter, currently
./posthog
):
json
"./{name}": {
  "types": "./dist/adapters/{name}.d.mts",
  "import": "./dist/adapters/{name}.mjs"
}
In
typesVersions["*"]
(after the last adapter):
json
"{name}": [
  "./dist/adapters/{name}.d.mts"
]
packages/evlog/package.json
中添加两项配置:
exports
(放在最后一个适配器之后,当前最后一个是
./posthog
):
json
"./{name}": {
  "types": "./dist/adapters/{name}.d.mts",
  "import": "./dist/adapters/{name}.mjs"
}
typesVersions["*"]
(放在最后一个适配器之后):
json
"{name}": [
  "./dist/adapters/{name}.d.mts"
]

Step 4: Tests

步骤4:测试用例

Create
packages/evlog/test/adapters/{name}.test.ts
.
Read references/test-template.md for the full annotated template.
Required test categories:
  1. URL construction (default + custom endpoint)
  2. Headers (auth, content-type, service-specific)
  3. Request body format (JSON structure matches service API)
  4. Error handling (non-OK responses throw with status)
  5. Batch operations (
    sendBatchTo{Name}
    )
  6. Timeout handling (default 5000ms + custom)
创建
packages/evlog/test/adapters/{name}.test.ts
文件。
可参考references/test-template.md获取完整的带注释模板。
必需的测试类别:
  1. URL构造(默认端点+自定义端点)
  2. 请求头(认证、内容类型、服务特定头)
  3. 请求体格式(JSON结构匹配服务API)
  4. 错误处理(非成功响应时抛出状态错误)
  5. 批量操作(
    sendBatchTo{Name}
  6. 超时处理(默认5000ms+自定义超时)

Step 5: Adapter Documentation Page

步骤5:适配器文档页面

Create
apps/docs/content/3.adapters/{n}.{name}.md
where
{n}
is the next number before
custom.md
(custom should always be last).
Use this frontmatter structure:
yaml
---
title: "{Name} Adapter"
description: "Send logs to {Name} for [value prop]. Zero-config setup with environment variables."
navigation:
  title: "{Name}"
  icon: i-simple-icons-{name}  # or i-lucide-* for generic
links:
  - label: "{Name} Dashboard"
    icon: i-lucide-external-link
    to: https://{service-url}
    target: _blank
    color: neutral
    variant: subtle
  - label: "OTLP Adapter"
    icon: i-simple-icons-opentelemetry
    to: /adapters/otlp
    color: neutral
    variant: subtle
---
Sections to include:
  1. Intro paragraph -- what the service is and what the adapter does
  2. Installation -- import path
    evlog/{name}
  3. Quick Setup -- Nitro plugin with
    create{Name}Drain()
  4. Configuration -- table of env vars and config options
  5. Configuration Priority -- overrides > runtimeConfig > env vars
  6. Advanced -- custom options, event transformation details
  7. Querying/Using -- how to find evlog events in the target service
  8. Troubleshooting -- common errors (missing config, auth failures)
  9. Direct API Usage --
    sendTo{Name}()
    and
    sendBatchTo{Name}()
    examples
  10. Next Steps -- links to other adapters and best practices
Use the existing Axiom adapter page (
apps/docs/content/3.adapters/2.axiom.md
) as a reference for tone, structure, and depth.
创建
apps/docs/content/3.adapters/{n}.{name}.md
,其中
{n}
custom.md
之前的下一个序号(custom必须始终处于最后位置)。
使用以下前置元数据结构:
yaml
---
title: "{Name} 适配器"
description: "将日志发送至{Name}以[实现价值]。支持通过环境变量实现零配置启动。"
navigation:
  title: "{Name}"
  icon: i-simple-icons-{name}  # 通用图标可使用i-lucide-*
links:
  - label: "{Name} 控制台"
    icon: i-lucide-external-link
    to: https://{service-url}
    target: _blank
    color: neutral
    variant: subtle
  - label: "OTLP 适配器"
    icon: i-simple-icons-opentelemetry
    to: /adapters/otlp
    color: neutral
    variant: subtle
---
需包含的章节:
  1. 介绍段落 —— 说明目标服务是什么,以及该适配器的作用
  2. 安装 —— 导入路径
    evlog/{name}
  3. 快速开始 —— 使用
    create{Name}Drain()
    的Nitro插件示例
  4. 配置 —— 环境变量和配置选项表格
  5. 配置优先级 —— 覆盖配置 > runtimeConfig > 环境变量
  6. 进阶用法 —— 自定义选项、事件转换细节
  7. 查询与使用 —— 如何在目标服务中查找evlog事件
  8. 故障排查 —— 常见错误(缺少配置、认证失败等)
  9. 直接API调用 ——
    sendTo{Name}()
    sendBatchTo{Name}()
    的使用示例
  10. 下一步 —— 指向其他适配器和最佳实践的链接
可参考现有的Axiom适配器页面(
apps/docs/content/3.adapters/2.axiom.md
)的语气、结构和内容深度。

Step 6: Update Adapters Overview Page

步骤6:更新适配器概览页面

Edit
apps/docs/content/3.adapters/1.overview.md
to add the new adapter in three places:
编辑
apps/docs/content/3.adapters/1.overview.md
,在三个位置添加新适配器:

6a. Frontmatter
links
array

6a. 前置元数据
links
数组

Add a link entry alongside the existing adapters:
yaml
- label: "{Name}"
  icon: i-simple-icons-{name}
  to: /adapters/{name}
  color: neutral
  variant: subtle
在现有适配器旁边添加一个链接项:
yaml
- label: "{Name}"
  icon: i-simple-icons-{name}
  to: /adapters/{name}
  color: neutral
  variant: subtle

6b.
::card-group
section

6b.
::card-group
章节

Add a card block for the new adapter (before the Custom card):
markdown
  :::card
  ---
  icon: i-simple-icons-{name}
  title: {Name}
  to: /adapters/{name}
  ---
  [Short description of what the adapter does.]
  :::
为新适配器添加一个卡片块(放在Custom卡片之前):
markdown
  :::card
  ---
  icon: i-simple-icons-{name}
  title: {Name}
  to: /adapters/{name}
  ---
  [适配器功能的简短描述]
  :::

6c. Zero-Config Setup
.env
example

6c. 零配置启动
.env
示例

Add the adapter's env vars in the
.env
code block. The variable names depend on the service (e.g.,
NUXT_AXIOM_TOKEN
,
NUXT_OTLP_ENDPOINT
,
NUXT_POSTHOG_API_KEY
):
bash
undefined
.env
代码块中添加该适配器的环境变量。变量名称取决于服务(例如
NUXT_AXIOM_TOKEN
NUXT_OTLP_ENDPOINT
NUXT_POSTHOG_API_KEY
):
bash
undefined

{Name}

{Name}

NUXT_{NAME}_<RELEVANT_VAR>=xxx
undefined
NUXT_{NAME}_<相关变量>=xxx
undefined

Step 7: Update AGENTS.md

步骤7:更新AGENTS.md

Add the new adapter to the "Built-in Adapters" table in the root
AGENTS.md
file, in the "Log Draining & Adapters" section:
markdown
| {Name} | `evlog/{name}` | Send logs to {Name} for [description] |
Also add a usage example block (following the pattern of existing adapters in AGENTS.md):
markdown
**Using {Name} Adapter:**

\`\`\`typescript
// server/plugins/evlog-drain.ts
import { create{Name}Drain } from 'evlog/{name}'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', create{Name}Drain())
})
\`\`\`

Set the required environment variables (e.g., \`NUXT_{NAME}_TOKEN\`, \`NUXT_{NAME}_ENDPOINT\`, etc. -- depends on the service).
在根目录的
AGENTS.md
文件的**“内置适配器”**表格中(位于“日志输出与适配器”章节)添加新适配器:
markdown
| {Name} | `evlog/{name}` | 将日志发送至{Name}以[描述用途] |
同时添加一个使用示例块(遵循AGENTS.md中现有适配器的格式):
markdown
**使用{Name}适配器:**

\`\`\`typescript
// server/plugins/evlog-drain.ts
import { create{Name}Drain } from 'evlog/{name}'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', create{Name}Drain())
})
\`\`\`

设置所需的环境变量(例如`NUXT_{NAME}_TOKEN``NUXT_{NAME}_ENDPOINT`等,具体取决于服务)。

Step 8: Renumber
custom.md

步骤8:重命名
custom.md

If the new adapter's number conflicts with
custom.md
, renumber
custom.md
to be the last entry. For example, if the new adapter is
5.{name}.md
, rename
5.custom.md
to
6.custom.md
.
如果新适配器的序号与
custom.md
冲突,请将
custom.md
重命名为最后一个序号。例如,如果新适配器是
5.{name}.md
,则将
5.custom.md
重命名为
6.custom.md

Verification

验证

After completing all steps, run:
bash
cd packages/evlog
bun run build    # Verify build succeeds with new entry
bun run test     # Verify tests pass
完成所有步骤后,运行以下命令:
bash
cd packages/evlog
bun run build    # 验证构建是否成功包含新入口
bun run test     # 验证测试是否通过