From 3762c0d10da73e593cb6464dd50f0071fd560035 Mon Sep 17 00:00:00 2001 From: Evan Baker Date: Thu, 20 Feb 2025 02:44:02 +0000 Subject: [PATCH 1/5] feat: add new v2 zap logger package to CNS Signed-off-by: Evan Baker --- cns/logger/v2/cores/ai.go | 58 ++++++++++++++++++++++++++++++ cns/logger/v2/cores/etw_windows.go | 22 ++++++++++++ cns/logger/v2/cores/file.go | 28 +++++++++++++++ cns/logger/v2/cores/stdout.go | 16 +++++++++ cns/logger/v2/logger.go | 44 +++++++++++++++++++++++ cns/logger/v2/logger_linux.go | 10 ++++++ cns/logger/v2/logger_windows.go | 15 ++++++++ go.mod | 4 ++- go.sum | 7 +++- 9 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 cns/logger/v2/cores/ai.go create mode 100644 cns/logger/v2/cores/etw_windows.go create mode 100644 cns/logger/v2/cores/file.go create mode 100644 cns/logger/v2/cores/stdout.go create mode 100644 cns/logger/v2/logger.go create mode 100644 cns/logger/v2/logger_linux.go create mode 100644 cns/logger/v2/logger_windows.go diff --git a/cns/logger/v2/cores/ai.go b/cns/logger/v2/cores/ai.go new file mode 100644 index 0000000000..41c51a8432 --- /dev/null +++ b/cns/logger/v2/cores/ai.go @@ -0,0 +1,58 @@ +package logger + +import ( + "runtime" + "time" + + "github.com/Azure/azure-container-networking/zapai" + "github.com/microsoft/ApplicationInsights-Go/appinsights" + "github.com/pkg/errors" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +type AIConfig struct { + GracePeriod time.Duration + IKey string + Level zapcore.Level + MaxBatchInterval time.Duration + MaxBatchSize int +} + +// ApplicationInsightsCore builds a zapcore.Core that sends logs to Application Insights. +// The first return is the core, the second is a function to close the sink. +func ApplicationInsightsCore(cfg *AIConfig) (zapcore.Core, func(), error) { + // build the AI config + aicfg := *appinsights.NewTelemetryConfiguration(cfg.IKey) + aicfg.MaxBatchSize = cfg.MaxBatchSize + aicfg.MaxBatchInterval = cfg.MaxBatchInterval + sinkcfg := zapai.SinkConfig{ + GracePeriod: cfg.GracePeriod, + TelemetryConfiguration: aicfg, + } + // open the AI zap sink + sink, aiclose, err := zap.Open(sinkcfg.URI()) + if err != nil { + return nil, aiclose, errors.Wrap(err, "failed to open AI sink") + } + // build the AI core + core := zapai.NewCore(cfg.Level, sink) + core = core.WithFieldMappers(zapai.DefaultMappers) + // add normalized fields for the built-in AI Tags + // TODO(rbtr): move to the caller + return core.With([]zapcore.Field{ + zap.String("user_id", runtime.GOOS), + zap.String("operation_id", ""), + zap.String("parent_id", "v0.0.0"), + zap.String("version", "v0.0.0"), + zap.String("account", "SubscriptionID"), + zap.String("anonymous_user_id", "VMName"), + zap.String("session_id", "VMID"), + zap.String("AppName", "name"), + zap.String("Region", "Location"), + zap.String("ResourceGroup", "ResourceGroupName"), + zap.String("VMSize", "VMSize"), + zap.String("OSVersion", "OSVersion"), + zap.String("VMID", "VMID"), + }), aiclose, nil +} diff --git a/cns/logger/v2/cores/etw_windows.go b/cns/logger/v2/cores/etw_windows.go new file mode 100644 index 0000000000..51e6656f48 --- /dev/null +++ b/cns/logger/v2/cores/etw_windows.go @@ -0,0 +1,22 @@ +package logger + +import ( + "github.com/Azure/azure-container-networking/zapetw" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +type ETWConfig struct { + EventName string + Level zapcore.Level + ProviderName string +} + +// ETWCore builds a zapcore.Core that sends logs to ETW. +// The first return is the core, the second is a function to close the sink. +func ETWCore(cfg *ETWConfig) (zapcore.Core, func(), error) { + encoderConfig := zap.NewProductionEncoderConfig() + encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + jsonEncoder := zapcore.NewJSONEncoder(encoderConfig) + return zapetw.New(cfg.ProviderName, cfg.EventName, jsonEncoder, cfg.Level) //nolint:wrapcheck // ignore +} diff --git a/cns/logger/v2/cores/file.go b/cns/logger/v2/cores/file.go new file mode 100644 index 0000000000..19c208f84d --- /dev/null +++ b/cns/logger/v2/cores/file.go @@ -0,0 +1,28 @@ +package logger + +import ( + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "gopkg.in/natefinch/lumberjack.v2" +) + +type FileConfig struct { + Filepath string + Level zapcore.Level + MaxBackups int + MaxSize int +} + +// FileCore builds a zapcore.Core that writes to a file. +// The first return is the core, the second is a function to close the file. +func FileCore(cfg *FileConfig) (zapcore.Core, func(), error) { + filesink := &lumberjack.Logger{ + Filename: cfg.Filepath, + MaxSize: cfg.MaxSize, // MegaBytes + MaxBackups: cfg.MaxBackups, + } + encoderConfig := zap.NewProductionEncoderConfig() + encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + jsonEncoder := zapcore.NewJSONEncoder(encoderConfig) + return zapcore.NewCore(jsonEncoder, zapcore.AddSync(filesink), cfg.Level), func() { _ = filesink.Close() }, nil +} diff --git a/cns/logger/v2/cores/stdout.go b/cns/logger/v2/cores/stdout.go new file mode 100644 index 0000000000..93ad09767a --- /dev/null +++ b/cns/logger/v2/cores/stdout.go @@ -0,0 +1,16 @@ +package logger + +import ( + "os" + + logfmt "github.com/jsternberg/zap-logfmt" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +// StdoutCore builds a zapcore.Core that writes to stdout. +func StdoutCore(l zapcore.Level) zapcore.Core { + encoderConfig := zap.NewProductionEncoderConfig() + encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + return zapcore.NewCore(logfmt.NewEncoder(encoderConfig), os.Stdout, l) +} diff --git a/cns/logger/v2/logger.go b/cns/logger/v2/logger.go new file mode 100644 index 0000000000..55ac056798 --- /dev/null +++ b/cns/logger/v2/logger.go @@ -0,0 +1,44 @@ +package logger + +import ( + cores "github.com/Azure/azure-container-networking/cns/logger/v2/cores" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +type Config struct { + // Level is the general logging Level. If cores have more specific config it will override this. + Level zapcore.Level + AIConfig cores.AIConfig + FileConfig cores.FileConfig +} + +type compoundCloser []func() + +func (c compoundCloser) Close() { + for _, closer := range c { + closer() + } +} + +func New(cfg *Config) (*zap.Logger, func(), error) { + stdoutCore := cores.StdoutCore(cfg.Level) + closer := compoundCloser{} + fileCore, fileCloser, err := cores.FileCore(&cfg.FileConfig) + closer = append(closer, fileCloser) + if err != nil { + return nil, closer.Close, err //nolint:wrapcheck // it's an internal pkg + } + aiCore, aiCloser, err := cores.ApplicationInsightsCore(&cfg.AIConfig) + closer = append(closer, aiCloser) + if err != nil { + return nil, closer.Close, err //nolint:wrapcheck // it's an internal pkg + } + platformCore, platformCloser, err := platformCore(cfg) + closer = append(closer, platformCloser) + if err != nil { + return nil, closer.Close, err + } + core := zapcore.NewTee(stdoutCore, fileCore, aiCore, platformCore) + return zap.New(core), closer.Close, nil +} diff --git a/cns/logger/v2/logger_linux.go b/cns/logger/v2/logger_linux.go new file mode 100644 index 0000000000..c875f3faaf --- /dev/null +++ b/cns/logger/v2/logger_linux.go @@ -0,0 +1,10 @@ +package logger + +import ( + "go.uber.org/zap/zapcore" +) + +// platformCore returns a no-op core for Linux. +func platformCore(*Config) (zapcore.Core, func(), error) { + return zapcore.NewNopCore(), func() {}, nil +} diff --git a/cns/logger/v2/logger_windows.go b/cns/logger/v2/logger_windows.go new file mode 100644 index 0000000000..018afd17a5 --- /dev/null +++ b/cns/logger/v2/logger_windows.go @@ -0,0 +1,15 @@ +package logger + +import ( + cores "github.com/Azure/azure-container-networking/cns/logger/v2/cores" + "go.uber.org/zap/zapcore" +) + +// platformCore returns a zapcore.Core that sends logs to ETW. +func platformCore(cfg *Config) (zapcore.Core, func(), error) { + return cores.ETWCore(&cores.ETWConfig{ //nolint:wrapcheck // ignore + EventName: "AzureCNS", + Level: cfg.Level, + ProviderName: "ACN-Monitoring", + }) +} diff --git a/go.mod b/go.mod index c8fc32d2b3..b9eaf712fc 100644 --- a/go.mod +++ b/go.mod @@ -68,7 +68,7 @@ require ( github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.4 // indirect - github.com/gofrs/uuid v3.3.0+incompatible // indirect + github.com/gofrs/uuid v4.2.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -125,11 +125,13 @@ require ( ) require ( + github.com/Azure/azure-container-networking/zapai v0.0.3 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.7.0-beta.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 + github.com/jsternberg/zap-logfmt v1.3.0 golang.org/x/sync v0.11.0 gotest.tools/v3 v3.5.2 k8s.io/kubectl v0.28.5 diff --git a/go.sum b/go.sum index 8ea6a3e523..c7b862b562 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= code.cloudfoundry.org/clock v1.0.0 h1:kFXWQM4bxYvdBw2X8BbBeXwQNgfoWv1vqAk2ZZyBN2o= code.cloudfoundry.org/clock v1.0.0/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= +github.com/Azure/azure-container-networking/zapai v0.0.3 h1:73druF1cnne5Ign/ztiXP99Ss5D+UJ80EL2mzPgNRhk= +github.com/Azure/azure-container-networking/zapai v0.0.3/go.mod h1:XV/aKJQAV6KqV4HQtZlDyxg2z7LaY9rsX8dqwyWFmUI= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys= @@ -111,8 +113,9 @@ github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= +github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= @@ -175,6 +178,8 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jsternberg/zap-logfmt v1.3.0 h1:z1n1AOHVVydOOVuyphbOKyR4NICDQFiJMn1IK5hVQ5Y= +github.com/jsternberg/zap-logfmt v1.3.0/go.mod h1:N3DENp9WNmCZxvkBD/eReWwz1149BK6jEN9cQ4fNwZE= github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= From d3bbfc8ef623dc039b090b7ccf2ea77cf922d3bc Mon Sep 17 00:00:00 2001 From: Evan Baker Date: Fri, 21 Feb 2025 21:01:38 +0000 Subject: [PATCH 2/5] update loggerv2 configs, add custom Unmarshalling Signed-off-by: Evan Baker --- cns/logger/log.go | 5 +-- cns/logger/v2/config.go | 50 +++++++++++++++++++++++++++++ cns/logger/v2/cores/ai.go | 57 +++++++++++++++++++-------------- cns/logger/v2/cores/file.go | 37 +++++++++++++++++---- cns/logger/v2/logger.go | 13 ++------ cns/logger/v2/logger_linux.go | 2 ++ cns/logger/v2/logger_windows.go | 4 ++- 7 files changed, 125 insertions(+), 43 deletions(-) create mode 100644 cns/logger/v2/config.go diff --git a/cns/logger/log.go b/cns/logger/log.go index 3397e132c1..ec1d32056d 100644 --- a/cns/logger/log.go +++ b/cns/logger/log.go @@ -7,8 +7,9 @@ import ( ) var ( - Log *CNSLogger - aiMetadata string // this var is set at build time. + Log *CNSLogger + aiMetadata string // this var is set at build time. + AppInsightsIKey = aiMetadata ) // todo: the functions below should be removed. CNSLogger should be injected where needed and not used from package level scope. diff --git a/cns/logger/v2/config.go b/cns/logger/v2/config.go new file mode 100644 index 0000000000..78fee15051 --- /dev/null +++ b/cns/logger/v2/config.go @@ -0,0 +1,50 @@ +package logger + +import ( + "encoding/json" + "time" + + loggerv1 "github.com/Azure/azure-container-networking/cns/logger" + cores "github.com/Azure/azure-container-networking/cns/logger/v2/cores" + "github.com/pkg/errors" + "go.uber.org/zap/zapcore" +) + +//nolint:unused // will be used +const ( + defaultMaxBackups = 10 + defaultMaxSize = 10 // MB + defaultMaxBatchInterval = 30 * time.Second + defaultMaxBatchSize = 32000 + defaultGracePeriod = 30 * time.Second +) + +//nolint:unused // will be used +var defaultIKey = loggerv1.AppInsightsIKey + +type Config struct { + // Level is the general logging Level. If cores have more specific config it will override this. + Level string `json:"level"` + level zapcore.Level `json:"-"` + AppInsights cores.AppInsightsConfig `json:"appInsights"` + File cores.FileConfig `json:"file"` +} + +// UnmarshalJSON implements json.Unmarshaler for the Config. +// It only differs from the default by parsing the +// Level string into a zapcore.Level and setting the level field. +func (c *Config) UnmarshalJSON(data []byte) error { + type Alias Config + aux := &struct { + *Alias + }{ + Alias: (*Alias)(c), + } + if err := json.Unmarshal(data, &aux); err != nil { + return errors.Wrap(err, "failed to unmarshal Config") + } + if l, err := zapcore.ParseLevel(c.Level); err == nil { + c.level = l + } + return nil +} diff --git a/cns/logger/v2/cores/ai.go b/cns/logger/v2/cores/ai.go index 41c51a8432..ee9b8c67a7 100644 --- a/cns/logger/v2/cores/ai.go +++ b/cns/logger/v2/cores/ai.go @@ -1,7 +1,7 @@ package logger import ( - "runtime" + "encoding/json" "time" "github.com/Azure/azure-container-networking/zapai" @@ -11,17 +11,40 @@ import ( "go.uber.org/zap/zapcore" ) -type AIConfig struct { - GracePeriod time.Duration - IKey string - Level zapcore.Level - MaxBatchInterval time.Duration - MaxBatchSize int +type AppInsightsConfig struct { + GracePeriod time.Duration `json:"grace_period"` + IKey string `json:"ikey"` + Level string `json:"level"` + level zapcore.Level `json:"-"` // Zero value is default Info level. + MaxBatchInterval time.Duration `json:"max_batch_interval"` + MaxBatchSize int `json:"max_batch_size"` + Fields []zapcore.Field `json:"fields"` +} + +// UnmarshalJSON implements json.Unmarshaler for the Config. +// It only differs from the default by parsing the +// Level string into a zapcore.Level and setting the level field. +func (c *AppInsightsConfig) UnmarshalJSON(data []byte) error { + type Alias AppInsightsConfig + aux := &struct { + *Alias + }{ + Alias: (*Alias)(c), + } + if err := json.Unmarshal(data, &aux); err != nil { + return errors.Wrap(err, "failed to unmarshal AppInsightsConfig") + } + lvl, err := zapcore.ParseLevel(c.Level) + if err != nil { + return errors.Wrap(err, "failed to parse AppInsightsConfig Level") + } + c.level = lvl + return nil } // ApplicationInsightsCore builds a zapcore.Core that sends logs to Application Insights. // The first return is the core, the second is a function to close the sink. -func ApplicationInsightsCore(cfg *AIConfig) (zapcore.Core, func(), error) { +func ApplicationInsightsCore(cfg *AppInsightsConfig) (zapcore.Core, func(), error) { // build the AI config aicfg := *appinsights.NewTelemetryConfiguration(cfg.IKey) aicfg.MaxBatchSize = cfg.MaxBatchSize @@ -36,23 +59,9 @@ func ApplicationInsightsCore(cfg *AIConfig) (zapcore.Core, func(), error) { return nil, aiclose, errors.Wrap(err, "failed to open AI sink") } // build the AI core - core := zapai.NewCore(cfg.Level, sink) + core := zapai.NewCore(cfg.level, sink) core = core.WithFieldMappers(zapai.DefaultMappers) // add normalized fields for the built-in AI Tags // TODO(rbtr): move to the caller - return core.With([]zapcore.Field{ - zap.String("user_id", runtime.GOOS), - zap.String("operation_id", ""), - zap.String("parent_id", "v0.0.0"), - zap.String("version", "v0.0.0"), - zap.String("account", "SubscriptionID"), - zap.String("anonymous_user_id", "VMName"), - zap.String("session_id", "VMID"), - zap.String("AppName", "name"), - zap.String("Region", "Location"), - zap.String("ResourceGroup", "ResourceGroupName"), - zap.String("VMSize", "VMSize"), - zap.String("OSVersion", "OSVersion"), - zap.String("VMID", "VMID"), - }), aiclose, nil + return core.With(cfg.Fields), aiclose, nil } diff --git a/cns/logger/v2/cores/file.go b/cns/logger/v2/cores/file.go index 19c208f84d..21b6b1182a 100644 --- a/cns/logger/v2/cores/file.go +++ b/cns/logger/v2/cores/file.go @@ -1,16 +1,41 @@ package logger import ( + "encoding/json" + + "github.com/pkg/errors" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) type FileConfig struct { - Filepath string - Level zapcore.Level - MaxBackups int - MaxSize int + Filepath string `json:"filepath"` + Level string `json:"level"` + level zapcore.Level `json:"-"` + MaxBackups int `json:"maxBackups"` + MaxSize int `json:"maxSize"` +} + +// UnmarshalJSON implements json.Unmarshaler for the Config. +// It only differs from the default by parsing the +// Level string into a zapcore.Level and setting the level field. +func (cfg *FileConfig) UnmarshalJSON(data []byte) error { + type Alias FileConfig + aux := &struct { + *Alias + }{ + Alias: (*Alias)(cfg), + } + if err := json.Unmarshal(data, &aux); err != nil { + return errors.Wrap(err, "failed to unmarshal FileConfig") + } + lvl, err := zapcore.ParseLevel(cfg.Level) + if err != nil { + return errors.Wrap(err, "failed to parse FileConfig Level") + } + cfg.level = lvl + return nil } // FileCore builds a zapcore.Core that writes to a file. @@ -18,11 +43,11 @@ type FileConfig struct { func FileCore(cfg *FileConfig) (zapcore.Core, func(), error) { filesink := &lumberjack.Logger{ Filename: cfg.Filepath, - MaxSize: cfg.MaxSize, // MegaBytes + MaxSize: cfg.MaxSize, // MB MaxBackups: cfg.MaxBackups, } encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder jsonEncoder := zapcore.NewJSONEncoder(encoderConfig) - return zapcore.NewCore(jsonEncoder, zapcore.AddSync(filesink), cfg.Level), func() { _ = filesink.Close() }, nil + return zapcore.NewCore(jsonEncoder, zapcore.AddSync(filesink), cfg.level), func() { _ = filesink.Close() }, nil } diff --git a/cns/logger/v2/logger.go b/cns/logger/v2/logger.go index 55ac056798..fca193c37b 100644 --- a/cns/logger/v2/logger.go +++ b/cns/logger/v2/logger.go @@ -6,13 +6,6 @@ import ( "go.uber.org/zap/zapcore" ) -type Config struct { - // Level is the general logging Level. If cores have more specific config it will override this. - Level zapcore.Level - AIConfig cores.AIConfig - FileConfig cores.FileConfig -} - type compoundCloser []func() func (c compoundCloser) Close() { @@ -22,14 +15,14 @@ func (c compoundCloser) Close() { } func New(cfg *Config) (*zap.Logger, func(), error) { - stdoutCore := cores.StdoutCore(cfg.Level) + stdoutCore := cores.StdoutCore(cfg.level) closer := compoundCloser{} - fileCore, fileCloser, err := cores.FileCore(&cfg.FileConfig) + fileCore, fileCloser, err := cores.FileCore(&cfg.File) closer = append(closer, fileCloser) if err != nil { return nil, closer.Close, err //nolint:wrapcheck // it's an internal pkg } - aiCore, aiCloser, err := cores.ApplicationInsightsCore(&cfg.AIConfig) + aiCore, aiCloser, err := cores.ApplicationInsightsCore(&cfg.AppInsights) closer = append(closer, aiCloser) if err != nil { return nil, closer.Close, err //nolint:wrapcheck // it's an internal pkg diff --git a/cns/logger/v2/logger_linux.go b/cns/logger/v2/logger_linux.go index c875f3faaf..ff03120ea6 100644 --- a/cns/logger/v2/logger_linux.go +++ b/cns/logger/v2/logger_linux.go @@ -4,6 +4,8 @@ import ( "go.uber.org/zap/zapcore" ) +const defaultFilePath = "/var/log/azure-cns.log" + // platformCore returns a no-op core for Linux. func platformCore(*Config) (zapcore.Core, func(), error) { return zapcore.NewNopCore(), func() {}, nil diff --git a/cns/logger/v2/logger_windows.go b/cns/logger/v2/logger_windows.go index 018afd17a5..01ddbfd21e 100644 --- a/cns/logger/v2/logger_windows.go +++ b/cns/logger/v2/logger_windows.go @@ -5,11 +5,13 @@ import ( "go.uber.org/zap/zapcore" ) +const defaultFilePath = "/k/azurecns/azure-cns.log" + // platformCore returns a zapcore.Core that sends logs to ETW. func platformCore(cfg *Config) (zapcore.Core, func(), error) { return cores.ETWCore(&cores.ETWConfig{ //nolint:wrapcheck // ignore EventName: "AzureCNS", - Level: cfg.Level, + Level: cfg.level, ProviderName: "ACN-Monitoring", }) } From 804180eb6cef4df1ecd94e576aa9c1cbdbc13da9 Mon Sep 17 00:00:00 2001 From: Evan Baker Date: Fri, 21 Feb 2025 23:53:07 +0000 Subject: [PATCH 3/5] add custom Duration type, tests, cores enabled by config Signed-off-by: Evan Baker --- cns/logger/v2/config.go | 15 ++------ cns/logger/v2/config_linux.go | 16 ++++++++ cns/logger/v2/config_test.go | 55 +++++++++++++++++++++++++++ cns/logger/v2/config_windows.go | 17 +++++++++ cns/logger/v2/cores/ai.go | 6 +-- cns/logger/v2/cores/ai_test.go | 48 ++++++++++++++++++++++++ cns/logger/v2/cores/file_test.go | 47 +++++++++++++++++++++++ cns/logger/v2/logger.go | 26 ++++++++----- cns/logger/v2/logger_linux.go | 2 - cns/logger/v2/logger_windows.go | 11 ++---- internal/time/duration.go | 30 +++++++++++++++ internal/time/duration_test.go | 64 ++++++++++++++++++++++++++++++++ 12 files changed, 304 insertions(+), 33 deletions(-) create mode 100644 cns/logger/v2/config_linux.go create mode 100644 cns/logger/v2/config_test.go create mode 100644 cns/logger/v2/config_windows.go create mode 100644 cns/logger/v2/cores/ai_test.go create mode 100644 cns/logger/v2/cores/file_test.go create mode 100644 internal/time/duration.go create mode 100644 internal/time/duration_test.go diff --git a/cns/logger/v2/config.go b/cns/logger/v2/config.go index 78fee15051..b10e3c1b47 100644 --- a/cns/logger/v2/config.go +++ b/cns/logger/v2/config.go @@ -5,7 +5,6 @@ import ( "time" loggerv1 "github.com/Azure/azure-container-networking/cns/logger" - cores "github.com/Azure/azure-container-networking/cns/logger/v2/cores" "github.com/pkg/errors" "go.uber.org/zap/zapcore" ) @@ -22,14 +21,6 @@ const ( //nolint:unused // will be used var defaultIKey = loggerv1.AppInsightsIKey -type Config struct { - // Level is the general logging Level. If cores have more specific config it will override this. - Level string `json:"level"` - level zapcore.Level `json:"-"` - AppInsights cores.AppInsightsConfig `json:"appInsights"` - File cores.FileConfig `json:"file"` -} - // UnmarshalJSON implements json.Unmarshaler for the Config. // It only differs from the default by parsing the // Level string into a zapcore.Level and setting the level field. @@ -43,8 +34,10 @@ func (c *Config) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &aux); err != nil { return errors.Wrap(err, "failed to unmarshal Config") } - if l, err := zapcore.ParseLevel(c.Level); err == nil { - c.level = l + lvl, err := zapcore.ParseLevel(c.Level) + if err != nil { + return errors.Wrap(err, "failed to parse Config Level") } + c.level = lvl return nil } diff --git a/cns/logger/v2/config_linux.go b/cns/logger/v2/config_linux.go new file mode 100644 index 0000000000..6432adc4ce --- /dev/null +++ b/cns/logger/v2/config_linux.go @@ -0,0 +1,16 @@ +package logger + +import ( + cores "github.com/Azure/azure-container-networking/cns/logger/v2/cores" + "go.uber.org/zap/zapcore" +) + +const defaultFilePath = "/var/log/azure-cns.log" + +type Config struct { + // Level is the general logging Level. If cores have more specific config it will override this. + Level string `json:"level"` + level zapcore.Level `json:"-"` + AppInsights *cores.AppInsightsConfig `json:"appInsights,omitempty"` + File *cores.FileConfig `json:"file,omitempty"` +} diff --git a/cns/logger/v2/config_test.go b/cns/logger/v2/config_test.go new file mode 100644 index 0000000000..1295cd663b --- /dev/null +++ b/cns/logger/v2/config_test.go @@ -0,0 +1,55 @@ +package logger + +import ( + "encoding/json" + "testing" + + cores "github.com/Azure/azure-container-networking/cns/logger/v2/cores" + "github.com/stretchr/testify/require" +) + +func TestUnmarshalJSON(t *testing.T) { + tests := []struct { + name string + have []byte + want *Config + wantErr bool + }{ + { + name: "valid", + have: []byte(`{"level":"info"}`), + want: &Config{ + Level: "info", + level: 0, + }, + }, + { + name: "invalid level", + have: []byte(`{"level":"invalid"}`), + wantErr: true, + }, + { + name: "valid with file", + have: []byte(`{"level":"info","file":{"filepath":"/k/azurecns/azure-cns.log"}}`), + want: &Config{ + Level: "info", + level: 0, + File: &cores.FileConfig{ + Filepath: "/k/azurecns/azure-cns.log", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &Config{} + err := json.Unmarshal(tt.have, c) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tt.want, c) + }) + } +} diff --git a/cns/logger/v2/config_windows.go b/cns/logger/v2/config_windows.go new file mode 100644 index 0000000000..b4cda2f3ad --- /dev/null +++ b/cns/logger/v2/config_windows.go @@ -0,0 +1,17 @@ +package logger + +import ( + cores "github.com/Azure/azure-container-networking/cns/logger/v2/cores" + "go.uber.org/zap/zapcore" +) + +const defaultFilePath = "/k/azurecns/azure-cns.log" + +type Config struct { + // Level is the general logging Level. If cores have more specific config it will override this. + Level string `json:"level"` + level zapcore.Level `json:"-"` + AppInsights *cores.AppInsightsConfig `json:"appInsights,omitempty"` + File *cores.FileConfig `json:"file,omitempty"` + ETW *cores.ETWConfig `json:"etw,omitempty"` +} diff --git a/cns/logger/v2/cores/ai.go b/cns/logger/v2/cores/ai.go index ee9b8c67a7..63232e69ff 100644 --- a/cns/logger/v2/cores/ai.go +++ b/cns/logger/v2/cores/ai.go @@ -2,8 +2,8 @@ package logger import ( "encoding/json" - "time" + "github.com/Azure/azure-container-networking/internal/time" "github.com/Azure/azure-container-networking/zapai" "github.com/microsoft/ApplicationInsights-Go/appinsights" "github.com/pkg/errors" @@ -48,9 +48,9 @@ func ApplicationInsightsCore(cfg *AppInsightsConfig) (zapcore.Core, func(), erro // build the AI config aicfg := *appinsights.NewTelemetryConfiguration(cfg.IKey) aicfg.MaxBatchSize = cfg.MaxBatchSize - aicfg.MaxBatchInterval = cfg.MaxBatchInterval + aicfg.MaxBatchInterval = cfg.MaxBatchInterval.Duration sinkcfg := zapai.SinkConfig{ - GracePeriod: cfg.GracePeriod, + GracePeriod: cfg.GracePeriod.Duration, TelemetryConfiguration: aicfg, } // open the AI zap sink diff --git a/cns/logger/v2/cores/ai_test.go b/cns/logger/v2/cores/ai_test.go new file mode 100644 index 0000000000..e81e2fc15b --- /dev/null +++ b/cns/logger/v2/cores/ai_test.go @@ -0,0 +1,48 @@ +package logger + +import ( + "encoding/json" + "testing" + + "github.com/Azure/azure-container-networking/internal/time" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" +) + +func TestAIConfigUnmarshalJSON(t *testing.T) { + tests := []struct { + name string + have []byte + want *AppInsightsConfig + wantErr bool + }{ + { + name: "valid", + have: []byte(`{"grace_period":"30s","level":"panic","max_batch_interval":"30s","max_batch_size":32000}`), + want: &AppInsightsConfig{ + GracePeriod: time.Duration{30 * time.Second}, + Level: "panic", + level: zapcore.PanicLevel, + MaxBatchInterval: time.Duration{30 * time.Second}, + MaxBatchSize: 32000, + }, + }, + { + name: "invalid level", + have: []byte(`{"level":"invalid"}`), + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &AppInsightsConfig{} + err := json.Unmarshal(tt.have, c) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tt.want, c) + }) + } +} diff --git a/cns/logger/v2/cores/file_test.go b/cns/logger/v2/cores/file_test.go new file mode 100644 index 0000000000..4fde7c3e04 --- /dev/null +++ b/cns/logger/v2/cores/file_test.go @@ -0,0 +1,47 @@ +package logger + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" +) + +func TestFileConfig_UnmarshalJSON(t *testing.T) { + tests := []struct { + name string + have []byte + want *FileConfig + wantErr bool + }{ + { + name: "valid", + have: []byte(`{"filepath":"test.log","level":"debug","maxBackups":5,"maxSize":10}`), + want: &FileConfig{ + Filepath: "test.log", + Level: "debug", + level: zapcore.DebugLevel, + MaxBackups: 5, + MaxSize: 10, + }, + }, + { + name: "invalid level", + have: []byte(`{"filepath":"test.log","level":"invalid","maxBackups":5,"maxSize":10}`), + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &FileConfig{} + err := json.Unmarshal(tt.have, c) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tt.want, c) + }) + } +} diff --git a/cns/logger/v2/logger.go b/cns/logger/v2/logger.go index fca193c37b..36a9450d9f 100644 --- a/cns/logger/v2/logger.go +++ b/cns/logger/v2/logger.go @@ -15,23 +15,29 @@ func (c compoundCloser) Close() { } func New(cfg *Config) (*zap.Logger, func(), error) { - stdoutCore := cores.StdoutCore(cfg.level) + core := cores.StdoutCore(cfg.level) closer := compoundCloser{} - fileCore, fileCloser, err := cores.FileCore(&cfg.File) - closer = append(closer, fileCloser) - if err != nil { - return nil, closer.Close, err //nolint:wrapcheck // it's an internal pkg + if cfg.File != nil { + fileCore, fileCloser, err := cores.FileCore(cfg.File) + closer = append(closer, fileCloser) + if err != nil { + return nil, closer.Close, err //nolint:wrapcheck // it's an internal pkg + } + core = zapcore.NewTee(core, fileCore) } - aiCore, aiCloser, err := cores.ApplicationInsightsCore(&cfg.AppInsights) - closer = append(closer, aiCloser) - if err != nil { - return nil, closer.Close, err //nolint:wrapcheck // it's an internal pkg + if cfg.AppInsights != nil { + aiCore, aiCloser, err := cores.ApplicationInsightsCore(cfg.AppInsights) + closer = append(closer, aiCloser) + if err != nil { + return nil, closer.Close, err //nolint:wrapcheck // it's an internal pkg + } + core = zapcore.NewTee(core, aiCore) } platformCore, platformCloser, err := platformCore(cfg) closer = append(closer, platformCloser) if err != nil { return nil, closer.Close, err } - core := zapcore.NewTee(stdoutCore, fileCore, aiCore, platformCore) + core = zapcore.NewTee(core, platformCore) return zap.New(core), closer.Close, nil } diff --git a/cns/logger/v2/logger_linux.go b/cns/logger/v2/logger_linux.go index ff03120ea6..c875f3faaf 100644 --- a/cns/logger/v2/logger_linux.go +++ b/cns/logger/v2/logger_linux.go @@ -4,8 +4,6 @@ import ( "go.uber.org/zap/zapcore" ) -const defaultFilePath = "/var/log/azure-cns.log" - // platformCore returns a no-op core for Linux. func platformCore(*Config) (zapcore.Core, func(), error) { return zapcore.NewNopCore(), func() {}, nil diff --git a/cns/logger/v2/logger_windows.go b/cns/logger/v2/logger_windows.go index 01ddbfd21e..f72be04985 100644 --- a/cns/logger/v2/logger_windows.go +++ b/cns/logger/v2/logger_windows.go @@ -5,13 +5,10 @@ import ( "go.uber.org/zap/zapcore" ) -const defaultFilePath = "/k/azurecns/azure-cns.log" - // platformCore returns a zapcore.Core that sends logs to ETW. func platformCore(cfg *Config) (zapcore.Core, func(), error) { - return cores.ETWCore(&cores.ETWConfig{ //nolint:wrapcheck // ignore - EventName: "AzureCNS", - Level: cfg.level, - ProviderName: "ACN-Monitoring", - }) + if cfg.ETW == nil { + return zapcore.NewNopCore(), func() {}, nil + } + return cores.ETWCore(cfg.ETW) } diff --git a/internal/time/duration.go b/internal/time/duration.go new file mode 100644 index 0000000000..ae14f794b2 --- /dev/null +++ b/internal/time/duration.go @@ -0,0 +1,30 @@ +package time + +import ( + "encoding/json" + "time" +) + +const Second = time.Second + +type Duration struct { + time.Duration +} + +func (d Duration) MarshalJSON() ([]byte, error) { + return json.Marshal(d.String()) //nolint:wrapcheck // ignore +} + +func (d *Duration) UnmarshalJSON(b []byte) error { + var s string + err := json.Unmarshal(b, &s) + if err != nil { + return err //nolint:wrapcheck // ignore + } + duration, err := time.ParseDuration(s) + if err != nil { + return err //nolint:wrapcheck // ignore + } + d.Duration = duration + return nil +} diff --git a/internal/time/duration_test.go b/internal/time/duration_test.go new file mode 100644 index 0000000000..d35b5772b0 --- /dev/null +++ b/internal/time/duration_test.go @@ -0,0 +1,64 @@ +package time + +import ( + "encoding/json" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestDurationMarshalJSON(t *testing.T) { + tests := []struct { + name string + have Duration + want []byte + wantErr bool + }{ + { + name: "valid", + have: Duration{30 * time.Second}, + want: []byte(`"30s"`), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := json.Marshal(tt.have) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tt.want, got) + }) + } +} + +func TestDurationUnmarshalJSON(t *testing.T) { + tests := []struct { + name string + have []byte + want Duration + wantErr bool + }{ + { + name: "valid", + have: []byte(`"30s"`), + want: Duration{30 * time.Second}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := &Duration{} + err := json.Unmarshal(tt.have, got) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tt.want, *got) + }) + } +} From 7b10cb3b58b86085bc634681ce84ca1874ad6117 Mon Sep 17 00:00:00 2001 From: Evan Baker Date: Sat, 22 Feb 2025 00:32:46 +0000 Subject: [PATCH 4/5] add config normalization for logger v2 Signed-off-by: Evan Baker --- cns/logger/v2/config.go | 33 ++++++++++++++++++++++++++++++++- cns/logger/v2/config_linux.go | 2 ++ cns/logger/v2/config_windows.go | 11 +++++++++++ cns/logger/v2/cores/ai.go | 6 +++--- cns/logger/v2/logger.go | 1 + 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/cns/logger/v2/config.go b/cns/logger/v2/config.go index b10e3c1b47..653dbcc711 100644 --- a/cns/logger/v2/config.go +++ b/cns/logger/v2/config.go @@ -2,9 +2,9 @@ package logger import ( "encoding/json" - "time" loggerv1 "github.com/Azure/azure-container-networking/cns/logger" + "github.com/Azure/azure-container-networking/internal/time" "github.com/pkg/errors" "go.uber.org/zap/zapcore" ) @@ -41,3 +41,34 @@ func (c *Config) UnmarshalJSON(data []byte) error { c.level = lvl return nil } + +// Normalize checks the Config for missing or illegal values and sets them +// to defaults if appropriate. +func (c *Config) Normalize() { + if c.File != nil { + if c.File.Filepath == "" { + c.File.Filepath = defaultFilePath + } + if c.File.MaxBackups == 0 { + c.File.MaxBackups = defaultMaxBackups + } + if c.File.MaxSize == 0 { + c.File.MaxSize = defaultMaxSize + } + } + if c.AppInsights != nil { + if c.AppInsights.IKey == "" { + c.AppInsights.IKey = defaultIKey + } + if c.AppInsights.GracePeriod.Duration == 0 { + c.AppInsights.GracePeriod.Duration = defaultGracePeriod + } + if c.AppInsights.MaxBatchInterval.Duration == 0 { + c.AppInsights.MaxBatchInterval.Duration = defaultMaxBatchInterval + } + if c.AppInsights.MaxBatchSize == 0 { + c.AppInsights.MaxBatchSize = defaultMaxBatchSize + } + } + c.normalize() +} diff --git a/cns/logger/v2/config_linux.go b/cns/logger/v2/config_linux.go index 6432adc4ce..0b109ebaa2 100644 --- a/cns/logger/v2/config_linux.go +++ b/cns/logger/v2/config_linux.go @@ -14,3 +14,5 @@ type Config struct { AppInsights *cores.AppInsightsConfig `json:"appInsights,omitempty"` File *cores.FileConfig `json:"file,omitempty"` } + +func (c *Config) normalize() {} diff --git a/cns/logger/v2/config_windows.go b/cns/logger/v2/config_windows.go index b4cda2f3ad..f614e8797c 100644 --- a/cns/logger/v2/config_windows.go +++ b/cns/logger/v2/config_windows.go @@ -15,3 +15,14 @@ type Config struct { File *cores.FileConfig `json:"file,omitempty"` ETW *cores.ETWConfig `json:"etw,omitempty"` } + +func (c *Config) normalize() { + if c.ETW != nil { + if c.ETW.EventName == "" { + c.ETW.EventName = "AzureCNS" + } + if c.ETW.ProviderName == "" { + c.ETW.ProviderName = "ACN-Monitoring" + } + } +} diff --git a/cns/logger/v2/cores/ai.go b/cns/logger/v2/cores/ai.go index 63232e69ff..76ba6add65 100644 --- a/cns/logger/v2/cores/ai.go +++ b/cns/logger/v2/cores/ai.go @@ -12,10 +12,10 @@ import ( ) type AppInsightsConfig struct { - GracePeriod time.Duration `json:"grace_period"` - IKey string `json:"ikey"` - Level string `json:"level"` level zapcore.Level `json:"-"` // Zero value is default Info level. + Level string `json:"level"` + IKey string `json:"ikey"` + GracePeriod time.Duration `json:"grace_period"` MaxBatchInterval time.Duration `json:"max_batch_interval"` MaxBatchSize int `json:"max_batch_size"` Fields []zapcore.Field `json:"fields"` diff --git a/cns/logger/v2/logger.go b/cns/logger/v2/logger.go index 36a9450d9f..2064f18e1c 100644 --- a/cns/logger/v2/logger.go +++ b/cns/logger/v2/logger.go @@ -15,6 +15,7 @@ func (c compoundCloser) Close() { } func New(cfg *Config) (*zap.Logger, func(), error) { + cfg.Normalize() core := cores.StdoutCore(cfg.level) closer := compoundCloser{} if cfg.File != nil { From 975d9b9ecbc0500424f096a0c2772b86397a4b68 Mon Sep 17 00:00:00 2001 From: Evan Baker Date: Sat, 22 Feb 2025 01:17:10 +0000 Subject: [PATCH 5/5] lints Signed-off-by: Evan Baker --- cns/logger/v2/config.go | 2 +- cns/logger/v2/cores/ai_test.go | 4 ++-- cns/logger/v2/logger_windows.go | 2 +- internal/time/duration.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cns/logger/v2/config.go b/cns/logger/v2/config.go index 653dbcc711..d64d6486fa 100644 --- a/cns/logger/v2/config.go +++ b/cns/logger/v2/config.go @@ -31,7 +31,7 @@ func (c *Config) UnmarshalJSON(data []byte) error { }{ Alias: (*Alias)(c), } - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux); err != nil { //nolint:musttag // doesn't understand the embedding strategy return errors.Wrap(err, "failed to unmarshal Config") } lvl, err := zapcore.ParseLevel(c.Level) diff --git a/cns/logger/v2/cores/ai_test.go b/cns/logger/v2/cores/ai_test.go index e81e2fc15b..963d8d37c4 100644 --- a/cns/logger/v2/cores/ai_test.go +++ b/cns/logger/v2/cores/ai_test.go @@ -20,10 +20,10 @@ func TestAIConfigUnmarshalJSON(t *testing.T) { name: "valid", have: []byte(`{"grace_period":"30s","level":"panic","max_batch_interval":"30s","max_batch_size":32000}`), want: &AppInsightsConfig{ - GracePeriod: time.Duration{30 * time.Second}, + GracePeriod: time.Duration{Duration: 30 * time.Second}, Level: "panic", level: zapcore.PanicLevel, - MaxBatchInterval: time.Duration{30 * time.Second}, + MaxBatchInterval: time.Duration{Duration: 30 * time.Second}, MaxBatchSize: 32000, }, }, diff --git a/cns/logger/v2/logger_windows.go b/cns/logger/v2/logger_windows.go index f72be04985..e6e5f198dc 100644 --- a/cns/logger/v2/logger_windows.go +++ b/cns/logger/v2/logger_windows.go @@ -10,5 +10,5 @@ func platformCore(cfg *Config) (zapcore.Core, func(), error) { if cfg.ETW == nil { return zapcore.NewNopCore(), func() {}, nil } - return cores.ETWCore(cfg.ETW) + return cores.ETWCore(cfg.ETW) //nolint:wrapcheck // ignore } diff --git a/internal/time/duration.go b/internal/time/duration.go index ae14f794b2..f9a56dc0a7 100644 --- a/internal/time/duration.go +++ b/internal/time/duration.go @@ -5,7 +5,7 @@ import ( "time" ) -const Second = time.Second +const Second = time.Second //nolint:revive // it's not a suffix type Duration struct { time.Duration