on main help sign in
fix(server): log to stderr if it's a terminal
commitbc383d98359b53b291eb2154289e098e1cfe15a3 authorAyman Bagabas <ayman.bagabas@gmail.com> dateSun 22 Mar 2026, 10:53 (7 months ago) parent72251dd
2 files changed+27−5
internal/cmd/server.go+7−1 internal/log/log.go+20−4
internal/cmd/server.go+7−1
@@ -13,6 +13,7 @@ import (
1313 "github.com/charmbracelet/crush/internal/config"
1414 crushlog "github.com/charmbracelet/crush/internal/log"
1515 "github.com/charmbracelet/crush/internal/server"
16+ "github.com/charmbracelet/x/term"
1617 "github.com/spf13/cobra"
1718)
1819
@@ -42,7 +43,12 @@ var serverCmd = &cobra.Command{
4243 }
4344
4445 logFile := filepath.Join(config.GlobalCacheDir(), "server-"+safeNameRegexp.ReplaceAllString(serverHost, "_"), "crush.log")
45− crushlog.Setup(logFile, debug)
46+
47+ if term.IsTerminal(os.Stderr.Fd()) {
48+ crushlog.Setup(logFile, debug, os.Stderr)
49+ } else {
50+ crushlog.Setup(logFile, debug)
51+ }
4652
4753 hostURL, err := server.ParseHostURL(serverHost)
4854 if err != nil {
internal/log/log.go+20−4
@@ -2,6 +2,7 @@ package log
22
33import (
44 "fmt"
5+ "io"
56 "log/slog"
67 "os"
78 "runtime/debug"
@@ -10,6 +11,7 @@ import (
1011 "time"
1112
1213 "github.com/charmbracelet/crush/internal/event"
14+ "github.com/charmbracelet/x/term"
1315 "gopkg.in/natefinch/lumberjack.v2"
1416)
1517
@@ -18,7 +20,7 @@ var (
1820 initialized atomic.Bool
1921)
2022
21−func Setup(logFile string, debug bool) {
23+func Setup(logFile string, debug bool, ws ...io.Writer) {
2224 initOnce.Do(func() {
2325 logRotator := &lumberjack.Logger{
2426 Filename: logFile,
@@ -33,12 +35,26 @@ func Setup(logFile string, debug bool) {
3335 level = slog.LevelDebug
3436 }
3537
36− logger := slog.NewJSONHandler(logRotator, &slog.HandlerOptions{
38+ opts := &slog.HandlerOptions{
3739 Level: level,
3840 AddSource: true,
39− })
41+ }
42+
43+ var handlers []slog.Handler
44+ handlers = append(handlers, slog.NewJSONHandler(logRotator, opts))
45+
46+ for _, w := range ws {
47+ if w == nil {
48+ continue
49+ }
50+ if f, ok := w.(term.File); ok && term.IsTerminal(f.Fd()) {
51+ handlers = append(handlers, slog.NewTextHandler(w, opts))
52+ } else {
53+ handlers = append(handlers, slog.NewJSONHandler(w, opts))
54+ }
55+ }
4056
41− slog.SetDefault(slog.New(logger))
57+ slog.SetDefault(slog.New(slog.NewMultiHandler(handlers...)))
4258 initialized.Store(true)
4359 })
4460}