diff options
| author | Paul Buetow <paul@buetow.org> | 2025-06-20 09:54:37 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-06-20 09:54:37 +0300 |
| commit | b0a1e7928d5147d2a9fe0df710bf7c75a777e0d0 (patch) | |
| tree | 8e90cac2bcf9691a1efd8d8f004e4dc119a9ac76 | |
| parent | ecc66fcf9241c429cf2378f09793ecef3a00b098 (diff) | |
Fix missing colored output in dcat serverless mode
- In serverless mode, output was written directly to stdout bypassing color processing
- Created ColorWriter wrapper that applies colors before writing to stdout
- Updated brush.Colorfy to also color severity levels (ERROR, WARN, FATAL) in plain text
- Ensured --plain flag still disables colors as expected
- Updated integration tests to use --noColor flag to get predictable output
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
| -rw-r--r-- | integrationtests/dcat_line_endings_test.go | 10 | ||||
| -rw-r--r-- | internal/color/brush/brush.go | 12 | ||||
| -rw-r--r-- | internal/io/dlog/dlog.go | 3 | ||||
| -rw-r--r-- | internal/server/handlers/colorwriter.go | 43 | ||||
| -rw-r--r-- | internal/server/handlers/readcommand.go | 8 |
5 files changed, 62 insertions, 14 deletions
diff --git a/integrationtests/dcat_line_endings_test.go b/integrationtests/dcat_line_endings_test.go index 5484929..cdf99b0 100644 --- a/integrationtests/dcat_line_endings_test.go +++ b/integrationtests/dcat_line_endings_test.go @@ -26,8 +26,8 @@ func TestDCatLineEndings(t *testing.T) { defer os.Remove(testFile) t.Run("Serverless", func(t *testing.T) { - // Run dcat in serverless mode - cmd := exec.Command("../dcat", "--cfg", "none", testFile) + // Run dcat in serverless mode with colors disabled for testing + cmd := exec.Command("../dcat", "--cfg", "none", "--noColor", testFile) output, err := cmd.Output() if err != nil { t.Fatalf("dcat command failed: %v", err) @@ -74,7 +74,7 @@ func TestDCatLineEndings(t *testing.T) { defer os.Remove(testFile3) // Run dcat with multiple files - cmd := exec.Command("../dcat", "--cfg", "none", testFile, testFile2, testFile3) + cmd := exec.Command("../dcat", "--cfg", "none", "--noColor", testFile, testFile2, testFile3) output, err := cmd.Output() if err != nil { t.Fatalf("dcat command failed: %v", err) @@ -96,7 +96,7 @@ func TestDCatLineEndings(t *testing.T) { } defer os.Remove(emptyFile) - cmd := exec.Command("../dcat", "--cfg", "none", emptyFile) + cmd := exec.Command("../dcat", "--cfg", "none", "--noColor", emptyFile) output, err := cmd.Output() if err != nil { t.Fatalf("dcat command failed: %v", err) @@ -119,7 +119,7 @@ func TestDCatLineEndings(t *testing.T) { defer os.Remove(crlfFile) // Run dcat in regular mode - cmd := exec.Command("../dcat", "--cfg", "none", crlfFile) + cmd := exec.Command("../dcat", "--cfg", "none", "--noColor", crlfFile) output, err := cmd.Output() if err != nil { t.Fatalf("dcat command failed: %v", err) diff --git a/internal/color/brush/brush.go b/internal/color/brush/brush.go index 63d63d8..2c89436 100644 --- a/internal/color/brush/brush.go +++ b/internal/color/brush/brush.go @@ -185,10 +185,14 @@ func Colorfy(line string) string { paintServer(sb, line) default: - color.PaintWithAttr(sb, line, - color.FgDefault, - color.BgDefault, - color.AttrNone) + // For lines that don't have protocol prefixes, check for severity levels + if !paintSeverity(sb, line) { + // No severity prefix found, paint with default colors + color.PaintWithAttr(sb, line, + color.FgDefault, + color.BgDefault, + color.AttrNone) + } } return sb.String() } diff --git a/internal/io/dlog/dlog.go b/internal/io/dlog/dlog.go index 044624e..6403f77 100644 --- a/internal/io/dlog/dlog.go +++ b/internal/io/dlog/dlog.go @@ -248,7 +248,8 @@ func (d *DLog) Raw(message string) string { d.logger.Raw(time.Now(), message) return message } - d.logger.RawWithColors(time.Now(), message, brush.Colorfy(message)) + coloredMessage := brush.Colorfy(message) + d.logger.RawWithColors(time.Now(), message, coloredMessage) return message } diff --git a/internal/server/handlers/colorwriter.go b/internal/server/handlers/colorwriter.go new file mode 100644 index 0000000..6e0f1af --- /dev/null +++ b/internal/server/handlers/colorwriter.go @@ -0,0 +1,43 @@ +package handlers + +import ( + "io" + "github.com/mimecast/dtail/internal/color/brush" + "github.com/mimecast/dtail/internal/config" +) + +// ColorWriter wraps an io.Writer and applies colors to output +type ColorWriter struct { + writer io.Writer + noColor bool +} + +// NewColorWriter creates a new ColorWriter +func NewColorWriter(writer io.Writer, noColor bool) *ColorWriter { + return &ColorWriter{ + writer: writer, + noColor: noColor, + } +} + +// Write implements io.Writer, applying colors if enabled +func (cw *ColorWriter) Write(p []byte) (n int, err error) { + if cw.noColor || !config.Client.TermColorsEnable { + // No colors, write as-is + return cw.writer.Write(p) + } + + // Apply colors + coloredStr := brush.Colorfy(string(p)) + coloredBytes := []byte(coloredStr) + + // Write the colored output + _, err = cw.writer.Write(coloredBytes) + if err != nil { + return 0, err + } + + // Return the original byte count to maintain compatibility + // (the caller expects n to match len(p)) + return len(p), nil +}
\ No newline at end of file diff --git a/internal/server/handlers/readcommand.go b/internal/server/handlers/readcommand.go index 616bf31..0a99aaa 100644 --- a/internal/server/handlers/readcommand.go +++ b/internal/server/handlers/readcommand.go @@ -146,8 +146,8 @@ func (r *readCommand) readFiles(ctx context.Context, ltx lcontext.LContext, // Choose output writer based on server mode var output io.Writer if r.server.serverless { - // In serverless mode, write directly to stdout - output = os.Stdout + // In serverless mode, write to stdout with color support + output = NewColorWriter(os.Stdout, r.server.plain) } else { // In client-server mode, write to server handler lines channel output = NewServerHandlerWriter(r.server, r.server.serverMessages, r.server.user) @@ -216,8 +216,8 @@ func (r *readCommand) readStdin(ctx context.Context, ltx lcontext.LContext, re r // Choose output writer based on server mode var output io.Writer if r.server.serverless { - // In serverless mode, write directly to stdout - output = os.Stdout + // In serverless mode, write to stdout with color support + output = NewColorWriter(os.Stdout, r.server.plain) } else { // In client-server mode, write to server handler lines channel output = NewServerHandlerWriter(r.server, r.server.serverMessages, r.server.user) |
