Skip to main content

create-evlog-enricher

Create a new built-in evlog enricher to add derived context to wide events. Use when adding a new enricher (e.g., for deployment metadata, tenant context, feature flags, etc.) to the evlog package. Covers source code, tests, and all documentation.

설치로 이동

소스 정보

저장소
evloghq/evlog
최근 소스 활동
2026년 8월 29일 16:04
감지된 SKILL.md 언어
영어
스타
1,855
포크
63

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
2 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
create-evlog-enricher
description
Create a new built-in evlog enricher to add derived context to wide events. Use when adding a new enricher (e.g., for deployment metadata, tenant context, feature flags, etc.) to the evlog package. Covers source code, tests, and all documentation.
metadata
{"internal":true}
# Create evlog Enricher Add a new built-in enricher to evlog. Every enricher is built on the public toolkit primitive `defineEnricher` from `evlog/toolkit`, so a community enricher has the same shape as a built-in one. ## PR Title ``` feat(core): add the {name} enricher ``` Enrichers live in the core package surface (`evlog/enrichers`), so use the `core` scope unless a dedicated scope exists. ## Touchpoints Checklist | # | File | Action | |---|------|--------| | 1 | `packages/evlog/src/enrichers/index.ts` | Add enricher source (one `defineEnricher` call) | | 2 | Same file — `createDefaultEnrichers()` | Decide whether the enricher belongs in the default composition (see below) | | 3 | `packages/evlog/test/toolkit/enrichers.test.ts` | Add tests (one `describe` block per enricher) | | 4 | `apps/docs/content/5.use-cases/5.enrichers.md` | Add a section for the enricher + update the import list and, if applicable, the "All built-in enrichers" default composition text | | 5 | `skills/review-logging-patterns/SKILL.md` | Add the enricher to the `Built-in:` line in the Enrichers section | | 6 | `packages/evlog/README.md` | Add the enricher to the Built-in Enrichers section (root `README.md` is a symlink to it) | | 7 | `.changeset/{name}-enricher.md` | Create changeset (`minor`) | **Important**: Do NOT consider the task complete until all 7 touchpoints have been addressed. ### Should it join `createDefaultEnrichers()`? `createDefaultEnrichers()` composes user agent, geo, request size, and trace context via `composeEnrichers` (from `../shared/compose`). Add the new enricher to the composition only if it is universally applicable and reads nothing but the request (headers/env). Anything requiring service-specific setup or extra cost stays opt-in. Changing the default composition is a behavior change for every existing `createDefaultEnrichers()` user: call it out explicitly in the changeset. ## Naming Conventions | Placeholder | Example (UserAgent) | Usage | |-------------|---------------------|-------| | `{name}` | `userAgent` | camelCase for event field key | | `{Name}` | `UserAgent` | PascalCase in function/interface names | | `{DISPLAY}` | `User Agent` | Human-readable display name | ## Step 1: Enricher Source: built on `defineEnricher` Add the enricher to `packages/evlog/src/enrichers/index.ts`. Read [references/enricher-template.md](references/enricher-template.md) for the full annotated template. The contract is `defineEnricher<T>({ name, field, compute }, options?)`. You only ship one piece of logic: - **`compute(ctx)`**: return the computed value (typed as `T`) or `undefined` to skip. `defineEnricher` handles the rest: - merging via `mergeEventField` (respecting `options.overwrite`, default `false`) - error isolation (throws are caught and logged, never propagated) - skipping when `compute` returns `undefined` Key rules: - **Use the toolkit helpers**: `getHeader()` for case-insensitive header lookup, `normalizeNumber()` for numeric strings. Both from `../shared/headers` (re-exported by `evlog/toolkit`). - **Single event field**: each enricher writes one top-level field on `ctx.event`. If the enricher must additionally pin top-level fields (like `createTraceContextEnricher` does for `event.traceId` / `event.spanId`), wrap the `defineEnricher` result in a closure, see that enricher for the pattern. - **Factory pattern**: `create{Name}Enricher(options: EnricherOptions = {})` returns the result of `defineEnricher(...)`, directly in the normal case, or through the thin closure wrapper when the enricher also pins top-level fields (see the single-event-field rule above). - **No side effects**: never throw, never log; rely on `defineEnricher`'s built-in error handling if something goes wrong. - **Export the Info type**: `{Name}Info` describing the field shape, exported alongside the factory. ## Step 2: Tests Add tests to `packages/evlog/test/toolkit/enrichers.test.ts`, following the existing structure (one `describe` block per enricher) and `packages/evlog/test/README.md` conventions. Required test categories: 1. **Sets the field from its source**: verify the enricher populates the event field correctly, reading whatever it actually reads (`ctx.request`, `ctx.response`, `process.env`, `ctx.event`, or headers) 2. **Skips when source data missing**: verify no field is set when the required input is absent 3. **Preserves existing data**: verify `overwrite: false` (default) doesn't replace user-provided fields 4. **Overwrites when requested**: verify `overwrite: true` replaces existing fields 5. **Handles edge cases**: empty strings and malformed values, plus case-insensitive lookup for a header-based enricher 6. **Default composition**: if the enricher joined `createDefaultEnrichers()`, extend that composition's tests ## Step 3: Update the Enrichers Docs Page Edit `apps/docs/content/5.use-cases/5.enrichers.md`: 1. Add the enricher to the import list at the top 2. Add a `## {DISPLAY}` section following the structure of the existing ones: ```markdown ## {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 } } \`\`\` ``` 3. If the enricher joined the default composition, update the "All built-in enrichers" section text listing what `createDefaultEnrichers()` composes. Custom-enricher authoring docs live separately at `apps/docs/content/6.extend/5.custom-enrichers.md`, with no change needed there unless the toolkit contract itself changed. ## Step 4: Update the Public Skill In `skills/review-logging-patterns/SKILL.md` (published on evlog.dev), find the **Enrichers** section and add the new enricher to the `Built-in:` line. ## Step 5: Update README Add the enricher to the **Built-in Enrichers** section in `packages/evlog/README.md` (the root `README.md` is a symlink to it). ## Step 6: Changeset Create `.changeset/{name}-enricher.md` with a `minor` bump describing what the enricher sets and when to use it. Mention explicitly if the default composition changed. ## Verification ```bash cd packages/evlog pnpm run lint pnpm run typecheck pnpm run test pnpm run build ```
GitHub에서 보기