diff --git a/embed/config.go b/embed/config.go index 7ac19adf3..73659e3aa 100644 --- a/embed/config.go +++ b/embed/config.go @@ -16,6 +16,7 @@ package embed import ( "crypto/tls" + "errors" "fmt" "io/ioutil" "net" @@ -23,6 +24,7 @@ import ( "net/url" "os" "path/filepath" + "reflect" "sort" "strings" "sync" @@ -265,13 +267,17 @@ type Config struct { // WARN: "capnslog" is being deprecated in v3.5. Logger string `json:"logger"` + // DeprecatedLogOutput is to be deprecated in v3.5. + // Just here for safe migration in v3.4. + DeprecatedLogOutput []string `json:"log-output"` + // LogOutputs is either: // - "default" as os.Stderr, // - "stderr" as os.Stderr, // - "stdout" as os.Stdout, // - file path to append server logs to. // It can be multiple when "Logger" is zap. - LogOutputs []string `json:"log-output"` + LogOutputs []string `json:"log-outputs"` // Debug is true, to enable debug level logging. Debug bool `json:"debug"` @@ -368,12 +374,13 @@ func NewConfig() *Config { PreVote: false, // TODO: enable by default in v3.5 - loggerMu: new(sync.RWMutex), - logger: nil, - Logger: "capnslog", - LogOutputs: []string{DefaultLogOutput}, - Debug: false, - LogPkgLevels: "", + loggerMu: new(sync.RWMutex), + logger: nil, + Logger: "capnslog", + DeprecatedLogOutput: []string{DefaultLogOutput}, + LogOutputs: []string{DefaultLogOutput}, + Debug: false, + LogPkgLevels: "", } cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name) return cfg @@ -406,6 +413,34 @@ var grpcLogOnce = new(sync.Once) // setupLogging initializes etcd logging. // Must be called after flag parsing or finishing configuring embed.Config. func (cfg *Config) setupLogging() error { + // handle "DeprecatedLogOutput" in v3.4 + // TODO: remove "DeprecatedLogOutput" in v3.5 + len1 := len(cfg.DeprecatedLogOutput) + len2 := len(cfg.LogOutputs) + if len1 != len2 { + switch { + case len1 > len2: // deprecate "log-output" flag is used + fmt.Fprintln(os.Stderr, "'--log-output' flag has been deprecated! Please use '--log-outputs'!") + cfg.LogOutputs = cfg.DeprecatedLogOutput + case len1 < len2: // "--log-outputs" flag has been set with multiple writers + cfg.DeprecatedLogOutput = []string{} + } + } else { + if len1 > 1 { + return errors.New("both '--log-output' and '--log-outputs' are set; only set '--log-outputs'") + } + if len1 < 1 { + return errors.New("either '--log-output' or '--log-outputs' flag must be set") + } + if reflect.DeepEqual(cfg.DeprecatedLogOutput, cfg.LogOutputs) && cfg.DeprecatedLogOutput[0] != DefaultLogOutput { + return fmt.Errorf("'--log-output=%q' and '--log-outputs=%q' are incompatible; only set --log-outputs", cfg.DeprecatedLogOutput, cfg.LogOutputs) + } + if !reflect.DeepEqual(cfg.DeprecatedLogOutput, []string{DefaultLogOutput}) { + fmt.Fprintf(os.Stderr, "Deprecated '--log-output' flag is set to %q\n", cfg.DeprecatedLogOutput) + fmt.Fprintln(os.Stderr, "Please use '--log-outputs' flag") + } + } + switch cfg.Logger { case "capnslog": // TODO: deprecate this in v3.5 cfg.ClientTLSInfo.HandshakeFailure = logTLSHandshakeFailure diff --git a/etcdmain/config.go b/etcdmain/config.go index 8d152a085..5c2bd7c04 100644 --- a/etcdmain/config.go +++ b/etcdmain/config.go @@ -218,7 +218,8 @@ func newConfig() *config { // logging fs.StringVar(&cfg.ec.Logger, "logger", "capnslog", "Specify 'zap' for structured logging or 'capnslog'.") - fs.Var(flags.NewUniqueStringsValue(embed.DefaultLogOutput), "log-output", "Specify 'stdout' or 'stderr' to skip journald logging even when running under systemd, or list of comma separated output targets.") + fs.Var(flags.NewUniqueStringsValue(embed.DefaultLogOutput), "log-output", "DEPRECATED: use '--log-outputs'.") + 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.BoolVar(&cfg.ec.Debug, "debug", false, "Enable debug-level logging for etcd.") fs.StringVar(&cfg.ec.LogPkgLevels, "log-package-levels", "", "(To be deprecated) Specify a particular log level for each etcd package (eg: 'etcdmain=CRITICAL,etcdserver=DEBUG').") @@ -306,13 +307,23 @@ func (cfg *config) configFromCmdLine() error { cfg.ec.CORS = flags.UniqueURLsMapFromFlag(cfg.cf.flagSet, "cors") cfg.ec.HostWhitelist = flags.UniqueStringsMapFromFlag(cfg.cf.flagSet, "host-whitelist") - outputs := flags.UniqueStringsMapFromFlag(cfg.cf.flagSet, "log-output") - oss := make([]string, 0, len(outputs)) - for v := range outputs { - oss = append(oss, v) + + // TODO: remove this in v3.5 + output := flags.UniqueStringsMapFromFlag(cfg.cf.flagSet, "log-output") + oss1 := make([]string, 0, len(output)) + for v := range output { + oss1 = append(oss1, v) } - sort.Strings(oss) - cfg.ec.LogOutputs = oss + sort.Strings(oss1) + cfg.ec.DeprecatedLogOutput = oss1 + + outputs := flags.UniqueStringsMapFromFlag(cfg.cf.flagSet, "log-outputs") + oss2 := make([]string, 0, len(outputs)) + for v := range outputs { + oss2 = append(oss2, v) + } + sort.Strings(oss2) + cfg.ec.LogOutputs = oss2 cfg.ec.ClusterState = cfg.cf.clusterState.String() cfg.cp.Fallback = cfg.cf.fallback.String() diff --git a/etcdmain/help.go b/etcdmain/help.go index 95cff0b8a..d9521fadb 100644 --- a/etcdmain/help.go +++ b/etcdmain/help.go @@ -160,7 +160,7 @@ Profiling: Logging: --logger 'capnslog' Specify 'zap' for structured logging or 'capnslog'. - --log-output 'default' + --log-outputs 'default' Specify 'stdout' or 'stderr' to skip journald logging even when running under systemd, or list of comma separated output targets. --debug 'false' Enable debug-level logging for etcd.