From 111c9ae563730cda1930e121716e37f5c4e3f0e4 Mon Sep 17 00:00:00 2001 From: dev Date: Wed, 29 Apr 2026 22:41:51 +0200 Subject: [PATCH] Document shared logger diagnostics contract --- NEXT_STEPS.md | 1 + src/arts/logr/README.md | 94 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/NEXT_STEPS.md b/NEXT_STEPS.md index ee68b6e..999663b 100644 --- a/NEXT_STEPS.md +++ b/NEXT_STEPS.md @@ -67,6 +67,7 @@ Estado al cierre: - `aapp` integration reforzado: `Connections` creadas antes de `Sess` reciben eventos posteriores de sesion y cierran en revoke. - `aapp` composition reforzado: `Frontend.dir` reacciona a locale solo mientras esta en `auto`; los overrides manuales no se pisan. - `src/arts/fend/README.md` ampliado: API, composicion via App, contrato auto/manual, locale/dir, salida DOM, integracion `adom`, persistencia, SSR y tests. +- `src/arts/logr/README.md` aclara contrato comun `Logger` en `$libs/logr` y `Diagnostics` como capa catalogada encima del logger, sin mini-loggers por modulo. - No commitear `.idea/`, `.claude/` ni `.opencode/`. Pendiente para manana: diff --git a/src/arts/logr/README.md b/src/arts/logr/README.md index 511ff10..1cc8843 100644 --- a/src/arts/logr/README.md +++ b/src/arts/logr/README.md @@ -250,6 +250,100 @@ logger.timeEnd('fetch', 'perf', 'operation done'); // emits INFO with durationM --- +## Framework Logger Contract + +El contrato minimo para cualquier modulo vive en `$libs/logr`: + +```ts +import type { Logger, LogInput, LogMessage } from '$libs/logr'; + +type LogFn = (category: string, message: LogMessage, input?: LogInput) => void; + +export interface Logger { + trace: LogFn; + debug: LogFn; + info: LogFn; + warn: LogFn; + error: LogFn; + fatal: LogFn; +} +``` + +Los artefactos no deben declarar mini-loggers locales (`logDebug`, `logInfo`, +`ConnectionLogger`, etc.). Si un modulo necesita loggear libremente, recibe +`logger?: Logger` y llama al nivel que corresponda. + +`EngineLogger` vive en `arts/logr` y extiende ese contrato con capacidades de +runtime: transports, history, children, timers, flush y dispose. El resto del +framework no necesita conocer esas capacidades para emitir logs. + +## Framework Diagnostics + +`Diagnostics` es una capa opcional encima de `Logger`, pensada para eventos +internos repetibles del framework: listener que lanza, reconnect agotado, +validacion fallida, cache invalidada, etc. + +```ts +import { createCatalogDiagnostics, LogLevel, type Diagnostics } from '$libs/logr'; +import type { Logger } from '$libs/logr'; + +type ConnEvent = + | { artifact: 'conn'; type: 'reconnect_exhausted'; meta: { attempts: number } } + | { artifact: 'conn'; type: 'transport_error'; meta: { error: unknown } }; + +function createConnDiagnostics(logger?: Logger): Diagnostics { + return createCatalogDiagnostics({ + logger, + defaultCategory: 'conn', + catalog: { + reconnect_exhausted: { + level: LogLevel.WARN, + message: 'reconnect attempts exhausted' + }, + transport_error: { + level: LogLevel.ERROR, + message: 'transport error' + } + } + }); +} +``` + +La idea no es reemplazar `logger.info(...)` ni obligar a declarar cada log como +evento. La regla es: + +- Usa `logger.info(...)`, `logger.warn(...)`, etc. para logs libres de negocio o + de modulo. +- Usa `Diagnostics.emit(...)` para eventos internos catalogados que queremos + mantener homogeneos, con categoria/mensaje/nivel centralizados. +- El diagnostic conserva `diagnostics.logger`, asi que sigue siendo un logger + normal por debajo. + +Los diagnostics pueden activar/desactivar por nivel mediante mapa explicito, no +por comparacion tradicional `level >= minLevel`: + +```ts +const diagnostics = createCatalogDiagnostics({ + logger, + catalog, + levels: { + [LogLevel.WARN]: { enabled: true }, + [LogLevel.ERROR]: { enabled: true }, + [LogLevel.DEBUG]: { enabled: false } + }, + events: { + transport_error: { level: LogLevel.ERROR }, + reconnect_exhausted: false + } +}); +``` + +El `EngineLogger` sigue siendo quien decide finalmente si la entrada se emite, +se guarda, pasa filtros de transporte o se manda a Sentry/Datadog/Loki/etc. +`Diagnostics` solo traduce un evento interno a una llamada normal del logger. + +--- + ## Transport interface ```ts