package logging import ( "io" "log/slog" "os" "path/filepath" ) // New creates the process logger. Callers provide the sink so tests and the // command entry point do not need to share global logging state. func New(w io.Writer) *slog.Logger { if w == nil { w = io.Discard } return slog.New(slog.NewJSONHandler(w, &slog.HandlerOptions{Level: slog.LevelInfo})) } // OpenFile creates an append-only local diagnostic log in the configured // directory. It never falls back to cwd, so a bad configured directory stays // visible to the caller instead of scattering logs beside a shortcut. func OpenFile(directory string) (*slog.Logger, io.Closer, error) { if err := os.MkdirAll(directory, 0o700); err != nil { return nil, nil, err } file, err := os.OpenFile(filepath.Join(directory, "chub.log"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o600) if err != nil { return nil, nil, err } return New(file), file, nil }