
Create Evlog Enricher
- 751 installs
- 1.7k repo stars
- Updated August 4, 2026
- hugorcd/evlog
create-evlog-enricher is a scaffolding skill that generates defineEnricher-compliant TypeScript enricher source files for developers extending the evlog event enrichment pipeline.
About
create-evlog-enricher is a skill from hugorcd/evlog that generates consistent, toolkit-compliant source files when adding a new enricher to the evlog event enrichment pipeline. It provides a template for defineEnricher factory functions, {Name}Info output interfaces, EnrichContext typing, and shared helpers like getHeader and normalizeNumber used in packages/evlog/src/enrichers/index.ts. Developers reach for create-evlog-enricher when extending evlog with a new event enricher that sets event.{name} fields without hand-copying boilerplate or breaking the defineEnricher contract. Replace {Name}, {name}, and {DISPLAY} placeholders to produce a factory function, info interface, and enricher registration ready for the monorepo pipeline.
- Generates complete TypeScript enricher using the defineEnricher factory
- Enforces 3 core architecture rules from the shared toolkit
- Includes Info interface, factory function, and JSDoc
- Provides header normalization and case-insensitive lookup helpers
- Template ready for immediate integration into evlog enrichers index
Create Evlog Enricher by the numbers
- 751 all-time installs (skills.sh)
- +3 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #1,373 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/hugorcd/evlog --skill create-evlog-enricherAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 751 |
|---|---|
| repo stars | ★ 1.7k |
| Security audit | 3 / 3 scanners passed |
| Last updated | August 4, 2026 |
| Repository | hugorcd/evlog ↗ |
How do you add a new enricher to evlog?
Quickly generate consistent, toolkit-compliant source files when extending an event enrichment pipeline.
Who is it for?
Developers extending the hugorcd/evlog monorepo who need a new defineEnricher-compliant enricher without rewriting boilerplate.
Skip if: Developers not using evlog or those building enrichment logic outside the defineEnricher and EnrichContext pattern.
When should I use this skill?
A new event enricher must be added to packages/evlog/src/enrichers with consistent defineEnricher structure.
What you get
TypeScript enricher source with {Name}Info interface, defineEnricher factory, and index.ts registration stub.
- enricher TypeScript module
- NameInfo interface
- index.ts registration stub
By the numbers
- Targets enricher registration in packages/evlog/src/enrichers/index.ts
Files
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} enricherThe 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 defineEnricher call) |
| 2 | packages/evlog/test/enrichers.test.ts | Add tests |
| 3 | apps/docs/content/4.enrichers/2.built-in.md | Add enricher to built-in docs |
| 4 | apps/docs/content/4.enrichers/1.overview.md | Add enricher to overview cards |
| 5 | skills/review-logging-patterns/SKILL.md | Add enricher to the Built-in line in the Enrichers section |
| 6 | README.md + packages/evlog/README.md | Add enricher to README enrichers section |
Important: Do NOT consider the task complete until all 6 touchpoints have been addressed.
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 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) orundefinedto skip.
defineEnricher handles the rest:
- merging via
mergeEventField(respectingoptions.overwrite) - error isolation (throws are caught and logged, never propagated)
- skipping when
computereturnsundefined
Key rules:
- Use the toolkit helpers:
getHeader()for case-insensitive header lookup,normalizeNumber()for numeric strings — both from../shared/headers(re-exported byevlog/toolkit). - Single event field — each enricher writes one top-level field on
ctx.event. - Factory pattern —
create{Name}Enricher(options?: EnricherOptions)always returns the result ofdefineEnricher(...). - No side effects — never throw, never log; rely on
defineEnricher's built-in error handling if something goes wrong.
Step 2: Tests
Add tests to packages/evlog/test/enrichers.test.ts.
Required test categories:
1. Sets field from headers — verify the enricher populates the event field correctly 2. Skips when header missing — verify no field is set when the required header 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, malformed values, case-insensitive header names
Follow the existing test structure in enrichers.test.ts — each enricher has its own describe block.
Step 3: Update Built-in Docs
Edit apps/docs/content/4.enrichers/2.built-in.md to add a new section for the enricher.
Each enricher section follows this structure:
## {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
}
}
\`\`\`Step 4: Update Overview Page
Edit apps/docs/content/4.enrichers/1.overview.md to add a card for the new enricher in the ::card-group section (before the Custom card).
Step 5: Update skills/review-logging-patterns/SKILL.md
In skills/review-logging-patterns/SKILL.md, find the Enrichers section and add the new enricher to the Built-in: line.
Step 6: Update README
Add the enricher to the enrichers section in packages/evlog/README.md (the root README.md is a symlink to it).
Verification
cd packages/evlog
pnpm run lint
pnpm run typecheck
pnpm run test
pnpm run buildEnricher 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:
export interface {Name}Info {
/** Description of field */
field1?: string
/** Description of field */
field2?: number
}Factory Function
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):
// 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 | undefinedFor 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)
Related skills
How it compares
Use create-evlog-enricher when extending hugorcd/evlog specifically rather than generic TypeScript module generators.
FAQ
What does create-evlog-enricher generate?
create-evlog-enricher produces TypeScript source for a new evlog enricher: a {Name}Info interface, a defineEnricher factory using EnrichContext, and registration patterns for packages/evlog/src/enrichers/index.ts.
Which evlog APIs does create-evlog-enricher use?
create-evlog-enricher scaffolds code around defineEnricher, EnricherOptions, EnrichContext from evlog types, and shared helpers getHeader and normalizeNumber from the enricher toolkit.
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.