Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func init() {
os.Exit(1)
}

log = logger.ZapCustomLogger(cf.DefaultConfig.Debug, config.LogLevel)
log = logger.ZapCustomLogger(cf.DefaultConfig.Debug, config.LogLevel, config.LogColor)
logger.Log = log
// Set the controller-runtime logger to prevent the warning about log.SetLogger(...) never being called
logf.SetLogger(log.Logger)
Expand Down
5 changes: 3 additions & 2 deletions cmd_clean/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func main() {
flag.StringVar(&envoyHost, "envoyhost", "", "envoy host")
flag.IntVar(&envoyPort, "envoyport", 0, "envoy port")
flag.IntVar(&config.LogLevel, "log-level", 2, "Use zap-core log system.")
flag.BoolVar(&config.LogColor, "log-color", false, "Enable ANSI color in log output.")
flag.Parse()

cf = config.NewNSXOpertorConfig()
Expand All @@ -80,10 +81,10 @@ func main() {

ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
defer cancel()
log = logger.ZapCustomLogger(cf.DefaultConfig.Debug, config.LogLevel)
log = logger.ZapCustomLogger(cf.DefaultConfig.Debug, config.LogLevel, config.LogColor)
logger.Log = log
logf.SetLogger(log.Logger)
err := clean.Clean(ctx, cf, &log.Logger, cf.DefaultConfig.Debug, config.LogLevel)
err := clean.Clean(ctx, cf, &log.Logger, cf.DefaultConfig.Debug, config.LogLevel, config.LogColor)
if err != nil {
log.Error(err, "Failed to clean nsx resources")
os.Exit(1)
Expand Down
4 changes: 2 additions & 2 deletions pkg/clean/clean.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ var Backoff = wait.Backoff{
// GetNSXClientFailed indicate that could not retrieve nsx client to perform cleanup operation
// InitCleanupServiceFailed indicate that error happened when trying to initialize cleanup service
// CleanupResourceFailed indicate that the cleanup operation failed at some services, the detailed will in the service logs
func Clean(ctx context.Context, cf *config.NSXOperatorConfig, log *logr.Logger, debug bool, logLevel int) error {
func Clean(ctx context.Context, cf *config.NSXOperatorConfig, log *logr.Logger, debug bool, logLevel int, logColor bool) error {
// Clean needs to support many instances which each have its own logger
if log == nil {
logg := logger.ZapCustomLogger(debug, logLevel).Logger
logg := logger.ZapCustomLogger(debug, logLevel, logColor).Logger
log = &logg
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/clean/clean_lb_infra_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,7 @@ func convertToResponse(t *testing.T, resources []interface{}, bindingType bindin
}

func prepareCleaner() *LBInfraCleaner {
log := logger.ZapCustomLogger(false, 0).Logger
log := logger.ZapCustomLogger(false, 0, false).Logger
return &LBInfraCleaner{
Service: common.Service{
NSXClient: &nsx.Client{
Expand Down
8 changes: 4 additions & 4 deletions pkg/clean/clean_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestClean_ValidationFailed(t *testing.T) {

defer patches.Reset()

err := Clean(ctx, cf, &log, debug, logLevel)
err := Clean(ctx, cf, &log, debug, logLevel, false)
assert.Error(t, err)
assert.Contains(t, err.Error(), "validation failed")
}
Expand All @@ -61,7 +61,7 @@ func TestClean_GetClientFailed(t *testing.T) {
return nil
})

err := Clean(ctx, cf, &log, debug, logLevel)
err := Clean(ctx, cf, &log, debug, logLevel, false)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to get nsx client")
}
Expand All @@ -85,7 +85,7 @@ func TestClean_InitError(t *testing.T) {
return nil, errors.New("init cleanup service failed")
})

err := Clean(ctx, cf, &log, debug, logLevel)
err := Clean(ctx, cf, &log, debug, logLevel, false)
assert.Error(t, err)
assert.Contains(t, err.Error(), "init cleanup service failed")
}
Expand Down Expand Up @@ -122,7 +122,7 @@ func TestClean_Cleanup(t *testing.T) {
return nil
})

err := Clean(ctx, cf, nil, debug, logLevel)
err := Clean(ctx, cf, nil, debug, logLevel, false)
assert.Nil(t, err)
assert.True(t, clean.vpcPreCleanupCalled)
assert.True(t, clean.vpcChildrenCleanupCalled)
Expand Down
2 changes: 2 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const (

var (
LogLevel int
LogColor bool
ProbeAddr, MetricsAddr string
WebhookServerPort int
configFilePath = ""
Expand Down Expand Up @@ -165,6 +166,7 @@ func AddFlags() {
flag.StringVar(&ProbeAddr, "health-probe-bind-address", ":8384", "The address the probe endpoint binds to.")
flag.StringVar(&MetricsAddr, "metrics-bind-address", ":8093", "The address the metrics endpoint binds to.")
flag.IntVar(&LogLevel, "log-level", 0, "Use zap-core log system.")
flag.BoolVar(&LogColor, "log-color", false, "Enable ANSI color in log output.")
flag.IntVar(&WebhookServerPort, "webhook-server-port", defaultWebhookPort, "Port number to expose the controller webhook server")
flag.Parse()
}
Expand Down
11 changes: 9 additions & 2 deletions pkg/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,19 @@ func getLogLevel(cfDebug bool, cfLogLevel int) int {
}

// ZapCustomLogger creates a CustomLogger with both logr.Logger and zerolog.Logger using the same configuration as ZapLogger
func ZapCustomLogger(cfDebug bool, cfLogLevel int) CustomLogger {
func ZapCustomLogger(cfDebug bool, cfLogLevel int, enableColor bool) CustomLogger {
logLevel := getLogLevel(cfDebug, cfLogLevel)

// Create the custom console writer with zap-like formatting
consoleWriter := zerolog.ConsoleWriter{
Out: os.Stdout,
NoColor: !enableColor,
TimeFormat: logTmFmtWithMS,
FormatLevel: func(i interface{}) string {
levelStr := strings.ToUpper(fmt.Sprintf("%s", i))
if !enableColor {
return levelStr
}
switch levelStr {
case "TRACE":
return colorWhite + levelStr + colorReset
Expand Down Expand Up @@ -140,6 +144,9 @@ func ZapCustomLogger(cfDebug bool, cfLogLevel int) CustomLogger {
if idx := strings.LastIndex(caller, "/"); idx >= 0 {
caller = caller[idx+1:]
}
if !enableColor {
return caller
}
return colorYellow + caller + colorReset
},
FormatFieldName: func(i interface{}) string {
Expand All @@ -154,7 +161,7 @@ func ZapCustomLogger(cfDebug bool, cfLogLevel int) CustomLogger {
// Set the log level based on the calculated level
var zeroLogLevel zerolog.Level
switch {
case logLevel == 2:
case logLevel >= 2:
zeroLogLevel = zerolog.TraceLevel
case logLevel == 1:
zeroLogLevel = zerolog.DebugLevel
Expand Down
82 changes: 80 additions & 2 deletions pkg/logger/logger_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package logger

import (
"bytes"
"fmt"
"strings"
"testing"
"time"

"github.com/rs/zerolog"
)

func TestZapLoggerLevels(t *testing.T) {
Expand Down Expand Up @@ -44,7 +49,7 @@ func TestZapLoggerLevels(t *testing.T) {
t.Logf("Testing: %s", tc.description)

// Create logger with specified configuration
logger := ZapCustomLogger(tc.debug, tc.logLevel).Logger
logger := ZapCustomLogger(tc.debug, tc.logLevel, false).Logger

// Test various log levels
logger.Info("This is an info message", "test_case", tc.name, "timestamp", time.Now().Format("15:04:05"))
Expand All @@ -68,7 +73,7 @@ func TestZapLoggerLevels(t *testing.T) {
func TestCustomLogger(t *testing.T) {
t.Log("Testing CustomLogger with all log levels...")
// Test CustomLogger wrapper
customLogger := ZapCustomLogger(true, 2)
customLogger := ZapCustomLogger(true, 2, false)

// Test all five log levels
customLogger.Trace("This is a trace message", "test_case", "trace_test", "timestamp", time.Now().Format("15:04:05"))
Expand All @@ -79,3 +84,76 @@ func TestCustomLogger(t *testing.T) {

t.Log("CustomLogger test completed - verify all log levels are displayed with proper formatting and colors")
}

func TestGetLogLevel(t *testing.T) {
testCases := []struct {
name string
debug bool
logLevel int
expected int
}{
{"default", false, 0, 0},
{"debug_flag_only", true, 0, 2},
{"log_level_1", false, 1, 1},
{"log_level_3", false, 3, 3},
{"debug_with_higher_level", true, 3, 3},
{"debug_with_lower_level", true, 1, 2},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got := getLogLevel(tc.debug, tc.logLevel)
if got != tc.expected {
t.Errorf("getLogLevel(%v, %d) = %d, want %d", tc.debug, tc.logLevel, got, tc.expected)
}
})
}
}

func TestAnsiColorControlledByFlag(t *testing.T) {
// Helper: create a console writer via the same logic as ZapCustomLogger,
// but write to a buffer so we can inspect the output.
buildWriter := func(enableColor bool) (*bytes.Buffer, zerolog.Logger) {
buf := &bytes.Buffer{}
cw := zerolog.ConsoleWriter{
Out: buf,
NoColor: !enableColor,
TimeFormat: logTmFmtWithMS,
FormatLevel: func(i interface{}) string {
levelStr := strings.ToUpper(fmt.Sprintf("%s", i))
if !enableColor {
return levelStr
}
switch levelStr {
case "INFO":
return colorGreen + levelStr + colorReset
case "WARN":
return colorMagenta + levelStr + colorReset
case "ERROR":
return colorBrightRed + levelStr + colorReset
default:
return levelStr
}
},
}
l := zerolog.New(cw).Level(zerolog.InfoLevel)
return buf, l
}

t.Run("color_disabled", func(t *testing.T) {
buf, l := buildWriter(false)
l.Info().Msg("hello")
output := buf.String()
if strings.Contains(output, "\033[") {
t.Errorf("color=false should not contain ANSI codes, got: %q", output)
}
})

t.Run("color_enabled", func(t *testing.T) {
buf, l := buildWriter(true)
l.Info().Msg("hello")
output := buf.String()
if !strings.Contains(output, "\033[") {
t.Errorf("color=true should contain ANSI codes, got: %q", output)
}
})
}
2 changes: 1 addition & 1 deletion pkg/nsx/services/node/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func TestNodeService_GetNodeByName(t *testing.T) {
}

func TestNodeService_SyncNodeStore(t *testing.T) {
logf.SetLogger(logger.ZapCustomLogger(false, 0).Logger)
logf.SetLogger(logger.ZapCustomLogger(false, 0, false).Logger)
service := createMockNodeService()
nodeName := "test-node"
// Test case: Node not found
Expand Down
1 change: 1 addition & 0 deletions test/e2e/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ type TestOptions struct {
logsExportOnSuccess bool
debugLog bool
logLevel int
logColor bool
}

var testOptions TestOptions
Expand Down
3 changes: 2 additions & 1 deletion test/e2e/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,10 @@ func testMain(m *testing.M) int {
flag.StringVar(&testOptions.vcPassword, "vc-password", "", "The password used by the user when requesting vCenter API session")
flag.BoolVar(&testOptions.debugLog, "debug", false, "")
flag.IntVar(&testOptions.logLevel, "log-level", 0, "")
flag.BoolVar(&testOptions.logColor, "log-color", false, "Enable ANSI color in log output.")
flag.Parse()

log = logger.ZapCustomLogger(testOptions.debugLog, testOptions.logLevel)
log = logger.ZapCustomLogger(testOptions.debugLog, testOptions.logLevel, testOptions.logColor)
logger.Log = log
// Set the controller-runtime logger to prevent the warning about log.SetLogger(...) never being called
logf.SetLogger(log.Logger)
Expand Down
Loading