
Create Evlog Enricher
Add a typed evlog enricher via defineEnricher, getHeader, and normalizeNumber instead of hand-rolling event enrichment logic.
Install
npx skills add https://github.com/hugorcd/evlog --skill create-evlog-enricherWhat is this skill?
- defineEnricher<T> primitive with name, field, and compute callback pattern
- Case-insensitive getHeader helper for x-* and standard headers
- normalizeNumber for string header values mapped to numeric event fields
- Single event field contract: event.{name} with a typed {Name}Info interface
Adoption & trust: 688 installs on skills.sh; 1.4k GitHub stars; 3/3 security scanners passed (skills.sh audits).
Recommended Skills
Entra App Registrationmicrosoft/azure-skills
Azure Aigatewaymicrosoft/azure-skills
Lark Openapi Explorerlarksuite/cli
Supabasesupabase/agent-skills
Firebase Auth Basicsfirebase/agent-skills
Firebase Data Connectfirebase/agent-skills
Journey fit
Common Questions / FAQ
Is Create Evlog Enricher safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Create Evlog Enricher
# Enricher Source Template Template for adding a new enricher to `packages/evlog/src/enrichers/index.ts` using `defineEnricher`. Replace `{Name}`, `{name}`, and `{DISPLAY}` with the actual enricher name. ## Info Interface Define the output shape: ```typescript export interface {Name}Info { /** Description of field */ field1?: string /** Description of field */ field2?: number } ``` ## Factory Function ```typescript import type { EnrichContext } from '../types' import { defineEnricher, type EnricherOptions } from '../shared/enricher' import { getHeader, normalizeNumber } from '../shared/headers' /** * Enrich events with {DISPLAY} data. * Sets `event.{name}` with `{Name}Info` shape: `{ field1?, field2? }`. */ export function create{Name}Enricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void { return defineEnricher<{Name}Info>({ name: '{name}', field: '{name}', compute: ({ headers }) => { const value = getHeader(headers, 'x-my-header') if (!value) return undefined return { field1: value, field2: normalizeNumber(value), } }, }, options) } ``` ## Architecture Rules 1. **Use the toolkit primitive**: `defineEnricher<T>({ name, field, compute }, options)` from `../shared/enricher` (re-exported as `evlog/toolkit`). 2. **Use the toolkit helpers**: `getHeader()` for case-insensitive header lookup and `normalizeNumber()` for numeric strings — both from `../shared/headers`. 3. **Single event field** — each enricher writes one top-level field on `ctx.event` (declared via the `field` option). 4. **Return `undefined` to skip** — `compute` returning `undefined` makes the enricher a no-op for that event (no field merge, no errors). 5. **Factory pattern** — always wrap `defineEnricher` in a `create{Name}Enricher(options?)` factory and return its result. 6. **No try/catch** — `defineEnricher` already isolates errors (logs as `[evlog/{name}]` and never throws to the pipeline). 7. **No mutation outside `compute`** — let `defineEnricher` handle the merge via `mergeEventField`. ## Available Helpers These helpers are exported from `../shared/headers` (and from `evlog/toolkit`): ```typescript // Case-insensitive header lookup function getHeader(headers: Record<string, string> | undefined, name: string): string | undefined // Parse string to number, returning undefined for non-finite values function normalizeNumber(value: string | undefined): number | undefined ``` For lower-level merging (rarely needed) the toolkit also exports `mergeEventField` from `../shared/event`. ## Data Sources Enrichers typically read from `ctx`: - **`ctx.headers`** — HTTP request headers (sensitive headers already filtered) - **`ctx.response?.headers`** — HTTP response headers - **`ctx.response?.status`** — HTTP response status code - **`ctx.request`** — Request metadata (method, path, requestId) - **`process.env`** — Environment variables (for deployment metadata) - **`ctx.event`** — The event itself (for computed/derived fields) --- 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. --- # 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 Recommended format for the pull request title: ``` feat: add {name} enricher ``` The exact wording may vary depending on the enricher (e.g., `feat: add user agent enricher`, `feat: add geo enricher`), but it should always follow the `feat:` conventional commit prefix. ## Touchpoints Checklist | # | File | Action | |---|------|--------| | 1 | `packages/evlog/src/enrichers/index.ts` | Add enricher source (one `defineEnric