feat: tipos Logger, LogLevel y LogEntry para structured logging (infra)
Tipos base para las funciones de structured logging sobre log/slog: - LogLevel: suma enum Debug/Info/Warn/Error - Logger: wrapper producto con nivel, output, formato y fields contextuales - LogEntry: modelo canonico JSON para tests y pipelines de logs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
package infra
|
||||
|
||||
import "time"
|
||||
|
||||
// LogEntry representa una entrada de log estructurada serializable a JSON.
|
||||
// Se usa como modelo canonico para tests y para pipelines que procesan logs.
|
||||
type LogEntry struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Level string `json:"level"`
|
||||
Message string `json:"message"`
|
||||
Fields map[string]any `json:"fields,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package infra
|
||||
|
||||
// LogLevel representa los niveles de log soportados por el Logger.
|
||||
// El orden implicito es Debug < Info < Warn < Error.
|
||||
type LogLevel int
|
||||
|
||||
const (
|
||||
// LogLevelDebug es el nivel mas verbose, util para trazas de desarrollo.
|
||||
LogLevelDebug LogLevel = iota
|
||||
// LogLevelInfo es el nivel por defecto para eventos normales del sistema.
|
||||
LogLevelInfo
|
||||
// LogLevelWarn indica situaciones anomalas que no impiden el funcionamiento.
|
||||
LogLevelWarn
|
||||
// LogLevelError indica fallos que requieren atencion.
|
||||
LogLevelError
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
package infra
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
// Logger wrappea slog.Logger con config del registry (nivel, output, formato, campos contextuales).
|
||||
// Se crea con LoggerNew y se clona inmutablemente con LoggerWith anadiendo campos.
|
||||
type Logger struct {
|
||||
Level LogLevel // nivel minimo filtrado
|
||||
Output io.Writer // destino de los logs (stdout, stderr, file, buffer)
|
||||
Format string // "json" | "text"
|
||||
Fields map[string]any // campos contextuales adjuntos al logger
|
||||
inner *slog.Logger // handler real de slog
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
name: LogEntry
|
||||
lang: go
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
algebraic: product
|
||||
definition: |
|
||||
type LogEntry struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Level string `json:"level"`
|
||||
Message string `json:"message"`
|
||||
Fields map[string]any `json:"fields,omitempty"`
|
||||
}
|
||||
description: "Entrada de log estructurada serializable a JSON. Modelo canonico para tests y pipelines de procesamiento de logs."
|
||||
tags: [logging, log, entry, json, infra]
|
||||
uses_types: []
|
||||
file_path: "functions/infra/log_entry.go"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
entry := LogEntry{
|
||||
Timestamp: time.Now(),
|
||||
Level: "INFO",
|
||||
Message: "server starting",
|
||||
Fields: map[string]any{"port": 8484, "app": "api"},
|
||||
}
|
||||
data, _ := json.Marshal(entry)
|
||||
// {"timestamp":"2026-04-18T10:00:00Z","level":"INFO","message":"server starting","fields":{"app":"api","port":8484}}
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Tipo producto — cuatro campos, todos exportados. El formato JSON de slog usa claves diferentes (`time`, `level`, `msg`) pero este tipo sirve como adaptador cuando se deserializan logs para tests o para pipelines downstream. `Fields` es opcional (omitempty) y permite adjuntar cualquier contexto key-value.
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: LogLevel
|
||||
lang: go
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
algebraic: sum
|
||||
definition: |
|
||||
type LogLevel int
|
||||
|
||||
const (
|
||||
LogLevelDebug LogLevel = iota
|
||||
LogLevelInfo
|
||||
LogLevelWarn
|
||||
LogLevelError
|
||||
)
|
||||
description: "Nivel de log soportado por el Logger. Los valores ordenados de menor a mayor severidad son Debug, Info, Warn y Error."
|
||||
tags: [logging, log, level, slog, infra]
|
||||
uses_types: []
|
||||
file_path: "functions/infra/log_level.go"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
logger, _ := LoggerNew(LogLevelInfo, os.Stdout, "json")
|
||||
LogDebug(logger, "no se imprime") // filtrado porque Debug < Info
|
||||
LogInfo(logger, "server up") // se imprime
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Tipo suma — los cuatro valores son exhaustivos y se corresponden uno a uno con los niveles de `log/slog` (slog.LevelDebug, slog.LevelInfo, slog.LevelWarn, slog.LevelError). El orden de comparacion sigue la convencion clasica: cuanto mas alto, mas severo. Util para configurar filtrado en LoggerNew.
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: Logger
|
||||
lang: go
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
algebraic: product
|
||||
definition: |
|
||||
type Logger struct {
|
||||
Level LogLevel
|
||||
Output io.Writer
|
||||
Format string
|
||||
Fields map[string]any
|
||||
inner *slog.Logger
|
||||
}
|
||||
description: "Wrapper sobre slog.Logger con config del registry: nivel, destino (io.Writer), formato (json/text) y campos contextuales inmutables."
|
||||
tags: [logging, log, slog, logger, infra]
|
||||
uses_types: [LogLevel_go_infra]
|
||||
file_path: "functions/infra/logger.go"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
logger, err := LoggerNew(LogLevelInfo, os.Stdout, "json")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
appLog := LoggerWith(logger, map[string]any{"app": "sqlite_api"})
|
||||
LogInfo(appLog, "server starting", "port", 8484)
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Tipo producto — los campos publicos describen la config y los fields contextuales. El campo privado `inner` es la instancia real de `slog.Logger` que escribe. Se construye con `LoggerNew` (impuro) y se clona con `LoggerWith` (puro). Nunca se muta despues de creado.
|
||||
Reference in New Issue
Block a user