summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-06-20 09:54:37 +0300
committerPaul Buetow <paul@buetow.org>2025-06-20 09:54:37 +0300
commitb0a1e7928d5147d2a9fe0df710bf7c75a777e0d0 (patch)
tree8e90cac2bcf9691a1efd8d8f004e4dc119a9ac76
parentecc66fcf9241c429cf2378f09793ecef3a00b098 (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.go10
-rw-r--r--internal/color/brush/brush.go12
-rw-r--r--internal/io/dlog/dlog.go3
-rw-r--r--internal/server/handlers/colorwriter.go43
-rw-r--r--internal/server/handlers/readcommand.go8
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)