create-evlog-adapter について
evlogに組み込みのdrainアダプターを追加するための、リポジトリ向けSkillです。アダプター構成を示し、実装、テスト、パッケージ公開、ドキュメント、リリースの作業を網羅するチェックリストを提供します。
主な機能
- 01defineHttpDrainによる実装
- 02標準設定の解決
- 03リクエストのエンコードと送信ヘルパー
- 04単体・エンドツーエンドテストの要件
- 05ビルド、公開、ドキュメントの確認項目
活用シーン
- 01新しいログサービス用アダプターの追加
- 02プルリクエスト前の変更確認
- 03パッケージとドキュメント更新の計画
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ evloghq/ evlog --skill create-evlog-adapterインストール後、Claude Code で/create-evlog-adapterを入力して読み込まれたか確認します。
詳細
evlog アダプターの作成
evlog に新しい組み込みアダプターを追加します。すべてのアダプターは同じアーキテクチャに従い、evlog/toolkit の公開ツールキットプリミティブを基盤としているため、コミュニティ製アダプターも組み込みアダプターと同じ構成です。
PR タイトル
feat({name}): add the {Name} drain adapter
最近の例:feat(loki): add the Grafana Loki drain adapter、feat(clickhouse): add the ClickHouse drain adapter。アダプター名を Conventional Commit のスコープとして使用し、そのスコープを登録してください(タッチポイント 11 を参照)。
スコープのタイミングに関する注意:セマンティック PR チェックはスコープ一覧をベースブランチから読み込むため、新しいスコープを追加する PR 自体は検証できません。先行する小規模な PR でスコープを登録する(Loki/ClickHouse のパターン)か、追加する PR のタイトルにスコープを付けず、feat: add the {Name} drain adapter を使用してください。
タッチポイントのチェックリスト
| # | ファイル | 作業 |
|---|---|---|
| 1 | packages/evlog/src/adapters/{name}.ts | アダプターのソースを作成(../shared/drain の defineHttpDrain を基盤にする) |
| 2 | packages/evlog/tsdown.config.ts | ビルドエントリーを追加 |
| 3 | packages/evlog/package.json | exports と typesVersions のエントリーを追加 |
| 4 | packages/evlog/test/adapters/{name}.test.ts | 単体テストを作成(test/helpers/fetch.ts を使用) |
| 5 | packages/evlog/test/e2e/{name}.e2e.ts | 環境変数で実行を制御する E2E テストを作成。セルフホスト可能な場合は Docker サンドボックスを拡張 |
| 6 | packages/evlog/test/toolkit/__snapshots__/api-surface.test.ts.snap | ビルド後にテストを実行すると再生成されます(pnpm run build の後に pnpm test を実行) |
| 7 | apps/docs/content/4.integrate/adapters/{category}/{NN}.{name}.md | 適切なカテゴリにアダプターのドキュメントページを作成 |
| 8 | apps/docs/content/4.integrate/adapters/01.overview.md | 概要にアダプターを追加(frontmatter のリンクとカード) |
| 9 | skills/review-logging-patterns/SKILL.md | Drain Adapters テーブルにアダプターの行を追加し、frontmatter の説明を更新 |
| 10 | .changeset/{name}-adapter.md | アダプターの説明を記載した changeset(minor)を作成 |
| 11 | .github/workflows/semantic-pull-request.yml + .github/pull_request_template.md | 両方のファイルで {name} を PR スコープとして登録 |
| 12 | .agents/skills/create-adapter/references/upstream-alignment.md | アダプターの行を追加:取り込みドキュメントの URL、公式クライアントのリポジトリとパッケージ、リクエストを構築するファイル、クライアントがイシュー、メトリクス、ユーザープロフィールなどのプロバイダーの他の機能にデータを渡すファイル(プロバイダーが送信したデータのみを保存する場合は none)、およびアダプター作成時に参照したクライアントのバージョンを Aligned to に設定 |
重要:12 個すべてのタッチポイントに対応するまで、作業を完了したと見なさないでください。
命名規則
以下のプレースホルダーを一貫して使用してください。
| プレースホルダー | 例(Loki) | 用途 |
|---|---|---|
{name} | loki | ファイル名、インポートパス、環境変数のサフィックス、PR スコープ |
{Name} | Loki | 関数名/インターフェース名の PascalCase |
{NAME} | LOKI | 環境変数プレフィックスの SCREAMING_CASE |
標準のオプション名(以下の名前を正確に使用してください)。
| 概念 | 標準のオプション名 |
|---|---|
| Bearer 形式の API シークレット | apiKey |
| 取り込み API のベース URL | endpoint |
| サービス識別子 | serviceName |
| リクエストのタイムアウト(ms) | timeout |
| 一時的な失敗時の再試行回数 | retries |
サービスで歴史的に別の名前(token、sourceToken など)が使われている場合は、applyDeprecatedAlias を使って非推奨エイリアスとして残してください。パターンについては Axiom と Better Stack を参照してください。
ステップ 1:アダプターのソース:defineHttpDrain を基盤にする
packages/evlog/src/adapters/{name}.ts を作成します。注釈付きの完全なテンプレートについては、references/adapter-template.md を参照してください。loki.ts と clickhouse.ts が最新の参考実装です。
契約は defineHttpDrain<TConfig>({ name, label, resolve, encode }) です。実装するロジックは次の 2 つだけです。
resolve():完全に解決された設定を返すか、スキップする場合はnullを返します。標準的な優先順位(overrides →runtimeConfig.evlog.{name}→runtimeConfig.{name}→ 環境変数)にはresolveAdapterConfigを使用します。Nuxt との互換性を保つため、ConfigField.envではNUXT_{NAME}_*を{NAME}_*より前に列挙し、ユーザー向けメッセージではformatPublicEnvKeysを使って{NAME}_*のみを表示します。encode(events, config):バッチの{ url, headers, body }を返すプライベート関数encode{Name}Request(events, config): HttpDrainRequestです。HTTP 転送、識別ヘッダー、再試行、タイムアウト、エラーログはdefineHttpDrain(httpPost経由)が処理します。
主なルール:
- ファクトリーは 1 つだけにします。
create{Name}Drain(overrides?: Partial<{Name}Config>)を 1 つだけエクスポートします。二重 API のファクトリーは作成しません。サービスに複数の取り込みモード(ログとイベントなど)がある場合は、modeオプションで切り替えられるようにします(PostHog を参照)。 - アダプターに HTTP コードを記述しません。
fetchを直接呼び出してはいけません。サービスでカスタム転送(バイナリーエンベロープ、非 HTTP)が本当に必要な場合は、代わりに../shared/drainのdefineDrainを使用します。fs.tsとmemory.tsを参照してください。 - エンコードの一貫性を保ちます。 単独の
sendTo{Name}/sendBatchTo{Name}ヘルパーでは、同じプライベート関数encode{Name}Request()を再利用し、必ずsendEncodedDrainRequest(request, { label, source, timeout, retries })を経由します。別の fetch 経路は使用しません。test/adapters/encode-parity.test.tsでは一部のアダプターについてこれを固定しています。新しいアダプターを追加してください(まだすべての既存アダプターが登録されているわけではありません。これは不足であり、登録を省略してよい理由にはなりません)。 - 独自の設定解決処理は作成しません。 必ず
resolveAdapterConfigを使用します。非推奨エイリアス(token→apiKey)にはapplyDeprecatedAliasを使用します。 - コンバーターをエクスポートします。 サービス固有のイベント形式が必要な場合は、
to{Name}Event()/build{Name}Payload()ヘルパーをエクスポートし、それぞれ単独でテストできるようにします。 - エッジ環境に対応させます。 アダプターは Cloudflare Workers 上で実行されます。
Bufferは使用せず(TextEncoderとbtoaを使用します。loki.tsを参照)、Node 専用 API も使用しません。実行環境が本当にサポートできない場合のisEdgeRuntime()ガードパターンはfs.tsを参照してください。
ステップ 2:ビルド設定
既存のアダプターと並べて、packages/evlog/tsdown.config.ts にビルドエントリーを追加します。
'adapters/{name}': 'src/adapters/{name}.ts',
このファイル内の既存の順序に従ってください。
ステップ 3:パッケージのエクスポート
packages/evlog/package.json に 2 つのエントリーを追加します(最後のアダプターの後に追加し、現在のリストを確認してください。位置を決めつけないでください)。
exports 内:
"./{name}": {
"types": "./dist/adapters/{name}.d.mts",
"import": "./dist/adapters/{name}.mjs",
"default": "./dist/adapters/{name}.mjs"
}
typesVersions["*"] 内:
"{name}": [
"./dist/adapters/{name}.d.mts"
]
test/toolkit/entrypoint-registry.test.ts は 3 つの登録が相互に一致するかをチェックし、ビルドなしで実行できます。typesVersions["*"] または tsdown.config.ts にサブパスがない場合、あるいは import と default が types と同じ場所にある .mjs を参照していない場合に失敗します。エクスポートのない tsdown エントリーは、内部チャンクも同じ方法でビルドされるため報告されません。
ステップ 4:ユニットテスト
packages/evlog/test/adapters/{name}.test.ts を作成します。注釈付きのテンプレート全体については references/test-template.md を、リポジトリ全体の規約については packages/evlog/test/README.md を確認してください。
テスト README で必須とされている事項:
test/helpers/fetch.tsのmockFetch()/getFetchCall/getFetchJson/getFetchHeadersを使用してください。vi.spyOn(globalThis, 'fetch')の定型コードを独自に作成しないでください。- アダプターが読み取る環境変数は、
afterEachで必ずクリーンアップしてください。 - エクスポートされている純粋ヘルパー(
to{Name}Event、build{Name}Payload、URL リゾルバー)をそれぞれ直接テストしてください。ヘルパーごとにdescribeを 1 つ用意します。
必須のテストカテゴリ:
- URL の構築(デフォルトとカスタムエンドポイント、末尾のスラッシュへの対応)
- ヘッダー(認証、コンテンツタイプ、サービス固有のヘッダー)
- リクエストボディの形式(JSON 構造がサービスの API と一致すること)
apiKey(または必須フィールド)がない場合にスキップする動作- バッチ操作(1 回のリクエストに複数のイベントを含めること、空のバッチではフェッチをスキップすること)
- 非推奨のエイリアスが引き続き動作すること(該当する場合)
- アダプターを
test/adapters/encode-parity.test.tsに追加する
ステップ 5:E2E テストとサンドボックス
アダプターの環境変数が設定されている場合に実行され、未設定の場合はスキップされる packages/evlog/test/e2e/{name}.e2e.ts を作成します。pnpm test:e2e で実行します。
サービスをセルフホストできる場合は、クラウドの認証情報なしでアダプターを試せるように、ローカルサンドボックスを拡張します。
packages/evlog/test/e2e/docker-compose.yml:サービスを追加しますpackages/evlog/test/e2e/seed.mjs:シーダーから新しいバックエンドにもデータを送るようにしますpackages/evlog/test/e2e/README.md:説明を追加します- ルートの
package.jsonのsandbox:e2eスクリプト:必要に応じてローカル環境変数を追加します
参考として、Loki と ClickHouse の構成を確認してください。
ステップ 6:アダプターのドキュメントページ
apps/docs/ 配下を編集する前に、apps/docs/AGENTS.md を確認してください(ステップ 6~8)。
アダプターのドキュメントは、apps/docs/content/4.integrate/adapters/ 配下の 3 つのカテゴリに分かれています。
| カテゴリ | ディレクトリ | 例 |
|---|---|---|
| クラウド(SaaS のみ) | cloud/ | Axiom、PostHog、Sentry、Better Stack、Datadog |
| クラウドまたはセルフホスト | hybrid/ | Loki、ClickHouse、OTLP、HyperDX |
| セルフホスト(ローカルのみ) | self-hosted/ | FS、NuxtHub、Memory |
適切なカテゴリに、次に使用できる番号を付けて {NN}.{name}.md を作成します。frontmatter、文体、セクションの参考として Loki のページ(hybrid/01.loki.md)を使用してください。主なセクションは、概要、クイックセットアップ、設定(環境変数の表と優先順位)、高度な使い方、対象サービスでのクエリ、トラブルシューティング、直接 API を使用する方法、次のステップです。
重要:複数のフレームワークの例を記載してください。 クイックスタートセクションには、対応する各フレームワーク(Nuxt、Nitro、Next.js、SvelteKit、TanStack Start、React Router、Hono、Express、Fastify、Elysia、NestJS、oRPC、Cloudflare Workers、Standalone)について、角括弧のラベルにフレームワーク名を含めたフェンスを 1 つずつ記載する ::framework-tabs グループが必要です。Axiom ページのグループをコピーし、drain factory を差し替えてください。Nitro の例だけにしないでください。また、グループ内にはフェンス以外を入れないでください。
ステップ 7:アダプター一覧ページの更新
apps/docs/content/4.integrate/adapters/01.overview.md の 2 か所を編集します(既存のアダプターのパターンに従ってください)。
- Frontmatter の
links配列:カテゴリ順に、アイコンと/integrate/adapters/{category}/{name}のパスを含むリンク項目を追加します ::card-groupセクション:該当する位置にカードブロックを追加します
ステップ 8:公開スキルの更新
skills/review-logging-patterns/SKILL.md(/.well-known/skills/ 経由で evlog.dev に公開されています)で、次の変更を行います。
- Drain Adapters テーブルに行を追加します:
| {Name} | evlog/{name} | {NAME}_API_KEY, ... | - YAML frontmatter の
description:行にアダプター名を追加します
ステップ 9:Changeset
minor のバージョン更新を指定した .changeset/{name}-adapter.md を作成します。リリースノートとして、アダプターの機能、対応するデプロイ方法、主なオプション、環境変数、直接送信ヘルパーを記載してください。必要な詳しさについては、Loki/ClickHouse の PR にある .changeset の項目を参照してください。
手順 10:PR のスコープ
.github/workflows/semantic-pull-request.yml の scopes リストと .github/pull_request_template.md の「スコープ」セクションに、アルファベット順で {name} を追加します。PR タイトルのセクションに記載されているタイミングに関する注意点を忘れないでください。この登録が適用されるのは、ベースブランチにすでに登録が含まれている PR のみです。
検証
クリーンインストール後、まずリポジトリのルートから生成済みワークスペース型を準備し、その後パッケージのチェックを実行します。
pnpm run dev:prepare
cd packages/evlog
pnpm run lint
pnpm run typecheck
pnpm run build # required before test — api-surface snapshot is gated on dist/
pnpm run test