diff --git a/internal/log/api.go b/internal/log/api.go index d721f47fdd..bb6bfba2e9 100644 --- a/internal/log/api.go +++ b/internal/log/api.go @@ -66,5 +66,7 @@ func ContextWithLogger(ctx context.Context, logger *Logger) context.Context { } func ContextWithNewDefaultLogger(ctx context.Context) context.Context { - return ContextWithLogger(ctx, Configure(os.Stderr, Config{Level: Debug})) + // Matches LOG_COLOR in log.Config. This is a special case for the default logger in testing. + color := os.Getenv("LOG_COLOR") != "" + return ContextWithLogger(ctx, Configure(os.Stderr, Config{Level: Debug, Color: color})) } diff --git a/internal/log/configure.go b/internal/log/configure.go index c6534e6342..94e6c7950a 100644 --- a/internal/log/configure.go +++ b/internal/log/configure.go @@ -9,6 +9,7 @@ type Config struct { Level Level `help:"Log level." default:"info" env:"LOG_LEVEL"` JSON bool `help:"Log in JSON format." env:"LOG_JSON"` Timestamps bool `help:"Include timestamps in text logs." env:"LOG_TIMESTAMPS"` + Color bool `help:"Enable colored output regardless of TTY." env:"LOG_COLOR"` } // Configure returns a new logger based on the config. @@ -17,7 +18,7 @@ func Configure(w io.Writer, cfg Config) *Logger { if cfg.JSON { sink = newJSONSink(w) } else { - sink = newPlainSink(w, cfg.Timestamps) + sink = newPlainSink(w, cfg.Timestamps, cfg.Color) } return New(cfg.Level, sink) } diff --git a/internal/log/plain.go b/internal/log/plain.go index 02881ec353..0bbabda99e 100644 --- a/internal/log/plain.go +++ b/internal/log/plain.go @@ -19,9 +19,11 @@ var colours = map[Level]string{ var _ Sink = (*plainSink)(nil) -func newPlainSink(w io.Writer, logTime bool) *plainSink { +func newPlainSink(w io.Writer, logTime bool, alwaysColor bool) *plainSink { var isaTTY bool - if f, ok := w.(*os.File); ok { + if alwaysColor { + isaTTY = true + } else if f, ok := w.(*os.File); ok { isaTTY = isatty.IsTerminal(f.Fd()) } return &plainSink{