feat(observability): configurable logging, request ids and error logs

- internal/logging: LOG_LEVEL/LOG_FORMAT parsing and slog handler
- request_id middleware (X-Request-ID or generated, echoed) + debug access log
- httpx registers errors; middleware logs internal causes with request_id
- health excluded, objects/sse debug-only, no query/body/secrets in logs
- new observability capability spec; README/.env.example docs
This commit is contained in:
iu
2026-10-11 13:40:11 +03:00
parent a5d0cee0eb
commit 6361e48b20
18 changed files with 998 additions and 5 deletions
+44
View File
@@ -132,3 +132,47 @@ func TestLoadDatabaseBackend(t *testing.T) {
}
})
}
func TestLoadLog(t *testing.T) {
t.Run("defaults", func(t *testing.T) {
setRequiredEnv(t)
t.Setenv("LOG_LEVEL", "")
t.Setenv("LOG_FORMAT", "")
cfg, err := Load()
if err != nil {
t.Fatalf("load: %v", err)
}
if cfg.Log.Level != "info" || cfg.Log.Format != "json" {
t.Fatalf("log = %+v, want info/json", cfg.Log)
}
})
t.Run("custom values", func(t *testing.T) {
setRequiredEnv(t)
t.Setenv("LOG_LEVEL", "debug")
t.Setenv("LOG_FORMAT", "text")
cfg, err := Load()
if err != nil {
t.Fatalf("load: %v", err)
}
if cfg.Log.Level != "debug" || cfg.Log.Format != "text" {
t.Fatalf("log = %+v, want debug/text", cfg.Log)
}
})
t.Run("invalid level", func(t *testing.T) {
setRequiredEnv(t)
t.Setenv("LOG_LEVEL", "trace")
if _, err := Load(); err == nil {
t.Fatal("expected error for invalid LOG_LEVEL")
}
})
t.Run("invalid format", func(t *testing.T) {
setRequiredEnv(t)
t.Setenv("LOG_FORMAT", "xml")
if _, err := Load(); err == nil {
t.Fatal("expected error for invalid LOG_FORMAT")
}
})
}