Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions cns/logger/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
50 changes: 50 additions & 0 deletions cns/logger/v2/config.go
Original file line number Diff line number Diff line change
@@ -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
}
67 changes: 67 additions & 0 deletions cns/logger/v2/cores/ai.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package logger

import (
"encoding/json"
"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 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 *AppInsightsConfig) (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(cfg.Fields), aiclose, nil
}
22 changes: 22 additions & 0 deletions cns/logger/v2/cores/etw_windows.go
Original file line number Diff line number Diff line change
@@ -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
}
53 changes: 53 additions & 0 deletions cns/logger/v2/cores/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
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 `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.
// 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, // 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
}
16 changes: 16 additions & 0 deletions cns/logger/v2/cores/stdout.go
Original file line number Diff line number Diff line change
@@ -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)
}
37 changes: 37 additions & 0 deletions cns/logger/v2/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package logger

import (
cores "github.com/Azure/azure-container-networking/cns/logger/v2/cores"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

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.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.AppInsights)
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
}
12 changes: 12 additions & 0 deletions cns/logger/v2/logger_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package logger

import (
"go.uber.org/zap/zapcore"
)

const defaultFilePath = "/var/log/azure-cns.log"

Check failure on line 7 in cns/logger/v2/logger_linux.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, ubuntu-latest)

const `defaultFilePath` is unused (unused)

Check failure on line 7 in cns/logger/v2/logger_linux.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, ubuntu-latest)

const `defaultFilePath` is unused (unused)

// platformCore returns a no-op core for Linux.
func platformCore(*Config) (zapcore.Core, func(), error) {
return zapcore.NewNopCore(), func() {}, nil
}
17 changes: 17 additions & 0 deletions cns/logger/v2/logger_windows.go
Original file line number Diff line number Diff line change
@@ -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"

Check failure on line 8 in cns/logger/v2/logger_windows.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

const `defaultFilePath` is unused (unused)

Check failure on line 8 in cns/logger/v2/logger_windows.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

const `defaultFilePath` is unused (unused)

// 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",
})
}
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down Expand Up @@ -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=
Expand Down Expand Up @@ -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=
Expand Down
Loading