From 493885979b0096dc3879dd04047a0a329df05fee Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 14 May 2021 12:10:15 +0200 Subject: [PATCH] etcd: Support configuring zap console log format with --log-format flag Console format is much easier to read during development when compared to json. --- server/embed/config.go | 8 +++++ server/embed/config_logging.go | 5 ++- server/embed/config_test.go | 45 +++++++++++++++++++++++++++ server/etcdmain/config.go | 1 + server/etcdmain/help.go | 2 ++ tests/integration/embed/embed_test.go | 2 ++ tools/etcd-dump-metrics/etcd.go | 1 + 7 files changed, 63 insertions(+), 1 deletion(-) diff --git a/server/embed/config.go b/server/embed/config.go index f50ff1663575..7cc1f10a7fab 100644 --- a/server/embed/config.go +++ b/server/embed/config.go @@ -350,6 +350,8 @@ type Config struct { // Logger is logger options: currently only supports "zap". // "capnslog" is removed in v3.5. Logger string `json:"logger"` + // LogFormat configures format of logs. Only supports json, console. Default 'json'. + LogFormat string `json:"log-format"` // LogLevel configures log level. Only supports debug, info, warn, error, panic, or fatal. Default 'info'. LogLevel string `json:"log-level"` // LogOutputs is either: @@ -485,6 +487,7 @@ func NewConfig() *Config { loggerMu: new(sync.RWMutex), logger: nil, Logger: "zap", + LogFormat: "json", LogOutputs: []string{DefaultLogOutput}, LogLevel: logutil.DefaultLogLevel, EnableLogRotation: false, @@ -619,6 +622,11 @@ func updateCipherSuites(tls *transport.TLSInfo, ss []string) error { // Validate ensures that '*embed.Config' fields are properly configured. func (cfg *Config) Validate() error { + switch cfg.LogFormat { + case "json", "console": + default: + return fmt.Errorf("--log-format=%s is not supported", cfg.LogFormat) + } if err := cfg.setupLogging(); err != nil { return err } diff --git a/server/embed/config_logging.go b/server/embed/config_logging.go index 261949ef0996..8798623ae213 100644 --- a/server/embed/config_logging.go +++ b/server/embed/config_logging.go @@ -98,7 +98,7 @@ func (cfg *Config) setupLogging() error { if !isJournal { copied := logutil.DefaultZapLoggerConfig - copied.OutputPaths = outputPaths + copied.Encoding = cfg.LogFormat copied.ErrorOutputPaths = errOutputPaths copied = logutil.MergeOutputPaths(copied) copied.Level = zap.NewAtomicLevelAt(logutil.ConvertToZapLevel(cfg.LogLevel)) @@ -125,6 +125,9 @@ func (cfg *Config) setupLogging() error { } } } + if cfg.LogFormat != logutil.DefaultLogLevel { + return fmt.Errorf("--log-format=%q with systemd/journal is not supported", cfg.LogFormat) + } // use stderr as fallback syncer, lerr := getJournalWriteSyncer() diff --git a/server/embed/config_test.go b/server/embed/config_test.go index b86d0d6c2469..c5be482c0750 100644 --- a/server/embed/config_test.go +++ b/server/embed/config_test.go @@ -364,3 +364,48 @@ func TestLogRotation(t *testing.T) { }) } } + +func TestLogFormat(t *testing.T) { + tests := []struct { + name string + LogFormat string + wantErr bool + wantErrMsg error + }{ + { + name: "default", + }, + { + name: "json", + LogFormat: "json", + }, + { + name: "console", + LogFormat: "console", + }, + { + name: "unsupported", + LogFormat: "xml", + wantErr: true, + wantErrMsg: errors.New("--log-format=xml is not supported"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := NewConfig() + if tt.LogFormat != "" { + cfg.LogFormat = tt.LogFormat + } + err := cfg.Validate() + if err != nil && !tt.wantErr { + t.Errorf("test %q, unexpected error %v", tt.name, err) + } + if err != nil && tt.wantErr && tt.wantErrMsg.Error() != err.Error() { + t.Errorf("test %q, expected error: %+v, got: %+v", tt.name, tt.wantErrMsg, err) + } + if err == nil && tt.wantErr { + t.Errorf("test %q, expected error, got nil", tt.name) + } + }) + } +} diff --git a/server/etcdmain/config.go b/server/etcdmain/config.go index fefb230f2150..7638109a5f11 100644 --- a/server/etcdmain/config.go +++ b/server/etcdmain/config.go @@ -234,6 +234,7 @@ func newConfig() *config { // logging fs.StringVar(&cfg.ec.Logger, "logger", "zap", "Currently only supports 'zap' for structured logging.") + fs.StringVar(&cfg.ec.LogFormat, "log-format", "json", "Configures format of logs. Only supports json, console. Default 'json'.") fs.Var(flags.NewUniqueStringsValue(embed.DefaultLogOutput), "log-outputs", "Specify 'stdout' or 'stderr' to skip journald logging even when running under systemd, or list of comma separated output targets.") fs.StringVar(&cfg.ec.LogLevel, "log-level", logutil.DefaultLogLevel, "Configures log level. Only supports debug, info, warn, error, panic, or fatal. Default 'info'.") fs.BoolVar(&cfg.ec.EnableLogRotation, "enable-log-rotation", false, "Enable log rotation of a single log-outputs file target.") diff --git a/server/etcdmain/help.go b/server/etcdmain/help.go index b63282e8950e..38e3fd84f1c8 100644 --- a/server/etcdmain/help.go +++ b/server/etcdmain/help.go @@ -184,6 +184,8 @@ Profiling and Monitoring: Logging: --logger 'zap' Currently only supports 'zap' for structured logging. + --log-format 'json' + LogFormat configures format of logs. Only supports json, console. --log-outputs 'default' Specify 'stdout' or 'stderr' to skip journald logging even when running under systemd, or list of comma separated output targets. --log-level 'info' diff --git a/tests/integration/embed/embed_test.go b/tests/integration/embed/embed_test.go index c04bf97c9615..da09f149f3f7 100644 --- a/tests/integration/embed/embed_test.go +++ b/tests/integration/embed/embed_test.go @@ -73,6 +73,7 @@ func TestEmbedEtcd(t *testing.T) { for i := range tests { tests[i].cfg = *embed.NewConfig() tests[i].cfg.Logger = "zap" + tests[i].cfg.LogFormat = "json" tests[i].cfg.LogOutputs = []string{"/dev/null"} } @@ -199,6 +200,7 @@ func newEmbedURLs(secure bool, n int) (urls []url.URL) { func setupEmbedCfg(cfg *embed.Config, curls []url.URL, purls []url.URL) { cfg.Logger = "zap" + cfg.LogFormat = "json" cfg.LogOutputs = []string{"/dev/null"} cfg.ClusterState = "new" diff --git a/tools/etcd-dump-metrics/etcd.go b/tools/etcd-dump-metrics/etcd.go index 7997e2832378..92fe41b29978 100644 --- a/tools/etcd-dump-metrics/etcd.go +++ b/tools/etcd-dump-metrics/etcd.go @@ -40,6 +40,7 @@ func newEmbedURLs(n int) (urls []url.URL) { func setupEmbedCfg(cfg *embed.Config, curls, purls, ics []url.URL) { cfg.Logger = "zap" + cfg.LogFormat = "json" cfg.LogOutputs = []string{"/dev/null"} // []string{"stderr"} to enable server logging