114 lines
5.0 KiB
Markdown
114 lines
5.0 KiB
Markdown
# OpenSpec Change: enterprise-logger
|
|
|
|
- **Change ID**: enterprise-logger
|
|
- **Package**: `@suaveplan/logger`
|
|
- **Category**: universal
|
|
- **Target path**: `packages/universal/logger`
|
|
- **Status**: IN PROGRESS
|
|
- **Date**: 2026-04-18
|
|
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/logger.md`
|
|
|
|
## Summary
|
|
|
|
Greenfield implementation of `@suaveplan/logger` for the genesis branch. The existing main-branch logger (v1.23) provides the baseline public-API surface to preserve; this change adds enterprise-grade structured JSON output, declarative redaction, head/tail/rule-based sampling, OpenTelemetry correlation, pluggable sinks, property-based tests, and benchmarks.
|
|
|
|
## Current-state audit (genesis)
|
|
|
|
The package does not exist on genesis yet — this is a fresh build.
|
|
|
|
## Available workspace deps on genesis
|
|
|
|
| Package | Available |
|
|
|---------|-----------|
|
|
| `@suaveplan/error` | ✅ |
|
|
| `@suaveplan/events` | ✅ |
|
|
| `@suaveplan/types` | ✅ |
|
|
| `@suaveplan/timing` | ❌ not yet built — use `Clock` from `@suaveplan/types` |
|
|
| `@suaveplan/storage` | ❌ not yet built — keep `StorageInterface` locally |
|
|
| `@suaveplan/streams` | ❌ not yet built — implement bounded buffer internally |
|
|
| `@suaveplan/opentelemetry` | ❌ not yet built — use `@opentelemetry/api` directly |
|
|
| `@suaveplan/feature-flags` | ❌ not yet built — skip |
|
|
| `@suaveplan/schema-registry` | ❌ not yet built — export Zod schemas directly |
|
|
|
|
External deps (via catalog):
|
|
|
|
- `zod` → `catalog:forms`
|
|
- `@opentelemetry/api` → `catalog:observability`
|
|
- `tslib` → `catalog:build`
|
|
|
|
Dev deps (via catalog):
|
|
|
|
- `vitest`, `@vitest/coverage-istanbul` → `catalog:testing`
|
|
- `fast-check` → `catalog:testing`
|
|
- `mitata` → `catalog:testing`
|
|
|
|
## Preserved public API surface (from main branch)
|
|
|
|
All of the following must be exported from the genesis build:
|
|
|
|
### Types
|
|
|
|
- `LogLevel`, `LogEntry<TMetadata>`, `LoggerConfig<TMetadata>`, `LoggerMetrics`
|
|
- `ConsoleLoggerConfig<TMetadata>`
|
|
- `EventLoggerConfig<TMetadata>`, `LoggerEvents<TMetadata>`
|
|
- `StorageLoggerConfig<TMetadata>`, `StorageInterface`
|
|
- `ConsoleLoggerFactoryConfig<TMetadata>`, `StorageLoggerFactoryConfig<TMetadata>`, `EventLoggerFactoryConfig<TMetadata>`, `LoggerFactoryConfig<TMetadata>`
|
|
- `InitLoggerOptions<TMetadata>`, `InitLoggerResult`
|
|
- `SeverityLevelMap`, `UninstallErrorInterceptor`, `InstallErrorInterceptorOptions`
|
|
|
|
### Classes
|
|
|
|
- `AbstractLogger<TMetadata>` (abstract)
|
|
- `ConsoleLogger<TMetadata>`
|
|
- `EventLogger<TMetadata>`
|
|
- `StorageLogger<TMetadata>`
|
|
|
|
### Interfaces
|
|
|
|
- `Logger<TMetadata>`
|
|
- `LogLevels`
|
|
|
|
### Functions
|
|
|
|
- `createLogger(config)` (overloaded factory)
|
|
- `initLogger(options?)` → `InitLoggerResult`
|
|
- `installSuaveplanErrorInterceptor(logger?)` → `UninstallErrorInterceptor`
|
|
- `__resetDefaultLoggerForTests()`
|
|
|
|
## New additions
|
|
|
|
### Modules
|
|
|
|
- **`record/`** — `LogRecord` structured JSON schema (Zod), `ts`/`level`/`msg`/`ctx`/`trace_id`/`span_id`/`error` fields
|
|
- **`errors/`** — `LoggerError` extending `SuaveplanError`; codes: `LOGGER.SINK`, `LOGGER.SERIALIZE`, `LOGGER.CONFIG`, `LOGGER.FLUSH`
|
|
- **`redaction/`** — `RedactionEngine` with field-path rules (dot-notation + glob), regex rules, depth limit; `@sensitive`-aware via `isSensitive()` from `@suaveplan/error`
|
|
- **`sampling/`** — `HeadSampler` (deterministic per trace_id hash), `TailSampler` (bounded buffer + decision callback), `RuleSampler` (predicate-based); `SamplingPolicy` union type
|
|
- **`sink/`** — `Sink` interface; `ConsoleSink` (ANSI dev output); `JsonSink` (NDJSON writer); `BufferedSink` (bounded queue, drop/block policy, `AbortSignal` flush)
|
|
- **`otel/`** — `getOtelTraceContext()` reads `trace_id`/`span_id` from active OTel span (no-op when no exporter)
|
|
- **`schemas/`** — Zod schemas for `LoggerConfig`, `LogRecord`, all sink configs (re-exported)
|
|
|
|
### Cross-cutting enterprise requirements
|
|
|
|
- Injectable `clock` (from `@suaveplan/types#Clock`) and `rng` on all time/random usages
|
|
- `AbortSignal` support on `flush()` and `getLogs()`
|
|
- `sideEffects: false` + tree-shake test
|
|
- Property-based tests (fast-check) for redaction invariants and sampling determinism
|
|
- mitata benchmarks in `src/__benchmarks__/`
|
|
- OTel counters + histograms on `log()` calls (via `@opentelemetry/api`, no-op when unregistered)
|
|
- Zero `any`, zero `ts-ignore`, zero mock usage in tests
|
|
|
|
## Dependency-layer check
|
|
|
|
`@suaveplan/logger` depends on `@suaveplan/error` and `@suaveplan/events`, both of which are enterprise-complete on genesis. ✅
|
|
|
|
## Acceptance criteria
|
|
|
|
- [x] `bunx turbo lint typecheck test:coverage --filter=@suaveplan/logger` green with ≥ 100% coverage on touched modules
|
|
- [x] `bun run docs:check --filter=@suaveplan/logger` reports ≥ 90%
|
|
- [x] All preserved public API surface exported from `src/index.ts`
|
|
- [x] New `LogRecord` schema, `LoggerError`, redaction, sampling, sink, OTel modules implemented
|
|
- [x] Zero `any`, `ts-ignore`, `TODO`, `FIXME`, `@deprecated`, `.skip`, `.only` in `src/`
|
|
- [x] Property-based tests for redaction invariants and sampling determinism
|
|
- [x] mitata benchmarks in `src/__benchmarks__/`
|
|
- [x] `sideEffects: false` confirmed, tree-shake test passes
|