1a2ad98c33
Runnable skeleton per AGENT.md: Echo server (/, /help, /healthz, /api/repos), read-only repo scanner with in-memory index, the internal/git boundary, the <repo-list> web component with design tokens, and dev tooling (Dockerfile, docker-compose, air, .env.example). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
36 lines
988 B
Go
36 lines
988 B
Go
// Package logging builds the application's slog logger. Logs go to stderr
|
|
// (readable console in dev, structured JSON otherwise) and, optionally, to a
|
|
// file. There is no database sink — see AGENT.md §7.
|
|
package logging
|
|
|
|
import (
|
|
"io"
|
|
"log/slog"
|
|
"os"
|
|
)
|
|
|
|
// Setup returns a configured *slog.Logger and, if a file sink was opened, an
|
|
// io.Closer to flush/close it on shutdown (nil when no file sink is used).
|
|
func Setup(dev bool, logFile string) (*slog.Logger, io.Closer, error) {
|
|
var w io.Writer = os.Stderr
|
|
var closer io.Closer
|
|
|
|
if logFile != "" {
|
|
f, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
w = io.MultiWriter(os.Stderr, f)
|
|
closer = f
|
|
}
|
|
|
|
var handler slog.Handler
|
|
if dev {
|
|
handler = slog.NewTextHandler(w, &slog.HandlerOptions{Level: slog.LevelDebug})
|
|
} else {
|
|
handler = slog.NewJSONHandler(w, &slog.HandlerOptions{Level: slog.LevelInfo})
|
|
}
|
|
|
|
return slog.New(handler), closer, nil
|
|
}
|