Skip to content

Commit 58d11e4

Browse files
committed
Enable ANSI color log output only when log-level >= 3
Previously ANSI color codes were always emitted in log output. This change makes color output opt-in: only when --log-level=3 or higher is specified will the console writer use ANSI colors. At default levels (0/1/2), logs are plain text for cleaner output in non-terminal environments (e.g. kubectl logs, log aggregators). Changes: - Add enableColor flag (logLevel >= 3) in ZapCustomLogger - Set ConsoleWriter.NoColor based on the flag - Guard FormatLevel and FormatCaller color wrapping - Widen logLevel switch to handle >= 2 for TraceLevel - Add TestGetLogLevel and TestAnsiColorOnlyEnabledAtLevel3 tests Change-Id: Iae257ccb447b63d2a2f40c28b5096d53f1527ea2
1 parent 0334455 commit 58d11e4

File tree

2 files changed

+106
-1
lines changed

2 files changed

+106
-1
lines changed

pkg/logger/logger.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,18 @@ func getLogLevel(cfDebug bool, cfLogLevel int) int {
105105
// ZapCustomLogger creates a CustomLogger with both logr.Logger and zerolog.Logger using the same configuration as ZapLogger
106106
func ZapCustomLogger(cfDebug bool, cfLogLevel int) CustomLogger {
107107
logLevel := getLogLevel(cfDebug, cfLogLevel)
108+
enableColor := logLevel >= 3
108109

109110
// Create the custom console writer with zap-like formatting
110111
consoleWriter := zerolog.ConsoleWriter{
111112
Out: os.Stdout,
113+
NoColor: !enableColor,
112114
TimeFormat: logTmFmtWithMS,
113115
FormatLevel: func(i interface{}) string {
114116
levelStr := strings.ToUpper(fmt.Sprintf("%s", i))
117+
if !enableColor {
118+
return levelStr
119+
}
115120
switch levelStr {
116121
case "TRACE":
117122
return colorWhite + levelStr + colorReset
@@ -140,6 +145,9 @@ func ZapCustomLogger(cfDebug bool, cfLogLevel int) CustomLogger {
140145
if idx := strings.LastIndex(caller, "/"); idx >= 0 {
141146
caller = caller[idx+1:]
142147
}
148+
if !enableColor {
149+
return caller
150+
}
143151
return colorYellow + caller + colorReset
144152
},
145153
FormatFieldName: func(i interface{}) string {
@@ -154,7 +162,7 @@ func ZapCustomLogger(cfDebug bool, cfLogLevel int) CustomLogger {
154162
// Set the log level based on the calculated level
155163
var zeroLogLevel zerolog.Level
156164
switch {
157-
case logLevel == 2:
165+
case logLevel >= 2:
158166
zeroLogLevel = zerolog.TraceLevel
159167
case logLevel == 1:
160168
zeroLogLevel = zerolog.DebugLevel

pkg/logger/logger_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
package logger
22

33
import (
4+
"bytes"
5+
"fmt"
6+
"strings"
47
"testing"
58
"time"
9+
10+
"github.com/rs/zerolog"
611
)
712

813
func TestZapLoggerLevels(t *testing.T) {
@@ -79,3 +84,95 @@ func TestCustomLogger(t *testing.T) {
7984

8085
t.Log("CustomLogger test completed - verify all log levels are displayed with proper formatting and colors")
8186
}
87+
88+
func TestGetLogLevel(t *testing.T) {
89+
testCases := []struct {
90+
name string
91+
debug bool
92+
logLevel int
93+
expected int
94+
}{
95+
{"default", false, 0, 0},
96+
{"debug_flag_only", true, 0, 2},
97+
{"log_level_1", false, 1, 1},
98+
{"log_level_3", false, 3, 3},
99+
{"debug_with_higher_level", true, 3, 3},
100+
{"debug_with_lower_level", true, 1, 2},
101+
}
102+
for _, tc := range testCases {
103+
t.Run(tc.name, func(t *testing.T) {
104+
got := getLogLevel(tc.debug, tc.logLevel)
105+
if got != tc.expected {
106+
t.Errorf("getLogLevel(%v, %d) = %d, want %d", tc.debug, tc.logLevel, got, tc.expected)
107+
}
108+
})
109+
}
110+
}
111+
112+
func TestAnsiColorOnlyEnabledAtLevel3(t *testing.T) {
113+
// Helper: create a console writer via the same logic as ZapCustomLogger,
114+
// but write to a buffer so we can inspect the output.
115+
buildWriter := func(logLevel int) (*bytes.Buffer, zerolog.Logger) {
116+
enableColor := logLevel >= 3
117+
buf := &bytes.Buffer{}
118+
cw := zerolog.ConsoleWriter{
119+
Out: buf,
120+
NoColor: !enableColor,
121+
TimeFormat: logTmFmtWithMS,
122+
FormatLevel: func(i interface{}) string {
123+
levelStr := strings.ToUpper(fmt.Sprintf("%s", i))
124+
if !enableColor {
125+
return levelStr
126+
}
127+
switch levelStr {
128+
case "INFO":
129+
return colorGreen + levelStr + colorReset
130+
case "WARN":
131+
return colorMagenta + levelStr + colorReset
132+
case "ERROR":
133+
return colorBrightRed + levelStr + colorReset
134+
default:
135+
return levelStr
136+
}
137+
},
138+
}
139+
l := zerolog.New(cw).Level(zerolog.InfoLevel)
140+
return buf, l
141+
}
142+
143+
t.Run("level_0_no_color", func(t *testing.T) {
144+
buf, l := buildWriter(0)
145+
l.Info().Msg("hello")
146+
output := buf.String()
147+
if strings.Contains(output, "\033[") {
148+
t.Errorf("log-level=0 should not contain ANSI codes, got: %q", output)
149+
}
150+
})
151+
152+
t.Run("level_2_no_color", func(t *testing.T) {
153+
buf, l := buildWriter(2)
154+
l.Info().Msg("hello")
155+
output := buf.String()
156+
if strings.Contains(output, "\033[") {
157+
t.Errorf("log-level=2 should not contain ANSI codes, got: %q", output)
158+
}
159+
})
160+
161+
t.Run("level_3_has_color", func(t *testing.T) {
162+
buf, l := buildWriter(3)
163+
l.Info().Msg("hello")
164+
output := buf.String()
165+
if !strings.Contains(output, "\033[") {
166+
t.Errorf("log-level=3 should contain ANSI codes, got: %q", output)
167+
}
168+
})
169+
170+
t.Run("level_4_has_color", func(t *testing.T) {
171+
buf, l := buildWriter(4)
172+
l.Info().Msg("hello")
173+
output := buf.String()
174+
if !strings.Contains(output, "\033[") {
175+
t.Errorf("log-level=4 should contain ANSI codes, got: %q", output)
176+
}
177+
})
178+
}

0 commit comments

Comments
 (0)