Files
agents_and_robots/shell/logger/writer_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

99 lines
2.1 KiB
Go

package logger
import (
"os"
"path/filepath"
"sync"
"testing"
"time"
)
func TestDailyRotatingWriter_DayRotation(t *testing.T) {
dir := t.TempDir()
w, err := NewDailyRotatingWriter(dir, "bot1", 50, false)
if err != nil {
t.Fatal(err)
}
day1 := time.Date(2026, 3, 5, 12, 0, 0, 0, time.UTC)
day2 := time.Date(2026, 3, 6, 12, 0, 0, 0, time.UTC)
w.nowFunc = func() time.Time { return day1 }
// Force re-open with correct day.
w.current.Close()
w.currentDay = ""
w.openFile()
w.Write([]byte(`{"msg":"day1"}`))
w.nowFunc = func() time.Time { return day2 }
w.Write([]byte(`{"msg":"day2"}`))
w.Close()
agentDir := filepath.Join(dir, "bot1")
entries, _ := os.ReadDir(agentDir)
names := make(map[string]bool)
for _, e := range entries {
names[e.Name()] = true
}
if !names["2026-03-05.jsonl"] && !names["2026-03-05.jsonl.gz"] {
t.Error("expected 2026-03-05.jsonl or .gz")
}
if !names["2026-03-06.jsonl"] {
t.Error("expected 2026-03-06.jsonl")
}
}
func TestDailyRotatingWriter_SizeRotation(t *testing.T) {
dir := t.TempDir()
// 1 byte max to force rotation on every write.
w, err := NewDailyRotatingWriter(dir, "bot2", 0, false)
if err != nil {
t.Fatal(err)
}
// Override maxSize to a tiny value (can't use 0 MB).
w.maxSize = 10
now := time.Date(2026, 3, 6, 10, 0, 0, 0, time.UTC)
w.nowFunc = func() time.Time { return now }
w.current.Close()
w.currentDay = ""
w.openFile()
w.Write([]byte(`{"line":1}` + "\n"))
w.Write([]byte(`{"line":2}` + "\n"))
w.Write([]byte(`{"line":3}` + "\n"))
w.Close()
entries, _ := os.ReadDir(filepath.Join(dir, "bot2"))
if len(entries) < 2 {
t.Errorf("expected multiple files from size rotation, got %d", len(entries))
}
}
func TestDailyRotatingWriter_Concurrent(t *testing.T) {
dir := t.TempDir()
w, err := NewDailyRotatingWriter(dir, "bot3", 50, false)
if err != nil {
t.Fatal(err)
}
defer w.Close()
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
w.Write([]byte(`{"concurrent":true}` + "\n"))
}()
}
wg.Wait()
entries, _ := os.ReadDir(filepath.Join(dir, "bot3"))
if len(entries) == 0 {
t.Error("expected at least one log file")
}
}