create-evlog-enricher について
evlog の組み込みエンリッチャー追加を案内する、コントリビューター向けのリポジトリスキルです。`defineEnricher` の実装パターンに加え、フィールドの動作、テスト、ドキュメント、デフォルト構成、リリース更新を扱います。
主な機能
- 01defineEnricher の実装パターン
- 02イベントの単一フィールド拡張
- 03上書きとデータ欠落時の動作
- 04エンリッチャーのテスト要件
- 05ドキュメントと README の更新
- 06デフォルト構成の判断指針
活用シーン
- 01リクエストコンテキスト由来のフィールド追加
- 02元データ欠落時の動作確認
- 03値の保持と上書き設定のテスト
- 04組み込みエンリッチャーの文書化とリリース
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ evloghq/ evlog --skill create-evlog-enricherインストール後、Claude Code で/create-evlog-enricherを入力して読み込まれたか確認します。
詳細
evlog エンリッチャーの作成
evlog に新しい組み込みエンリッチャーを追加します。すべてのエンリッチャーは、evlog/toolkit の公開ツールキットプリミティブ defineEnricher を基に構築されているため、コミュニティ製エンリッチャーも組み込みエンリッチャーと同じ形式です。
PR タイトル
feat(core): add the {name} enricher
エンリッチャーはコアパッケージの公開サーフェス(evlog/enrichers)にあるため、専用のスコープが存在しない場合は core スコープを使用してください。
対応箇所チェックリスト
| # | ファイル | 対応内容 |
|---|---|---|
| 1 | packages/evlog/src/enrichers/index.ts | エンリッチャーのソースを追加(defineEnricher の呼び出しを 1 つ) |
| 2 | 同じファイル:createDefaultEnrichers() | エンリッチャーをデフォルト構成に含めるか判断する(以下を参照) |
| 3 | packages/evlog/test/toolkit/enrichers.test.ts | テストを追加(エンリッチャーごとに describe ブロックを 1 つ) |
| 4 | apps/docs/content/5.use-cases/5.enrichers.md | エンリッチャーのセクションを追加し、インポート一覧と、該当する場合は「All built-in enrichers」のデフォルト構成の説明を更新する |
| 5 | skills/review-logging-patterns/SKILL.md | Enrichers セクションの Built-in: 行にエンリッチャーを追加する |
| 6 | packages/evlog/README.md | Built-in Enrichers セクションにエンリッチャーを追加する(ルートの README.md はこのファイルへのシンボリックリンクです) |
| 7 | .changeset/{name}-enricher.md | changeset(minor)を作成する |
重要:7 つすべての対応箇所を網羅するまで、タスクを完了とみなさないでください。
createDefaultEnrichers() に含めるべきですか?
createDefaultEnrichers() は、composeEnrichers(../shared/compose から)を使ってユーザーエージェント、地理情報、リクエストサイズ、トレースコンテキストを組み合わせます。新しいエンリッチャーを構成に追加するのは、汎用的に適用でき、リクエスト(ヘッダー/環境変数)以外を参照しない場合に限ります。サービス固有の設定や追加コストが必要なものは、オプトインのままにしてください。デフォルト構成の変更は、既存の createDefaultEnrichers() のすべての利用者に影響する動作変更です。changeset で明示してください。
命名規則
| プレースホルダー | 例(UserAgent) | 用途 |
|---|---|---|
{name} | userAgent | イベントフィールドキーには camelCase を使用 |
{Name} | UserAgent | 関数名/インターフェース名には PascalCase を使用 |
{DISPLAY} | User Agent | 人が読みやすい表示名 |
ステップ 1:エンリッチャーのソース:defineEnricher を基に構築
エンリッチャーを packages/evlog/src/enrichers/index.ts に追加します。注釈付きの完全なテンプレートについては、references/enricher-template.md を参照してください。
契約は defineEnricher<T>({ name, field, compute }, options?) です。実装するロジックは 1 つだけです。
compute(ctx):計算した値(型はT)を返すか、スキップする場合はundefinedを返します。
残りの処理は defineEnricher が行います。
mergeEventFieldによるマージ(options.overwriteを尊重します。デフォルトはfalse)- エラーの分離(例外を捕捉してログに記録し、伝播させません)
computeがundefinedを返した場合のスキップ
主なルール:
- ツールキットのヘルパーを使用する:大文字と小文字を区別しないヘッダー検索には
getHeader()、数値文字列の処理にはnormalizeNumber()を使用します。どちらも../shared/headersにあり、evlog/toolkitから再エクスポートされています。 - イベントフィールドは 1 つ:各エンリッチャーは、
ctx.eventのトップレベルにフィールドを 1 つ書き込みます。エンリッチャーが追加でトップレベルフィールドを固定する必要がある場合(createTraceContextEnricherがevent.traceId/event.parentSpanIdに対して行うように)、defineEnricherの結果をクロージャーでラップします。パターンについては、そのエンリッチャーを参照してください。 - ファクトリーパターン:
create{Name}Enricher(options: EnricherOptions = {})は通常、defineEnricher(...)の結果を直接返します。エンリッチャーがトップレベルフィールドも固定する場合は、薄いクロージャーラッパーを介して返します(上記のイベントフィールドは 1 つというルールを参照)。 - 副作用なし:例外をスローしたり、ログを記録したりしないでください。問題が発生した場合は、
defineEnricherに組み込まれたエラー処理に任せてください。 - Info 型をエクスポートする:フィールドの形状を示す
{Name}Infoを定義し、ファクトリーとともにエクスポートします。
ステップ 2:テスト
既存の構成(エンリッチャーごとに 1 つの describe ブロック)と packages/evlog/test/README.md の規約に従って、packages/evlog/test/toolkit/enrichers.test.ts にテストを追加します。
必須のテストカテゴリ:
- ソースからフィールドを設定する:エンリッチャーがイベントフィールドを正しく設定することを検証します。実際に読み取るデータ(
ctx.request、ctx.response、process.env、ctx.event、またはヘッダー)を読み取るようにします - ソースデータがない場合はスキップする:必要な入力がない場合にフィールドが設定されないことを検証します
- 既存データを保持する:
overwrite: false(デフォルト)では、ユーザーが設定したフィールドが置き換えられないことを検証します - 指定時に上書きする:
overwrite: trueでは、既存のフィールドが置き換えられることを検証します - エッジケースに対応する:空文字列や不正な値、およびヘッダーを使用するエンリッチャーの場合は大文字小文字を区別しない検索を検証します
- デフォルト構成:エンリッチャーが
createDefaultEnrichers()に追加された場合、その構成のテストを拡張します
ステップ 3:Enrichers のドキュメントページを更新する
apps/docs/content/5.use-cases/5.enrichers.md を編集します:
- 冒頭のインポート一覧にエンリッチャーを追加します
- 既存セクションの構成に従って、
## {DISPLAY}セクションを追加します:
## {DISPLAY}
[One-sentence description of what the enricher does.]
**Sets:** `event.{name}`
\`\`\`typescript
const enrich = create{Name}Enricher()
\`\`\`
**Output shape:**
\`\`\`typescript
interface {Name}Info {
// fields
}
\`\`\`
**Example output:**
\`\`\`json
{
"{name}": {
// example values
}
}
\`\`\`
- エンリッチャーがデフォルト構成に追加された場合、「All built-in enrichers」セクションの、
createDefaultEnrichers()が構成する内容を列挙したテキストを更新します。
カスタムエンリッチャーの作成に関するドキュメントは apps/docs/content/6.extend/5.custom-enrichers.md に別途あります。ツールキットの契約自体が変更された場合を除き、そちらの更新は不要です。
ステップ 4:公開済みスキルを更新する
(evlog.dev で公開されている)skills/review-logging-patterns/SKILL.md の Enrichers セクションを見つけ、Built-in: の行に新しいエンリッチャーを追加します。
ステップ 5:README を更新する
packages/evlog/README.md の Built-in Enrichers セクションにエンリッチャーを追加します(ルートの README.md はこのファイルへのシンボリックリンクです)。
ステップ 6:チェンジセット
minor のバンプを設定し、エンリッチャーが設定する内容と使用するタイミングを説明した .changeset/{name}-enricher.md を作成します。デフォルト構成が変更された場合は、その旨を明記します。
検証
cd packages/evlog
pnpm run lint
pnpm run typecheck
pnpm run test
pnpm run build