| 1 | --- |
| 2 | name: create-evlog-adapter |
| 3 | description: Create a new built-in evlog adapter to send wide events to an external observability platform. Use when adding a new drain adapter (e.g., for Datadog, Sentry, Loki, Elasticsearch, etc.) to the evlog package. Covers source code, build config, package exports, tests, and all documentation. |
| 4 | --- |
| 5 | |
| 6 | # Create evlog Adapter |
| 7 | |
| 8 | 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. |
| 9 | |
| 10 | ## PR Title |
| 11 | |
| 12 | Recommended format for the pull request title: |
| 13 | |
| 14 | ``` |
| 15 | feat: add {name} adapter |
| 16 | ``` |
| 17 | |
| 18 | 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 |
| 19 | |
| 20 | ## Touchpoints Checklist |
| 21 | |
| 22 | | # | File | Action | |
| 23 | |---|------|--------| |
| 24 | | 1 | `packages/evlog/src/adapters/{name}.ts` | Create adapter source |
| 25 | | 2 | `packages/evlog/tsdown.config.ts` | Add build entry |
| 26 | | 3 | `packages/evlog/package.json` | Add |
| 27 | | 4 | `packages/evlog/test/adapters/{name}.test.ts` | Create tests |
| 28 | | 5 | `apps/docs/content/3.adapters/{n}.{name}.md` | Create adapter doc page (before |
| 29 | | 6 | `apps/docs/content/3.adapters/1.overview.md` | Add adapter to overview (links, card, env vars) |
| 30 | | 7 | `AGENTS.md` | Add adapter to the "Built-in Adapters" table |
| 31 | | 8 | Renumber `custom.md` | Ensure |
| 32 | |
| 33 | **Important**: Do NOT consider the task complete until all 8 touchpoints have been addressed. |
| 34 | |
| 35 | ## Naming Conventions |
| 36 | |
| 37 | Use these placeholders consistently: |
| 38 | |
| 39 | | Placeholder | Example (Datadog) | Usage | |
| 40 | |-------------|-------------------|-------| |
| 41 | | `{name}` | `datadog |
| 42 | | `{Name}` | `Datadog |
| 43 | | `{NAME}` | `DATADOG |
| 44 | |
| 45 | ## Step 1: Adapter Source |
| 46 | |
| 47 | Create `packages/evlog/src/adapters/{name}.ts`. |
| 48 | |
| 49 | Read [references/adapter-template.md](references/adapter-template.md |
| 50 | |
| 51 | Key architecture rules: |
| 52 | |
| 53 | 1. **Config interface** -- service-specific fields (API key, endpoint, etc.) plus optional |
| 54 | 2. **`getRuntimeConfig()` |
| 55 | 3. **Config priority** (highest to lowest): |
| 56 | - Overrides passed to `create{Name}Drain()` |
| 57 | - `runtimeConfig.evlog.{name}` |
| 58 | - `runtimeConfig.{name}` |
| 59 | - Environment variables: `NUXT_{NAME}_*` then `{NAME}_*` |
| 60 | 4. **Factory function** -- |
| 61 | 5. **Exported send functions** -- |
| 62 | 6. **Error handling** -- try/catch with |
| 63 | 7. **Timeout** -- |
| 64 | 8. **Event transformation** -- if the service needs a specific format, export a |
| 65 | |
| 66 | ## Step 2: Build Config |
| 67 | |
| 68 | Add a build entry in `packages/evlog/tsdown.config.ts` alongside the existing adapters: |
| 69 | |
| 70 | ```typescript |
| 71 | 'adapters/{name}': 'src/adapters/{name}.ts', |
| 72 | ``` |
| 73 | |
| 74 | Place it after the last adapter entry (currently `sentry` at line 22). |
| 75 | |
| 76 | ## Step 3: Package Exports |
| 77 | |
| 78 | In `packages/evlog/package.json`, add two entries: |
| 79 | |
| 80 | **In `exports |
| 81 | |
| 82 | ```json |
| 83 | "./{name}": { |
| 84 | "types": |
| 85 | "import": |
| 86 | } |
| 87 | ``` |
| 88 | |
| 89 | **In `typesVersions["*"] |
| 90 | |
| 91 | ```json |
| 92 | "{name}": [ |
| 93 | "./dist/adapters/{name}.d.mts" |
| 94 | ] |
| 95 | ``` |
| 96 | |
| 97 | ## Step 4: Tests |
| 98 | |
| 99 | Create `packages/evlog/test/adapters/{name}.test.ts`. |
| 100 | |
| 101 | Read [references/test-template.md](references/test-template.md |
| 102 | |
| 103 | Required test categories: |
| 104 | |
| 105 | 1. URL construction (default + custom endpoint) |
| 106 | 2. Headers (auth, content-type, service-specific) |
| 107 | 3. Request body format (JSON structure matches service API) |
| 108 | 4. Error handling (non-OK responses throw with status) |
| 109 | 5. Batch operations (`sendBatchTo{Name}`) |
| 110 | 6. Timeout handling (default 5000ms + custom) |
| 111 | |
| 112 | ## Step 5: Adapter Documentation Page |
| 113 | |
| 114 | Create `apps/docs/content/3.adapters/{n}.{name}.md` where `{n}` is the next number before ` |
| 115 | |
| 116 | Use the existing Axiom adapter page (`apps/docs/content/3.adapters/2.axiom.md`) as a reference for frontmatter structure, tone, and sections. Key sections: intro, quick setup, configuration (env vars table + priority), advanced usage, querying in the target service, troubleshooting, direct API usage, next steps. |
| 117 | |
| 118 | ## Step 6: Update Adapters Overview Page |
| 119 | |
| 120 | Edit `apps/docs/content/3.adapters/1.overview.md` to add the new adapter in **three |
| 121 | |
| 122 | 1. **Frontmatter `links |
| 123 | 2. **`::card-group` |
| 124 | 3. **Zero-Config Setup `.env |
| 125 | |
| 126 | ## Step 7: Update AGENTS.md |
| 127 | |
| 128 | In the root `AGENTS.md` file, "Log Draining & Adapters" section: |
| 129 | |
| 130 | 1. Add a row to the **"Built-in Adapters"** table |
| 131 | 2. Add a **"Using {Name} Adapter"** usage example block with |
| 132 | |
| 133 | Follow the pattern of existing adapters in the file. |
| 134 | |
| 135 | ## Step 8: Renumber ` |
| 136 | |
| 137 | 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 |
| 138 | |
| 139 | ## Verification |
| 140 | |
| 141 | After completing all steps, run: |
| 142 | |
| 143 | ```bash |
| 144 | cd packages/evlog |
| 145 | bun run build # |
| 146 | bun run test # |
| 147 | ``` |