From d61f68c24c66e4a4c0f519eb7c9b1cf32ad32b15 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Thu, 20 Dec 2018 16:11:37 -0500 Subject: [PATCH 01/14] pkg/log/zap: adding helpers for zap logger configuration --- Gopkg.lock | 3 + commands/operator-sdk/cmd/up/local.go | 12 +- pkg/log/zap/factory.go | 100 +++++++++++++++ pkg/log/zap/flags.go | 115 ++++++++++++++++++ .../cmd/ansible-operator/main.go | 4 +- test/helm-operator/cmd/helm-operator/main.go | 8 +- 6 files changed, 235 insertions(+), 7 deletions(-) create mode 100644 pkg/log/zap/factory.go create mode 100644 pkg/log/zap/flags.go diff --git a/Gopkg.lock b/Gopkg.lock index 6db0069214f..2570c56423a 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1423,6 +1423,7 @@ "github.com/coreos/prometheus-operator/pkg/client/versioned/typed/monitoring/v1", "github.com/ghodss/yaml", "github.com/go-logr/logr", + "github.com/go-logr/zapr", "github.com/markbates/inflect", "github.com/martinlindhe/base36", "github.com/pborman/uuid", @@ -1434,6 +1435,8 @@ "github.com/spf13/pflag", "github.com/stretchr/testify/assert", "github.com/stretchr/testify/require", + "go.uber.org/zap", + "go.uber.org/zap/zapcore", "golang.org/x/tools/imports", "gopkg.in/yaml.v2", "k8s.io/api/apps/v1", diff --git a/commands/operator-sdk/cmd/up/local.go b/commands/operator-sdk/cmd/up/local.go index 0a1ebd09a5b..7b789c77c5f 100644 --- a/commands/operator-sdk/cmd/up/local.go +++ b/commands/operator-sdk/cmd/up/local.go @@ -36,6 +36,7 @@ import ( "github.com/operator-framework/operator-sdk/pkg/helm/controller" "github.com/operator-framework/operator-sdk/pkg/helm/release" "github.com/operator-framework/operator-sdk/pkg/k8sutil" + "github.com/operator-framework/operator-sdk/pkg/log/zap" "github.com/operator-framework/operator-sdk/pkg/scaffold" helmScaffold "github.com/operator-framework/operator-sdk/pkg/scaffold/helm" sdkVersion "github.com/operator-framework/operator-sdk/version" @@ -65,8 +66,12 @@ kubernetes cluster using a kubeconfig file. upLocalCmd.Flags().StringVar(&operatorFlags, "operator-flags", "", "The flags that the operator needs. Example: \"--flag1 value1 --flag2=value2\"") upLocalCmd.Flags().StringVar(&namespace, "namespace", "default", "The namespace where the operator watches for changes.") upLocalCmd.Flags().StringVar(&ldFlags, "go-ldflags", "", "Set Go linker options") - if projutil.GetOperatorType() == projutil.OperatorTypeAnsible { + switch projutil.GetOperatorType() { + case projutil.OperatorTypeAnsible: ansibleOperatorFlags = flags.AddTo(upLocalCmd.Flags(), "(ansible operator)") + zapFactory = zap.FactoryForFlags(upLocalCmd.Flags()) + case projutil.OperatorTypeHelm: + zapFactory = zap.FactoryForFlags(upLocalCmd.Flags()) } return upLocalCmd } @@ -76,6 +81,7 @@ var ( operatorFlags string namespace string ldFlags string + zapFactory *zap.Factory ansibleOperatorFlags *flags.AnsibleOperatorFlags ) @@ -155,7 +161,7 @@ func upLocalAnsible() { log.Fatalf("failed to set %s environment variable: (%v)", k8sutil.KubeConfigEnvVar, err) } - logf.SetLogger(logf.ZapLogger(false)) + logf.SetLogger(zapFactory.Logger()) mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{Namespace: namespace}) if err != nil { @@ -195,7 +201,7 @@ func upLocalHelm() { log.Fatalf("failed to set %s environment variable: (%v)", k8sutil.KubeConfigEnvVar, err) } - logf.SetLogger(logf.ZapLogger(false)) + logf.SetLogger(zapFactory.Logger()) printVersion() diff --git a/pkg/log/zap/factory.go b/pkg/log/zap/factory.go new file mode 100644 index 00000000000..e906c629909 --- /dev/null +++ b/pkg/log/zap/factory.go @@ -0,0 +1,100 @@ +// Copyright 2018 The Operator-SDK Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package zap + +import ( + "io" + "os" + "time" + + "github.com/go-logr/zapr" + "github.com/spf13/pflag" + + "github.com/go-logr/logr" + "go.uber.org/zap/zapcore" + logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" + + "go.uber.org/zap" +) + +type Factory struct { + development bool + encoderValue encoderValue + levelValue levelValue + sampleValue sampleValue +} + +func (f Factory) Logger() logr.Logger { + return f.LoggerTo(os.Stderr) +} + +func (f Factory) LoggerTo(destWriter io.Writer) logr.Logger { + sink := zapcore.AddSync(destWriter) + conf := f.getConfig(destWriter) + + conf.encoder = &logf.KubeAwareEncoder{Encoder: conf.encoder, Verbose: conf.level.Level() < 0} + if conf.sample { + conf.opts = append(conf.opts, zap.WrapCore(func(core zapcore.Core) zapcore.Core { + return zapcore.NewSampler(core, time.Second, 100, 100) + })) + } + conf.opts = append(conf.opts, zap.AddCallerSkip(1), zap.ErrorOutput(sink)) + log := zap.New(zapcore.NewCore(conf.encoder, sink, conf.level)) + log = log.WithOptions(conf.opts...) + return zapr.NewLogger(log) +} + +type config struct { + encoder zapcore.Encoder + level zap.AtomicLevel + sample bool + opts []zap.Option +} + +func (f *Factory) getConfig(destWriter io.Writer) config { + var c config + + // Set the defaults depending on the log mode (development vs. production) + if f.development { + c.encoder = consoleEncoder() + c.level = zap.NewAtomicLevelAt(zap.DebugLevel) + c.opts = append(c.opts, zap.Development(), zap.AddStacktrace(zap.ErrorLevel)) + c.sample = false + } else { + c.encoder = jsonEncoder() + c.level = zap.NewAtomicLevelAt(zap.InfoLevel) + c.opts = append(c.opts, zap.AddStacktrace(zap.WarnLevel)) + c.sample = true + } + + // Override the defaults if the flags were set explicitly on the command line + if f.encoderValue.set { + c.encoder = f.encoderValue.encoder + } + if f.levelValue.set { + c.level = zap.NewAtomicLevelAt(f.levelValue.level) + } + if f.sampleValue.set { + c.sample = f.sampleValue.sample + } + + return c +} + +func FactoryForFlags(flagSet *pflag.FlagSet) *Factory { + f := &Factory{} + flagSet.AddFlagSet(f.FlagSet()) + return f +} diff --git a/pkg/log/zap/flags.go b/pkg/log/zap/flags.go new file mode 100644 index 00000000000..61f4af18522 --- /dev/null +++ b/pkg/log/zap/flags.go @@ -0,0 +1,115 @@ +// Copyright 2018 The Operator-SDK Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package zap + +import ( + "fmt" + "strconv" + + "github.com/spf13/pflag" + + "go.uber.org/zap/zapcore" + + "go.uber.org/zap" +) + +func (f *Factory) FlagSet() *pflag.FlagSet { + flagSet := pflag.NewFlagSet("zap", pflag.ExitOnError) + flagSet.BoolVar(&f.development, "zap-devel", false, "Enable zap development mode") + flagSet.Var(&f.encoderValue, "zap-encoder", "Zap log encoding ('json' or 'console')") + flagSet.Var(&f.levelValue, "zap-level", "Zap log level (one of 'debug', 'info', 'warn', 'error', 'dpanic', 'panic', 'fatal')") + flagSet.Var(&f.sampleValue, "zap-sample", "Enable zap log sampling") + return flagSet +} + +type encoderValue struct { + set bool + encoder zapcore.Encoder + str string +} + +func (v *encoderValue) Set(e string) error { + v.set = true + switch e { + case "json": + v.encoder = jsonEncoder() + case "console": + v.encoder = consoleEncoder() + default: + return fmt.Errorf("unknown encoder \"%s\"", e) + } + v.str = e + return nil +} + +func (v encoderValue) String() string { + return v.str +} + +func (v encoderValue) Type() string { + return "encoder" +} + +func jsonEncoder() zapcore.Encoder { + encoderConfig := zap.NewProductionEncoderConfig() + return zapcore.NewJSONEncoder(encoderConfig) +} + +func consoleEncoder() zapcore.Encoder { + encoderConfig := zap.NewDevelopmentEncoderConfig() + return zapcore.NewConsoleEncoder(encoderConfig) +} + +type levelValue struct { + set bool + level zapcore.Level +} + +func (v *levelValue) Set(l string) error { + v.set = true + return v.level.Set(l) +} + +func (v levelValue) String() string { + return v.level.String() +} + +func (v *sampleValue) Set(s string) error { + var err error + v.set = true + v.sample, err = strconv.ParseBool(s) + return err +} + +func (v levelValue) Type() string { + return "level" +} + +type sampleValue struct { + set bool + sample bool +} + +func (v sampleValue) String() string { + return strconv.FormatBool(v.sample) +} + +func (v sampleValue) IsBoolFlag() bool { + return true +} + +func (v sampleValue) Type() string { + return "sample" +} diff --git a/test/ansible-operator/cmd/ansible-operator/main.go b/test/ansible-operator/cmd/ansible-operator/main.go index 75e4bd002b2..4fc322b6268 100644 --- a/test/ansible-operator/cmd/ansible-operator/main.go +++ b/test/ansible-operator/cmd/ansible-operator/main.go @@ -22,6 +22,7 @@ import ( "github.com/operator-framework/operator-sdk/pkg/ansible/operator" proxy "github.com/operator-framework/operator-sdk/pkg/ansible/proxy" "github.com/operator-framework/operator-sdk/pkg/k8sutil" + "github.com/operator-framework/operator-sdk/pkg/log/zap" sdkVersion "github.com/operator-framework/operator-sdk/version" log "github.com/sirupsen/logrus" @@ -39,9 +40,10 @@ func printVersion() { func main() { aflags := aoflags.AddTo(pflag.CommandLine) + zf := zap.FactoryForFlags(pflag.CommandLine) pflag.Parse() - logf.SetLogger(logf.ZapLogger(false)) + logf.SetLogger(zf.Logger()) namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar) if found { diff --git a/test/helm-operator/cmd/helm-operator/main.go b/test/helm-operator/cmd/helm-operator/main.go index fb00ae7964a..0764821e7ea 100644 --- a/test/helm-operator/cmd/helm-operator/main.go +++ b/test/helm-operator/cmd/helm-operator/main.go @@ -15,7 +15,6 @@ package main import ( - "flag" "fmt" "os" "runtime" @@ -25,7 +24,9 @@ import ( "github.com/operator-framework/operator-sdk/pkg/helm/controller" "github.com/operator-framework/operator-sdk/pkg/helm/release" "github.com/operator-framework/operator-sdk/pkg/k8sutil" + "github.com/operator-framework/operator-sdk/pkg/log/zap" sdkVersion "github.com/operator-framework/operator-sdk/version" + "github.com/spf13/pflag" "k8s.io/helm/pkg/storage" "k8s.io/helm/pkg/storage/driver" @@ -44,9 +45,10 @@ func printVersion() { } func main() { - flag.Parse() + zf := zap.FactoryForFlags(pflag.CommandLine) + pflag.Parse() - logf.SetLogger(logf.ZapLogger(false)) + logf.SetLogger(zf.Logger()) printVersion() From eae7198a970c8e43ca054849912a31307a4e8e6b Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Thu, 20 Dec 2018 17:36:35 -0500 Subject: [PATCH 02/14] pkg/scaffold/cmd.go: adding zap logger helper to scaffold --- pkg/scaffold/cmd.go | 8 +++++--- pkg/scaffold/cmd_test.go | 8 +++++--- test/test-framework/cmd/manager/main.go | 8 +++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/pkg/scaffold/cmd.go b/pkg/scaffold/cmd.go index 9d83a108565..e36b34103cf 100644 --- a/pkg/scaffold/cmd.go +++ b/pkg/scaffold/cmd.go @@ -38,7 +38,6 @@ const cmdTmpl = `package main import ( "context" - "flag" "fmt" "os" "runtime" @@ -48,8 +47,10 @@ import ( "github.com/operator-framework/operator-sdk/pkg/k8sutil" "github.com/operator-framework/operator-sdk/pkg/leader" + "github.com/operator-framework/operator-sdk/pkg/log/zap" "github.com/operator-framework/operator-sdk/pkg/ready" sdkVersion "github.com/operator-framework/operator-sdk/version" + "github.com/spf13/pflag" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -66,13 +67,14 @@ func printVersion() { } func main() { - flag.Parse() + zapFactory := zap.FactoryForFlags(pflag.CommandLine) + pflag.Parse() // The logger instantiated here can be changed to any logger // implementing the logr.Logger interface. This logger will // be propagated through the whole operator, generating // uniform and structured logs. - logf.SetLogger(logf.ZapLogger(false)) + logf.SetLogger(zapFactory.Logger()) printVersion() diff --git a/pkg/scaffold/cmd_test.go b/pkg/scaffold/cmd_test.go index 40fbcf64d45..ac6a8b0a4f8 100644 --- a/pkg/scaffold/cmd_test.go +++ b/pkg/scaffold/cmd_test.go @@ -37,7 +37,6 @@ const cmdExp = `package main import ( "context" - "flag" "fmt" "os" "runtime" @@ -46,8 +45,10 @@ import ( "github.com/example-inc/app-operator/pkg/controller" "github.com/operator-framework/operator-sdk/pkg/k8sutil" "github.com/operator-framework/operator-sdk/pkg/leader" + "github.com/operator-framework/operator-sdk/pkg/log/zap" "github.com/operator-framework/operator-sdk/pkg/ready" sdkVersion "github.com/operator-framework/operator-sdk/version" + "github.com/spf13/pflag" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -64,13 +65,14 @@ func printVersion() { } func main() { - flag.Parse() + zapFactory := zap.FactoryForFlags(pflag.CommandLine) + pflag.Parse() // The logger instantiated here can be changed to any logger // implementing the logr.Logger interface. This logger will // be propagated through the whole operator, generating // uniform and structured logs. - logf.SetLogger(logf.ZapLogger(false)) + logf.SetLogger(zapFactory.Logger()) printVersion() diff --git a/test/test-framework/cmd/manager/main.go b/test/test-framework/cmd/manager/main.go index bb9da753efc..f8bca2a0b5b 100644 --- a/test/test-framework/cmd/manager/main.go +++ b/test/test-framework/cmd/manager/main.go @@ -16,17 +16,18 @@ package main import ( "context" - "flag" "fmt" "os" "runtime" "github.com/operator-framework/operator-sdk/pkg/k8sutil" "github.com/operator-framework/operator-sdk/pkg/leader" + "github.com/operator-framework/operator-sdk/pkg/log/zap" "github.com/operator-framework/operator-sdk/pkg/ready" "github.com/operator-framework/operator-sdk/test/test-framework/pkg/apis" "github.com/operator-framework/operator-sdk/test/test-framework/pkg/controller" sdkVersion "github.com/operator-framework/operator-sdk/version" + "github.com/spf13/pflag" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -43,13 +44,14 @@ func printVersion() { } func main() { - flag.Parse() + zapFactory := zap.FactoryForFlags(pflag.CommandLine) + pflag.Parse() // The logger instantiated here can be changed to any logger // implementing the logr.Logger interface. This logger will // be propagated through the whole operator, generating // uniform and structured logs. - logf.SetLogger(logf.ZapLogger(false)) + logf.SetLogger(zapFactory.Logger()) printVersion() From 03d152c91d4f108765a3bacbbedd6528cd347540 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Thu, 3 Jan 2019 12:09:18 -0500 Subject: [PATCH 03/14] pkg/log/zap/flags.go: improve zap-devel help text, group sampleValue Set function with others --- pkg/log/zap/flags.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pkg/log/zap/flags.go b/pkg/log/zap/flags.go index 61f4af18522..aa656f1bd45 100644 --- a/pkg/log/zap/flags.go +++ b/pkg/log/zap/flags.go @@ -27,7 +27,7 @@ import ( func (f *Factory) FlagSet() *pflag.FlagSet { flagSet := pflag.NewFlagSet("zap", pflag.ExitOnError) - flagSet.BoolVar(&f.development, "zap-devel", false, "Enable zap development mode") + flagSet.BoolVar(&f.development, "zap-devel", false, "Enable zap development mode (changes defaults to console encoder, debug log level, and disables sampling)") flagSet.Var(&f.encoderValue, "zap-encoder", "Zap log encoding ('json' or 'console')") flagSet.Var(&f.levelValue, "zap-level", "Zap log level (one of 'debug', 'info', 'warn', 'error', 'dpanic', 'panic', 'fatal')") flagSet.Var(&f.sampleValue, "zap-sample", "Enable zap log sampling") @@ -86,13 +86,6 @@ func (v levelValue) String() string { return v.level.String() } -func (v *sampleValue) Set(s string) error { - var err error - v.set = true - v.sample, err = strconv.ParseBool(s) - return err -} - func (v levelValue) Type() string { return "level" } @@ -102,6 +95,13 @@ type sampleValue struct { sample bool } +func (v *sampleValue) Set(s string) error { + var err error + v.set = true + v.sample, err = strconv.ParseBool(s) + return err +} + func (v sampleValue) String() string { return strconv.FormatBool(v.sample) } From c283dc194640965641dcae4137586422e7f7a52f Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Mon, 7 Jan 2019 12:31:28 -0500 Subject: [PATCH 04/14] pkg/log/zap/flags.go: remove unnecessary import newlines --- pkg/log/zap/flags.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/log/zap/flags.go b/pkg/log/zap/flags.go index aa656f1bd45..c463114e583 100644 --- a/pkg/log/zap/flags.go +++ b/pkg/log/zap/flags.go @@ -19,10 +19,8 @@ import ( "strconv" "github.com/spf13/pflag" - - "go.uber.org/zap/zapcore" - "go.uber.org/zap" + "go.uber.org/zap/zapcore" ) func (f *Factory) FlagSet() *pflag.FlagSet { From 641106da71d96074a841efb96e9f92ca345eb78b Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Mon, 7 Jan 2019 16:24:23 -0500 Subject: [PATCH 05/14] pkg/log/zap: remove factory; s/sink/syncer/g --- commands/operator-sdk/cmd/up/local.go | 9 ++-- pkg/log/zap/flags.go | 26 +++++++--- pkg/log/zap/{factory.go => logger.go} | 50 +++++++------------ pkg/scaffold/cmd.go | 11 +++- pkg/scaffold/cmd_test.go | 11 +++- .../cmd/ansible-operator/main.go | 4 +- test/helm-operator/cmd/helm-operator/main.go | 4 +- test/test-framework/cmd/manager/main.go | 11 +++- 8 files changed, 71 insertions(+), 55 deletions(-) rename pkg/log/zap/{factory.go => logger.go} (69%) diff --git a/commands/operator-sdk/cmd/up/local.go b/commands/operator-sdk/cmd/up/local.go index 7b789c77c5f..ea4c20a9c02 100644 --- a/commands/operator-sdk/cmd/up/local.go +++ b/commands/operator-sdk/cmd/up/local.go @@ -69,9 +69,9 @@ kubernetes cluster using a kubeconfig file. switch projutil.GetOperatorType() { case projutil.OperatorTypeAnsible: ansibleOperatorFlags = flags.AddTo(upLocalCmd.Flags(), "(ansible operator)") - zapFactory = zap.FactoryForFlags(upLocalCmd.Flags()) + upLocalCmd.Flags().AddFlagSet(zap.FlagSet()) case projutil.OperatorTypeHelm: - zapFactory = zap.FactoryForFlags(upLocalCmd.Flags()) + upLocalCmd.Flags().AddFlagSet(zap.FlagSet()) } return upLocalCmd } @@ -81,7 +81,6 @@ var ( operatorFlags string namespace string ldFlags string - zapFactory *zap.Factory ansibleOperatorFlags *flags.AnsibleOperatorFlags ) @@ -161,7 +160,7 @@ func upLocalAnsible() { log.Fatalf("failed to set %s environment variable: (%v)", k8sutil.KubeConfigEnvVar, err) } - logf.SetLogger(zapFactory.Logger()) + logf.SetLogger(zap.Logger()) mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{Namespace: namespace}) if err != nil { @@ -201,7 +200,7 @@ func upLocalHelm() { log.Fatalf("failed to set %s environment variable: (%v)", k8sutil.KubeConfigEnvVar, err) } - logf.SetLogger(zapFactory.Logger()) + logf.SetLogger(zap.Logger()) printVersion() diff --git a/pkg/log/zap/flags.go b/pkg/log/zap/flags.go index c463114e583..a0fced2ad66 100644 --- a/pkg/log/zap/flags.go +++ b/pkg/log/zap/flags.go @@ -23,13 +23,25 @@ import ( "go.uber.org/zap/zapcore" ) -func (f *Factory) FlagSet() *pflag.FlagSet { - flagSet := pflag.NewFlagSet("zap", pflag.ExitOnError) - flagSet.BoolVar(&f.development, "zap-devel", false, "Enable zap development mode (changes defaults to console encoder, debug log level, and disables sampling)") - flagSet.Var(&f.encoderValue, "zap-encoder", "Zap log encoding ('json' or 'console')") - flagSet.Var(&f.levelValue, "zap-level", "Zap log level (one of 'debug', 'info', 'warn', 'error', 'dpanic', 'panic', 'fatal')") - flagSet.Var(&f.sampleValue, "zap-sample", "Enable zap log sampling") - return flagSet +var ( + zapFlagSet *pflag.FlagSet + + development bool + encoderVal encoderValue + levelVal levelValue + sampleVal sampleValue +) + +func init() { + zapFlagSet = pflag.NewFlagSet("zap", pflag.ExitOnError) + zapFlagSet.BoolVar(&development, "zap-devel", false, "Enable zap development mode (changes defaults to console encoder, debug log level, and disables sampling)") + zapFlagSet.Var(&encoderVal, "zap-encoder", "Zap log encoding ('json' or 'console')") + zapFlagSet.Var(&levelVal, "zap-level", "Zap log level (one of 'debug', 'info', 'warn', 'error', 'dpanic', 'panic', 'fatal')") + zapFlagSet.Var(&sampleVal, "zap-sample", "Enable zap log sampling") +} + +func FlagSet() *pflag.FlagSet { + return zapFlagSet } type encoderValue struct { diff --git a/pkg/log/zap/factory.go b/pkg/log/zap/logger.go similarity index 69% rename from pkg/log/zap/factory.go rename to pkg/log/zap/logger.go index e906c629909..f03e8a34a49 100644 --- a/pkg/log/zap/factory.go +++ b/pkg/log/zap/logger.go @@ -19,30 +19,20 @@ import ( "os" "time" - "github.com/go-logr/zapr" - "github.com/spf13/pflag" - "github.com/go-logr/logr" + "github.com/go-logr/zapr" + "go.uber.org/zap" "go.uber.org/zap/zapcore" logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" - - "go.uber.org/zap" ) -type Factory struct { - development bool - encoderValue encoderValue - levelValue levelValue - sampleValue sampleValue -} - -func (f Factory) Logger() logr.Logger { - return f.LoggerTo(os.Stderr) +func Logger() logr.Logger { + return LoggerTo(os.Stderr) } -func (f Factory) LoggerTo(destWriter io.Writer) logr.Logger { - sink := zapcore.AddSync(destWriter) - conf := f.getConfig(destWriter) +func LoggerTo(destWriter io.Writer) logr.Logger { + syncer := zapcore.AddSync(destWriter) + conf := getConfig(destWriter) conf.encoder = &logf.KubeAwareEncoder{Encoder: conf.encoder, Verbose: conf.level.Level() < 0} if conf.sample { @@ -50,8 +40,8 @@ func (f Factory) LoggerTo(destWriter io.Writer) logr.Logger { return zapcore.NewSampler(core, time.Second, 100, 100) })) } - conf.opts = append(conf.opts, zap.AddCallerSkip(1), zap.ErrorOutput(sink)) - log := zap.New(zapcore.NewCore(conf.encoder, sink, conf.level)) + conf.opts = append(conf.opts, zap.AddCallerSkip(1), zap.ErrorOutput(syncer)) + log := zap.New(zapcore.NewCore(conf.encoder, syncer, conf.level)) log = log.WithOptions(conf.opts...) return zapr.NewLogger(log) } @@ -63,11 +53,11 @@ type config struct { opts []zap.Option } -func (f *Factory) getConfig(destWriter io.Writer) config { +func getConfig(destWriter io.Writer) config { var c config // Set the defaults depending on the log mode (development vs. production) - if f.development { + if development { c.encoder = consoleEncoder() c.level = zap.NewAtomicLevelAt(zap.DebugLevel) c.opts = append(c.opts, zap.Development(), zap.AddStacktrace(zap.ErrorLevel)) @@ -80,21 +70,15 @@ func (f *Factory) getConfig(destWriter io.Writer) config { } // Override the defaults if the flags were set explicitly on the command line - if f.encoderValue.set { - c.encoder = f.encoderValue.encoder + if encoderVal.set { + c.encoder = encoderVal.encoder } - if f.levelValue.set { - c.level = zap.NewAtomicLevelAt(f.levelValue.level) + if levelVal.set { + c.level = zap.NewAtomicLevelAt(levelVal.level) } - if f.sampleValue.set { - c.sample = f.sampleValue.sample + if sampleVal.set { + c.sample = sampleVal.sample } return c } - -func FactoryForFlags(flagSet *pflag.FlagSet) *Factory { - f := &Factory{} - flagSet.AddFlagSet(f.FlagSet()) - return f -} diff --git a/pkg/scaffold/cmd.go b/pkg/scaffold/cmd.go index e36b34103cf..d364d23bb1b 100644 --- a/pkg/scaffold/cmd.go +++ b/pkg/scaffold/cmd.go @@ -67,14 +67,21 @@ func printVersion() { } func main() { - zapFactory := zap.FactoryForFlags(pflag.CommandLine) + // Add the zap logger flag set to the CLI. The flag set must + // be added before calling pflag.Parse(). + pflag.CommandLine.AddFlagSet(zap.FlagSet()) + pflag.Parse() + // Use a zap logr.Logger implementation. If none of the zap + // flags are configured (or if the zap flag set is not being + // used), this defaults to a production zap logger. + // // The logger instantiated here can be changed to any logger // implementing the logr.Logger interface. This logger will // be propagated through the whole operator, generating // uniform and structured logs. - logf.SetLogger(zapFactory.Logger()) + logf.SetLogger(zap.Logger()) printVersion() diff --git a/pkg/scaffold/cmd_test.go b/pkg/scaffold/cmd_test.go index ac6a8b0a4f8..55fb19509fb 100644 --- a/pkg/scaffold/cmd_test.go +++ b/pkg/scaffold/cmd_test.go @@ -65,14 +65,21 @@ func printVersion() { } func main() { - zapFactory := zap.FactoryForFlags(pflag.CommandLine) + // Add the zap logger flag set to the CLI. The flag set must + // be added before calling pflag.Parse(). + pflag.CommandLine.AddFlagSet(zap.FlagSet()) + pflag.Parse() + // Use a zap logr.Logger implementation. If none of the zap + // flags are configured (or if the zap flag set is not being + // used), this defaults to a production zap logger. + // // The logger instantiated here can be changed to any logger // implementing the logr.Logger interface. This logger will // be propagated through the whole operator, generating // uniform and structured logs. - logf.SetLogger(zapFactory.Logger()) + logf.SetLogger(zap.Logger()) printVersion() diff --git a/test/ansible-operator/cmd/ansible-operator/main.go b/test/ansible-operator/cmd/ansible-operator/main.go index 4fc322b6268..0bc7b76f9b5 100644 --- a/test/ansible-operator/cmd/ansible-operator/main.go +++ b/test/ansible-operator/cmd/ansible-operator/main.go @@ -40,10 +40,10 @@ func printVersion() { func main() { aflags := aoflags.AddTo(pflag.CommandLine) - zf := zap.FactoryForFlags(pflag.CommandLine) + pflag.CommandLine.AddFlagSet(zap.FlagSet()) pflag.Parse() - logf.SetLogger(zf.Logger()) + logf.SetLogger(zap.Logger()) namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar) if found { diff --git a/test/helm-operator/cmd/helm-operator/main.go b/test/helm-operator/cmd/helm-operator/main.go index 0764821e7ea..00d22a1623c 100644 --- a/test/helm-operator/cmd/helm-operator/main.go +++ b/test/helm-operator/cmd/helm-operator/main.go @@ -45,10 +45,10 @@ func printVersion() { } func main() { - zf := zap.FactoryForFlags(pflag.CommandLine) + pflag.CommandLine.AddFlagSet(zap.FlagSet()) pflag.Parse() - logf.SetLogger(zf.Logger()) + logf.SetLogger(zap.Logger()) printVersion() diff --git a/test/test-framework/cmd/manager/main.go b/test/test-framework/cmd/manager/main.go index f8bca2a0b5b..36d1b13a040 100644 --- a/test/test-framework/cmd/manager/main.go +++ b/test/test-framework/cmd/manager/main.go @@ -44,14 +44,21 @@ func printVersion() { } func main() { - zapFactory := zap.FactoryForFlags(pflag.CommandLine) + // Add the zap logger flag set to the CLI. The flag set must + // be added before calling pflag.Parse(). + pflag.CommandLine.AddFlagSet(zap.FlagSet()) + pflag.Parse() + // Use a zap logr.Logger implementation. If none of the zap + // flags are configured (or if the zap flag set is not being + // used), this defaults to a production zap logger. + // // The logger instantiated here can be changed to any logger // implementing the logr.Logger interface. This logger will // be propagated through the whole operator, generating // uniform and structured logs. - logf.SetLogger(zapFactory.Logger()) + logf.SetLogger(zap.Logger()) printVersion() From bf391e9d90adc9a54f3b1378e171c5cc0bc8f458 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Mon, 7 Jan 2019 16:31:06 -0500 Subject: [PATCH 06/14] test/*,commands/operator-sdk/cmd/up/local.go: include flags registered by imported packages --- test/ansible-operator/cmd/ansible-operator/main.go | 2 ++ test/helm-operator/cmd/helm-operator/main.go | 2 ++ test/test-framework/cmd/manager/main.go | 2 ++ 3 files changed, 6 insertions(+) diff --git a/test/ansible-operator/cmd/ansible-operator/main.go b/test/ansible-operator/cmd/ansible-operator/main.go index 0bc7b76f9b5..3016b055a80 100644 --- a/test/ansible-operator/cmd/ansible-operator/main.go +++ b/test/ansible-operator/cmd/ansible-operator/main.go @@ -15,6 +15,7 @@ package main import ( + "flag" "os" "runtime" @@ -41,6 +42,7 @@ func printVersion() { func main() { aflags := aoflags.AddTo(pflag.CommandLine) pflag.CommandLine.AddFlagSet(zap.FlagSet()) + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.Parse() logf.SetLogger(zap.Logger()) diff --git a/test/helm-operator/cmd/helm-operator/main.go b/test/helm-operator/cmd/helm-operator/main.go index 00d22a1623c..e88db9e40ea 100644 --- a/test/helm-operator/cmd/helm-operator/main.go +++ b/test/helm-operator/cmd/helm-operator/main.go @@ -15,6 +15,7 @@ package main import ( + "flag" "fmt" "os" "runtime" @@ -46,6 +47,7 @@ func printVersion() { func main() { pflag.CommandLine.AddFlagSet(zap.FlagSet()) + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.Parse() logf.SetLogger(zap.Logger()) diff --git a/test/test-framework/cmd/manager/main.go b/test/test-framework/cmd/manager/main.go index 36d1b13a040..1d8142f64b6 100644 --- a/test/test-framework/cmd/manager/main.go +++ b/test/test-framework/cmd/manager/main.go @@ -16,6 +16,7 @@ package main import ( "context" + "flag" "fmt" "os" "runtime" @@ -48,6 +49,7 @@ func main() { // be added before calling pflag.Parse(). pflag.CommandLine.AddFlagSet(zap.FlagSet()) + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.Parse() // Use a zap logr.Logger implementation. If none of the zap From ccaf53fd2749ce548a1edfe84b8178bff084146d Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Mon, 7 Jan 2019 17:06:29 -0500 Subject: [PATCH 07/14] pkg/log/zap: bump copyright year to 2019 --- pkg/log/zap/flags.go | 2 +- pkg/log/zap/logger.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/log/zap/flags.go b/pkg/log/zap/flags.go index a0fced2ad66..308b539277e 100644 --- a/pkg/log/zap/flags.go +++ b/pkg/log/zap/flags.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Operator-SDK Authors +// Copyright 2019 The Operator-SDK Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/pkg/log/zap/logger.go b/pkg/log/zap/logger.go index f03e8a34a49..316669544bb 100644 --- a/pkg/log/zap/logger.go +++ b/pkg/log/zap/logger.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Operator-SDK Authors +// Copyright 2019 The Operator-SDK Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From 975eddc8955e92600aae202762222458e789e64b Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Tue, 8 Jan 2019 10:26:01 -0500 Subject: [PATCH 08/14] pkg/scaffold: include flags registered by imported packages --- pkg/scaffold/cmd.go | 5 +++++ pkg/scaffold/cmd_test.go | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/pkg/scaffold/cmd.go b/pkg/scaffold/cmd.go index d364d23bb1b..843ed231848 100644 --- a/pkg/scaffold/cmd.go +++ b/pkg/scaffold/cmd.go @@ -38,6 +38,7 @@ const cmdTmpl = `package main import ( "context" + "flag" "fmt" "os" "runtime" @@ -71,6 +72,10 @@ func main() { // be added before calling pflag.Parse(). pflag.CommandLine.AddFlagSet(zap.FlagSet()) + // Add flags registered by imported packages (e.g. glog and + // controller-runtime) + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) + pflag.Parse() // Use a zap logr.Logger implementation. If none of the zap diff --git a/pkg/scaffold/cmd_test.go b/pkg/scaffold/cmd_test.go index 55fb19509fb..1635e89f927 100644 --- a/pkg/scaffold/cmd_test.go +++ b/pkg/scaffold/cmd_test.go @@ -37,6 +37,7 @@ const cmdExp = `package main import ( "context" + "flag" "fmt" "os" "runtime" @@ -69,6 +70,10 @@ func main() { // be added before calling pflag.Parse(). pflag.CommandLine.AddFlagSet(zap.FlagSet()) + // Add flags registered by imported packages (e.g. glog and + // controller-runtime) + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) + pflag.Parse() // Use a zap logr.Logger implementation. If none of the zap From c90c6faccd1dad8fef2645a9fcebd86c1caab1a6 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Fri, 11 Jan 2019 13:19:58 -0500 Subject: [PATCH 09/14] pkg/(ansible|helm)/flags,commands,test: centralizing zap flagset setup Moves the zap flagset initialization into the ansible and helm flag packages so that they are reused in all ansible and helm operator scenarios (e.g. `up local`, `run`, and the helm binary) Also reverts parts a previous commit (975eddc) that added flags to the ansible and helm operators imported by other libraries because it caused the entire set of "testing" package flags to be added (from `operator-sdk` dependencies). --- commands/operator-sdk/cmd/run/ansible.go | 2 -- commands/operator-sdk/cmd/up/local.go | 2 -- pkg/ansible/flags/flag.go | 2 ++ pkg/helm/flags/flag.go | 2 ++ test/helm-operator/cmd/helm-operator/main.go | 3 --- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/commands/operator-sdk/cmd/run/ansible.go b/commands/operator-sdk/cmd/run/ansible.go index 3c5c775951a..90889b9f4ca 100644 --- a/commands/operator-sdk/cmd/run/ansible.go +++ b/commands/operator-sdk/cmd/run/ansible.go @@ -17,7 +17,6 @@ package run import ( "github.com/operator-framework/operator-sdk/pkg/ansible" aoflags "github.com/operator-framework/operator-sdk/pkg/ansible/flags" - "github.com/operator-framework/operator-sdk/pkg/log/zap" "github.com/spf13/cobra" ) @@ -34,7 +33,6 @@ func NewAnsibleCmd() *cobra.Command { }, } flags = aoflags.AddTo(newCmd.Flags()) - newCmd.Flags().AddFlagSet(zap.FlagSet()) return newCmd } diff --git a/commands/operator-sdk/cmd/up/local.go b/commands/operator-sdk/cmd/up/local.go index 9515ae81bbf..0ed0bec092e 100644 --- a/commands/operator-sdk/cmd/up/local.go +++ b/commands/operator-sdk/cmd/up/local.go @@ -67,10 +67,8 @@ kubernetes cluster using a kubeconfig file. switch projutil.GetOperatorType() { case projutil.OperatorTypeAnsible: ansibleOperatorFlags = aoflags.AddTo(upLocalCmd.Flags(), "(ansible operator)") - upLocalCmd.Flags().AddFlagSet(zap.FlagSet()) case projutil.OperatorTypeHelm: helmOperatorFlags = hoflags.AddTo(upLocalCmd.Flags(), "(helm operator)") - upLocalCmd.Flags().AddFlagSet(zap.FlagSet()) } return upLocalCmd } diff --git a/pkg/ansible/flags/flag.go b/pkg/ansible/flags/flag.go index 278f6c6e381..0830351ace7 100644 --- a/pkg/ansible/flags/flag.go +++ b/pkg/ansible/flags/flag.go @@ -16,6 +16,7 @@ package flags import ( "github.com/operator-framework/operator-sdk/pkg/internal/flags" + "github.com/operator-framework/operator-sdk/pkg/log/zap" "github.com/spf13/pflag" ) @@ -29,5 +30,6 @@ type AnsibleOperatorFlags struct { func AddTo(flagSet *pflag.FlagSet, helpTextPrefix ...string) *AnsibleOperatorFlags { aof := &AnsibleOperatorFlags{} aof.WatchFlags.AddTo(flagSet, helpTextPrefix...) + flagSet.AddFlagSet(zap.FlagSet()) return aof } diff --git a/pkg/helm/flags/flag.go b/pkg/helm/flags/flag.go index 239ee19d011..ee41e869e9d 100644 --- a/pkg/helm/flags/flag.go +++ b/pkg/helm/flags/flag.go @@ -16,6 +16,7 @@ package flags import ( "github.com/operator-framework/operator-sdk/pkg/internal/flags" + "github.com/operator-framework/operator-sdk/pkg/log/zap" "github.com/spf13/pflag" ) @@ -29,5 +30,6 @@ type HelmOperatorFlags struct { func AddTo(flagSet *pflag.FlagSet, helpTextPrefix ...string) *HelmOperatorFlags { hof := &HelmOperatorFlags{} hof.WatchFlags.AddTo(flagSet, helpTextPrefix...) + flagSet.AddFlagSet(zap.FlagSet()) return hof } diff --git a/test/helm-operator/cmd/helm-operator/main.go b/test/helm-operator/cmd/helm-operator/main.go index d104b060e87..75e8163f81e 100644 --- a/test/helm-operator/cmd/helm-operator/main.go +++ b/test/helm-operator/cmd/helm-operator/main.go @@ -15,7 +15,6 @@ package main import ( - "flag" "fmt" "os" "runtime" @@ -47,8 +46,6 @@ func printVersion() { func main() { hflags := hoflags.AddTo(pflag.CommandLine) - pflag.CommandLine.AddFlagSet(zap.FlagSet()) - pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.Parse() logf.SetLogger(zap.Logger()) From fc945ce515914173d3f330a0db075767c629bedb Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Fri, 11 Jan 2019 13:53:18 -0500 Subject: [PATCH 10/14] pkg/scaffold/,test/test-framework: whitespace and comment consistency --- pkg/scaffold/cmd.go | 2 +- test/test-framework/cmd/manager/main.go | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/scaffold/cmd.go b/pkg/scaffold/cmd.go index 25801675791..8aa9d461a7d 100644 --- a/pkg/scaffold/cmd.go +++ b/pkg/scaffold/cmd.go @@ -75,7 +75,7 @@ func main() { // Add flags registered by imported packages (e.g. glog and // controller-runtime) pflag.CommandLine.AddGoFlagSet(flag.CommandLine) - + pflag.Parse() // Use a zap logr.Logger implementation. If none of the zap diff --git a/test/test-framework/cmd/manager/main.go b/test/test-framework/cmd/manager/main.go index 7f82ab2596c..9b4a5871a54 100644 --- a/test/test-framework/cmd/manager/main.go +++ b/test/test-framework/cmd/manager/main.go @@ -49,7 +49,10 @@ func main() { // be added before calling pflag.Parse(). pflag.CommandLine.AddFlagSet(zap.FlagSet()) + // Add flags registered by imported packages (e.g. glog and + // controller-runtime) pflag.CommandLine.AddGoFlagSet(flag.CommandLine) + pflag.Parse() // Use a zap logr.Logger implementation. If none of the zap From e7c77aebd3c55044295caa1d7a61726dcdcbdf9e Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Mon, 28 Jan 2019 11:48:19 -0500 Subject: [PATCH 11/14] images/scorecard-proxy/cmd/proxy/main.go: use configurable zap logger --- images/scorecard-proxy/cmd/proxy/main.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/images/scorecard-proxy/cmd/proxy/main.go b/images/scorecard-proxy/cmd/proxy/main.go index 90162e3796a..344c224f071 100644 --- a/images/scorecard-proxy/cmd/proxy/main.go +++ b/images/scorecard-proxy/cmd/proxy/main.go @@ -15,11 +15,13 @@ package main import ( - "flag" "os" + "github.com/spf13/pflag" + proxy "github.com/operator-framework/operator-sdk/pkg/ansible/proxy" "github.com/operator-framework/operator-sdk/pkg/k8sutil" + "github.com/operator-framework/operator-sdk/pkg/log/zap" log "github.com/sirupsen/logrus" "sigs.k8s.io/controller-runtime/pkg/client/config" @@ -28,8 +30,10 @@ import ( ) func main() { - flag.Parse() - logf.SetLogger(logf.ZapLogger(false)) + pflag.CommandLine.AddFlagSet(zap.FlagSet()) + pflag.Parse() + + logf.SetLogger(zap.Logger()) namespace, found := os.LookupEnv(k8sutil.WatchNamespaceEnvVar) if found { From 98d0398d0a9958bdc3c521a4421e2de835b5152d Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Wed, 30 Jan 2019 11:59:06 -0500 Subject: [PATCH 12/14] pkg/log/zap/flags.go: only allow debug, info, and error --- pkg/log/zap/flags.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/log/zap/flags.go b/pkg/log/zap/flags.go index 308b539277e..67d0080edd8 100644 --- a/pkg/log/zap/flags.go +++ b/pkg/log/zap/flags.go @@ -17,6 +17,7 @@ package zap import ( "fmt" "strconv" + "strings" "github.com/spf13/pflag" "go.uber.org/zap" @@ -36,7 +37,7 @@ func init() { zapFlagSet = pflag.NewFlagSet("zap", pflag.ExitOnError) zapFlagSet.BoolVar(&development, "zap-devel", false, "Enable zap development mode (changes defaults to console encoder, debug log level, and disables sampling)") zapFlagSet.Var(&encoderVal, "zap-encoder", "Zap log encoding ('json' or 'console')") - zapFlagSet.Var(&levelVal, "zap-level", "Zap log level (one of 'debug', 'info', 'warn', 'error', 'dpanic', 'panic', 'fatal')") + zapFlagSet.Var(&levelVal, "zap-level", "Zap log level (one of 'debug', 'info', 'error')") zapFlagSet.Var(&sampleVal, "zap-sample", "Enable zap log sampling") } @@ -89,7 +90,12 @@ type levelValue struct { func (v *levelValue) Set(l string) error { v.set = true - return v.level.Set(l) + lower := strings.ToLower(l) + switch lower { + case "debug", "info", "error": + return v.level.Set(l) + } + return fmt.Errorf("invalid log level \"%s\"", l) } func (v levelValue) String() string { From e6ef2ca28424698f350160fefb73f85df5d73bb7 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Wed, 30 Jan 2019 17:20:06 -0500 Subject: [PATCH 13/14] images/scorecard-proxy/cmd/proxy/main.go: fix imports --- images/scorecard-proxy/cmd/proxy/main.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/images/scorecard-proxy/cmd/proxy/main.go b/images/scorecard-proxy/cmd/proxy/main.go index a31fecc21c5..d3a4b6d01bf 100644 --- a/images/scorecard-proxy/cmd/proxy/main.go +++ b/images/scorecard-proxy/cmd/proxy/main.go @@ -17,14 +17,13 @@ package main import ( "os" - "github.com/spf13/pflag" - proxy "github.com/operator-framework/operator-sdk/pkg/ansible/proxy" "github.com/operator-framework/operator-sdk/pkg/ansible/proxy/controllermap" "github.com/operator-framework/operator-sdk/pkg/k8sutil" "github.com/operator-framework/operator-sdk/pkg/log/zap" log "github.com/sirupsen/logrus" + "github.com/spf13/pflag" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" From 48f07e0bdddb867c1cdb23d8ef343555b6454e1b Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Wed, 30 Jan 2019 17:42:22 -0500 Subject: [PATCH 14/14] doc/user/logging.md: document zap helpers and flags --- doc/user/logging.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/doc/user/logging.md b/doc/user/logging.md index df702d7d27b..6a6aa30910d 100644 --- a/doc/user/logging.md +++ b/doc/user/logging.md @@ -8,11 +8,15 @@ Operators set the logger for all operator logging in [`cmd/manager/main.go`][cod ```Go import ( + "github.com/operator-framework/operator-sdk/pkg/log/zap" + "github.com/spf13/pflag" logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" ) func main() { - logf.SetLogger(logf.ZapLogger(false)) + pflag.CommandLine.AddFlagSet(zap.FlagSet()) + pflag.Parse() + logf.SetLogger(zap.Logger()) log := logf.Log.WithName("cmd") ... @@ -25,7 +29,19 @@ func main() { By using `controller-runtime/pkg/runtime/log`, your logger is propagated through `controller-runtime`. Any logs produced by `controller-runtime` code will be through your logger, and therefore have the same formatting and destination. -In the above example, `logf.ZapLogger()` takes a boolean flag to set development parameters. Passing in `true` will set the logger to log in development mode; debug log statements will trigger, and error log statements will include stack traces. +### Default zap logger + +Operator SDK uses a `zap`-based `logr` backend when scaffolding new projects. To assist with configuring and using this logger, the SDK includes several helper functions. + +In the above example, we add the zap flagset to the operator's command line flags with `zap.FlagSet()`, and then set the controller-runtime logger with `zap.Logger()`. + +By default, `zap.Logger()` will return a logger that is ready for production use. It uses a JSON encoder, logs starting at the `info` level, and has [sampling][zap_sampling] enabled. To customize the default behavior, users can use the zap flagset and specify flags on the command line. The zap flagset includes the following flags that can be used to configure the logger: +* `--zap-devel` - Enables the zap development config (changes defaults to console encoder, debug log level, and disables sampling) (default: `false`) +* `--zap-encoder` string - Sets the zap log encoding (`json` or `console`) +* `--zap-level` string - Sets the zap log level (`debug`, `info`, or `error`) +* `--zap-sample` - Enables zap's sampling mode + +**NOTE:** Although the `logr` interface supports multiple debug levels (e.g. `log.V(1).Info()`, `log.V(2).Info()`, etc.), zap supports only a single debug level with `log.V(1).Info()`. Log statements with higher debug levels will not be printed with the zap's `logr` backend. ## Creating a structured log statement @@ -102,4 +118,5 @@ If you do not want to use `logr` as your logging tool, you can remove `logr`-spe [godoc_logr_logger]:https://godoc.org/github.com/go-logr/logr#Logger [site_struct_logging]:https://www.client9.com/structured-logging-in-golang/ [code_memcached_controller]:../../example/memcached-operator/memcached_controller.go.tmpl -[code_set_logger]:https://github.com/operator-framework/operator-sdk/blob/948139171fff0e802c9e68f87cb95939941772ef/pkg/scaffold/cmd.go#L68-L72 +[code_set_logger]:https://github.com/operator-framework/operator-sdk/blob/ecd02000616f11303f1adecd3d4ceb4a8561a9ec/pkg/scaffold/cmd.go#L90-L94 +[zap_sampling]:https://github.com/uber-go/zap/blob/master/FAQ.md#why-sample-application-logs