Files
agents_and_robots/shell/logger/logger_test.go
T
egutierrez 71079962ca feat: add structured JSONL logging package with rotation and query
Nuevo paquete shell/logger/ que implementa logging estructurado JSONL
para agentes. Incluye DailyRotatingWriter con rotación diaria y por
tamaño (50MB default), limpieza automática de archivos viejos (7 días),
compresión gzip de logs rotados, y funciones de consulta (ReadLogs,
SearchLogs, ListAgents, ListDates) para que agentes LLM puedan leer
logs de otros agentes. Basado en log/slog de stdlib, sin dependencias
externas. 18 tests unitarios cubren rotación, concurrencia y consultas.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 17:26:56 +00:00

78 lines
1.6 KiB
Go

package logger
import (
"context"
"encoding/json"
"log/slog"
"os"
"path/filepath"
"testing"
)
func TestNewAgentLogger_WritesJSONL(t *testing.T) {
dir := t.TempDir()
l, cleanup, err := NewAgentLogger(LoggerConfig{
BaseDir: dir,
AgentID: "test-bot",
Level: slog.LevelDebug,
})
if err != nil {
t.Fatal(err)
}
defer cleanup()
l.Info("hello world", FieldAction, "greet", FieldReason, "testing")
// Force flush by closing.
cleanup()
files, _ := os.ReadDir(filepath.Join(dir, "test-bot"))
if len(files) == 0 {
t.Fatal("expected at least one log file")
}
data, err := os.ReadFile(filepath.Join(dir, "test-bot", files[0].Name()))
if err != nil {
t.Fatal(err)
}
var m map[string]any
if err := json.Unmarshal(data, &m); err != nil {
t.Fatalf("log line is not valid JSON: %s", data)
}
if m["msg"] != "hello world" {
t.Errorf("msg = %v, want hello world", m["msg"])
}
if m[FieldAgentID] != "test-bot" {
t.Errorf("agent_id = %v, want test-bot", m[FieldAgentID])
}
if m[FieldAction] != "greet" {
t.Errorf("action = %v, want greet", m[FieldAction])
}
}
func TestNewAgentLogger_Stdout(t *testing.T) {
l, cleanup, err := NewAgentLogger(LoggerConfig{
BaseDir: "stdout",
AgentID: "dev-bot",
})
if err != nil {
t.Fatal(err)
}
defer cleanup()
// Just verify it doesn't panic.
l.Info("stdout test")
}
func TestTraceIDContext(t *testing.T) {
ctx := context.Background()
if got := TraceIDFromCtx(ctx); got != "" {
t.Errorf("empty ctx should return empty trace, got %q", got)
}
ctx = WithTraceID(ctx, "abc-123")
if got := TraceIDFromCtx(ctx); got != "abc-123" {
t.Errorf("trace = %q, want abc-123", got)
}
}