create-evlog-adapter
npx skills add https://github.com/hugorcd/evlog --skill create-evlog-adapter
Agent 安装分布
Skill 文档
Create evlog Adapter
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.
PR Title
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.
Touchpoints Checklist
| # | File | Action |
|---|---|---|
| 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 |
| 8 | Renumber 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.
Naming Conventions
Use these placeholders consistently:
| Placeholder | Example (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 |
Step 1: Adapter Source
Create packages/evlog/src/adapters/{name}.ts.
Read references/adapter-template.md for the full annotated template.
Key architecture rules:
- Config interface — service-specific fields (API key, endpoint, etc.) plus optional
timeout?: number getRuntimeConfig()— import from./_utils(shared helper, do NOT redefine locally)- Config priority (highest to lowest):
- Overrides passed to
create{Name}Drain() runtimeConfig.evlog.{name}runtimeConfig.{name}- Environment variables:
NUXT_{NAME}_*then{NAME}_*
- Overrides passed to
- Factory function —
create{Name}Drain(overrides?: Partial<Config>)returns(ctx: DrainContext) => Promise<void> - Exported send functions —
sendTo{Name}(event, config)andsendBatchTo{Name}(events, config)for direct use and testability - Error handling — try/catch with
console.error('[evlog/{name}] ...'), never throw from the drain - Timeout —
AbortControllerwith 5000ms default, configurable viaconfig.timeout - Event transformation — if the service needs a specific format, export a
to{Name}Event()converter
Step 2: Build Config
Add a build entry in packages/evlog/tsdown.config.ts alongside the existing adapters:
'adapters/{name}': 'src/adapters/{name}.ts',
Place it after the last adapter entry (currently sentry at line 22).
Step 3: Package Exports
In packages/evlog/package.json, add two entries:
In exports (after the last adapter, currently ./posthog):
"./{name}": {
"types": "./dist/adapters/{name}.d.mts",
"import": "./dist/adapters/{name}.mjs"
}
In typesVersions["*"] (after the last adapter):
"{name}": [
"./dist/adapters/{name}.d.mts"
]
Step 4: Tests
Create packages/evlog/test/adapters/{name}.test.ts.
Read references/test-template.md for the full annotated template.
Required test categories:
- URL construction (default + custom endpoint)
- Headers (auth, content-type, service-specific)
- Request body format (JSON structure matches service API)
- Error handling (non-OK responses throw with status)
- Batch operations (
sendBatchTo{Name}) - Timeout handling (default 5000ms + custom)
Step 5: Adapter Documentation Page
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:
---
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:
- Intro paragraph — what the service is and what the adapter does
- Installation — import path
evlog/{name} - Quick Setup — Nitro plugin with
create{Name}Drain() - Configuration — table of env vars and config options
- Configuration Priority — overrides > runtimeConfig > env vars
- Advanced — custom options, event transformation details
- Querying/Using — how to find evlog events in the target service
- Troubleshooting — common errors (missing config, auth failures)
- Direct API Usage —
sendTo{Name}()andsendBatchTo{Name}()examples - 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.
Step 6: Update Adapters Overview Page
Edit apps/docs/content/3.adapters/1.overview.md to add the new adapter in three places:
6a. Frontmatter links array
Add a link entry alongside the existing adapters:
- label: "{Name}"
icon: i-simple-icons-{name}
to: /adapters/{name}
color: neutral
variant: subtle
6b. ::card-group section
Add a card block for the new adapter (before the Custom card):
:::card
---
icon: i-simple-icons-{name}
title: {Name}
to: /adapters/{name}
---
[Short description of what the adapter does.]
:::
6c. Zero-Config Setup .env example
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):
# {Name}
NUXT_{NAME}_<RELEVANT_VAR>=xxx
Step 7: Update AGENTS.md
Add the new adapter to the “Built-in Adapters” table in the root AGENTS.md file, in the “Log Draining & Adapters” section:
| {Name} | `evlog/{name}` | Send logs to {Name} for [description] |
Also add a usage example block (following the pattern of existing adapters in AGENTS.md):
**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).
Step 8: Renumber 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.
Verification
After completing all steps, run:
cd packages/evlog
bun run build # Verify build succeeds with new entry
bun run test # Verify tests pass