Skip to content

Commit

Permalink
Added EncoderConfigOptions field in Options struct.
Browse files Browse the repository at this point in the history
  • Loading branch information
bharathi-tenneti committed Jul 23, 2020
1 parent fb0577a commit eccba7c
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 37 deletions.
3 changes: 0 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@ require (
github.com/onsi/gomega v1.10.1
github.com/prometheus/client_golang v1.0.0
github.com/prometheus/client_model v0.2.0
github.com/prometheus/procfs v0.0.11 // indirect
github.com/spf13/pflag v1.0.5
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/zap v1.10.0
golang.org/x/text v0.3.3 // indirect
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
gomodules.xyz/jsonpatch/v2 v2.0.1
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
Expand Down
9 changes: 3 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
Expand Down Expand Up @@ -221,6 +223,7 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
Expand Down Expand Up @@ -295,8 +298,6 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI=
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
Expand Down Expand Up @@ -414,17 +415,13 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e h1:LwyF2AFISC9nVbS6MgzsaQNSUsRXI49GS+YQ5KX/QH0=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
Expand Down
24 changes: 7 additions & 17 deletions pkg/log/zap/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ limitations under the License.
package zap

import (
"flag"
"fmt"
"strconv"
"strings"

"github.com/spf13/pflag"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
Expand All @@ -42,11 +42,11 @@ var stackLevelStrings = map[string]zapcore.Level{
}

type encoderFlag struct {
setFunc func(zapcore.Encoder)
setFunc func(NewEncoderFunc)
value string
}

var _ pflag.Value = &encoderFlag{}
var _ flag.Value = &encoderFlag{}

func (ev *encoderFlag) String() string {
return ev.value
Expand All @@ -60,32 +60,22 @@ func (ev *encoderFlag) Set(flagValue string) error {
val := strings.ToLower(flagValue)
switch val {
case "json":
ev.setFunc(newJSONEncoder())
ev.setFunc(newJSONEncoder)
case "console":
ev.setFunc(newConsoleEncoder())
ev.setFunc(newConsoleEncoder)
default:
return fmt.Errorf("invalid encoder value \"%s\"", flagValue)
}
ev.value = flagValue
return nil
}

func newJSONEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
return zapcore.NewJSONEncoder(encoderConfig)
}

func newConsoleEncoder() zapcore.Encoder {
encoderConfig := zap.NewDevelopmentEncoderConfig()
return zapcore.NewConsoleEncoder(encoderConfig)
}

type levelFlag struct {
setFunc func(zapcore.LevelEnabler)
value string
}

var _ pflag.Value = &levelFlag{}
var _ flag.Value = &levelFlag{}

func (ev *levelFlag) Set(flagValue string) error {
level, validLevel := levelStrings[strings.ToLower(flagValue)]
Expand Down Expand Up @@ -120,7 +110,7 @@ type stackTraceFlag struct {
value string
}

var _ pflag.Value = &stackTraceFlag{}
var _ flag.Value = &stackTraceFlag{}

func (ev *stackTraceFlag) Set(flagValue string) error {
level, validLevel := stackLevelStrings[strings.ToLower(flagValue)]
Expand Down
54 changes: 43 additions & 11 deletions pkg/log/zap/zap.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ import (
"go.uber.org/zap/zapcore"
)

// EncoderConfigOption is being used to pass options
// for configuring console/json encoder.
type EncoderConfigOption func(*zapcore.EncoderConfig)

// NewEncoderFunc is a function that creates an Encoder using the provided EncoderConfigOptions.
type NewEncoderFunc func(...EncoderConfigOption) zapcore.Encoder

// New returns a brand new Logger configured with Opts. It
// uses KubeAwareEncoder which adds Type information and
// Namespace/Name to the log.
Expand Down Expand Up @@ -98,6 +105,22 @@ func Encoder(encoder zapcore.Encoder) func(o *Options) {
}
}

func newJSONEncoder(ecfs ...EncoderConfigOption) zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
for _, f := range ecfs {
f(&encoderConfig)
}
return zapcore.NewJSONEncoder(encoderConfig)
}

func newConsoleEncoder(ecfs ...EncoderConfigOption) zapcore.Encoder {
encoderConfig := zap.NewDevelopmentEncoderConfig()
for _, f := range ecfs {
f(&encoderConfig)
}
return zapcore.NewConsoleEncoder(encoderConfig)
}

// Level sets the the minimum enabled logging level e.g Debug, Info
// See Options.Level
func Level(level zapcore.LevelEnabler) func(o *Options) {
Expand Down Expand Up @@ -132,6 +155,14 @@ type Options struct {
// Encoder configures how Zap will encode the output. Defaults to
// console when Development is true and JSON otherwise
Encoder zapcore.Encoder
// EncoderConfigOptions can modify the EncoderConfig needed to initialize an Encoder.
// See https://godoc.org/go.uber.org/zap/zapcore#EncoderConfig for the list of options
// that can be configured.
// Note that the EncoderConfigOptions are not applied when the Encoder option is already set.
EncoderConfigOptions []EncoderConfigOption
// NewEncoder configures Encoder using the provided EncoderConfigOptions.
// Note that the NewEncoder function is not used when the Encoder option is already set.
NewEncoder NewEncoderFunc
// DestWritter controls the destination of the log output. Defaults to
// os.Stderr.
DestWritter io.Writer
Expand All @@ -154,9 +185,8 @@ func (o *Options) addDefaults() {
}

if o.Development {
if o.Encoder == nil {
encCfg := zap.NewDevelopmentEncoderConfig()
o.Encoder = zapcore.NewConsoleEncoder(encCfg)
if o.NewEncoder == nil {
o.NewEncoder = newConsoleEncoder
}
if o.Level == nil {
lvl := zap.NewAtomicLevelAt(zap.DebugLevel)
Expand All @@ -169,9 +199,8 @@ func (o *Options) addDefaults() {
o.ZapOpts = append(o.ZapOpts, zap.Development())

} else {
if o.Encoder == nil {
encCfg := zap.NewProductionEncoderConfig()
o.Encoder = zapcore.NewJSONEncoder(encCfg)
if o.NewEncoder == nil {
o.NewEncoder = newJSONEncoder
}
if o.Level == nil {
lvl := zap.NewAtomicLevelAt(zap.InfoLevel)
Expand All @@ -190,6 +219,9 @@ func (o *Options) addDefaults() {
}))
}
}
if o.Encoder == nil {
o.Encoder = o.NewEncoder(o.EncoderConfigOptions...)
}
o.ZapOpts = append(o.ZapOpts, zap.AddStacktrace(o.StacktraceLevel))
}

Expand All @@ -215,7 +247,7 @@ func NewRaw(opts ...Opts) *zap.Logger {
// BindFlags will parse the given flagset for zap option flags and set the log options accordingly
// zap-devel: Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn)
// Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error)
// zap-encoder: Zap log encoding ('json' or 'console')
// zap-encoder: Zap log encoding (Eg., 'json' or 'console')
// zap-log-level: Zap Level to configure the verbosity of logging. Can be one of 'debug', 'info', 'error',
// or any integer value > 0 which corresponds to custom debug levels of increasing verbosity")
// zap-stacktrace-level: Zap Level at and above which stacktraces are captured (one of 'info' or 'error')
Expand All @@ -228,10 +260,10 @@ func (o *Options) BindFlags(fs *flag.FlagSet) {

// Set Encoder value
var encVal encoderFlag
encVal.setFunc = func(fromFlag zapcore.Encoder) {
o.Encoder = fromFlag
encVal.setFunc = func(fromFlag NewEncoderFunc) {
o.NewEncoder = fromFlag
}
fs.Var(&encVal, "zap-encoder", "Zap log encoding ('json' or 'console')")
fs.Var(&encVal, "zap-encoder", "Zap log encoding (Eg., 'json' or 'console')")

// Set the Log Level
var levelVal levelFlag
Expand All @@ -254,10 +286,10 @@ func (o *Options) BindFlags(fs *flag.FlagSet) {
// UseFlagOptions configures the logger to use the Options set by parsing zap option flags from the CLI.
// opts := zap.Options{}
// opts.BindFlags(flag.CommandLine)
// flag.Parse()
// log := zap.New(zap.UseFlagOptions(&opts))
func UseFlagOptions(in *Options) Opts {
return func(o *Options) {
*o = *in
o.addDefaults()
}
}
77 changes: 77 additions & 0 deletions pkg/log/zap/zap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,4 +459,81 @@ var _ = Describe("Zap log level flag options setup", func() {

})

Context("with only -zap-devel flag provided", func() {
It("Should set dev=true.", func() {
args := []string{"--zap-devel=true"}
fromFlags.BindFlags(&fs)
if err := fs.Parse(args); err != nil {
Expect(err).ToNot(HaveOccurred())
}
out := Options{}
UseFlagOptions(&fromFlags)(&out)

Expect(out.Development).To(BeTrue())
Expect(out.Encoder).To(BeNil())
Expect(out.Level).To(BeNil())
Expect(out.StacktraceLevel).To(BeNil())
Expect(out.EncoderConfigOptions).To(BeNil())
})
It("Should set dev=false with log options.", func() {
args := []string{"--zap-log-level=2"}
fromFlags.BindFlags(&fs)
if err := fs.Parse(args); err != nil {
Expect(err).ToNot(HaveOccurred())
}
out := Options{}
UseFlagOptions(&fromFlags)(&out)

Expect(out.Development).To(BeFalse())
Expect(out.Level.Enabled(zapcore.ErrorLevel)).To(BeTrue())

})
})

Context("with encoder options provided programmatically.", func() {

It("Should set Console Encoder, with given Nanos TimEncoder option.", func() {
logOut := new(bytes.Buffer)
f := func(ec *zapcore.EncoderConfig) {
if err := ec.EncodeTime.UnmarshalText([]byte("nanos")); err != nil {
Expect(err).ToNot(HaveOccurred())
}
}
opts := func(o *Options) {
o.EncoderConfigOptions = append(o.EncoderConfigOptions, f)
}
log := New(UseDevMode(true), WriteTo(logOut), opts)
log.Info("This is a test message")
outRaw := logOut.Bytes()
// Assert for Console Encoder
res := map[string]interface{}{}
Expect(json.Unmarshal(outRaw, &res)).ToNot(Succeed())
// Assert for Epoch Nanos TimeEncoder
Expect(string(outRaw)).ShouldNot(ContainSubstring("."))

})
It("Should set JSON Encoder, with given Millis TimEncoder option, and MessageKey", func() {
logOut := new(bytes.Buffer)
f := func(ec *zapcore.EncoderConfig) {
ec.MessageKey = "MillisTimeFormat"
if err := ec.EncodeTime.UnmarshalText([]byte("millis")); err != nil {
Expect(err).ToNot(HaveOccurred())
}
}
opts := func(o *Options) {
o.EncoderConfigOptions = append(o.EncoderConfigOptions, f)
}
log := New(UseDevMode(false), WriteTo(logOut), opts)
log.Info("This is a test message")
outRaw := logOut.Bytes()
// Assert for JSON Encoder
res := map[string]interface{}{}
Expect(json.Unmarshal(outRaw, &res)).To(Succeed())
// Assert for Epoch Nanos TimeEncoder
Expect(string(outRaw)).Should(ContainSubstring("."))
// Assert for MessageKey
Expect(string(outRaw)).Should(ContainSubstring("MillisTimeFormat"))
})

})
})

0 comments on commit eccba7c

Please sign in to comment.