Skip to content

Commit dec6d16

Browse files
authored
feat: add new v2 zap logger package to CNS
Signed-off-by: Evan Baker <[email protected]>
1 parent 2d2b9d4 commit dec6d16

File tree

9 files changed

+203
-2
lines changed

9 files changed

+203
-2
lines changed

cns/logger/v2/cores/ai.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package logger
2+
3+
import (
4+
"runtime"
5+
"time"
6+
7+
"github.com/Azure/azure-container-networking/zapai"
8+
"github.com/microsoft/ApplicationInsights-Go/appinsights"
9+
"github.com/pkg/errors"
10+
"go.uber.org/zap"
11+
"go.uber.org/zap/zapcore"
12+
)
13+
14+
type AIConfig struct {
15+
GracePeriod time.Duration
16+
IKey string
17+
Level zapcore.Level
18+
MaxBatchInterval time.Duration
19+
MaxBatchSize int
20+
}
21+
22+
// ApplicationInsightsCore builds a zapcore.Core that sends logs to Application Insights.
23+
// The first return is the core, the second is a function to close the sink.
24+
func ApplicationInsightsCore(cfg *AIConfig) (zapcore.Core, func(), error) {
25+
// build the AI config
26+
aicfg := *appinsights.NewTelemetryConfiguration(cfg.IKey)
27+
aicfg.MaxBatchSize = cfg.MaxBatchSize
28+
aicfg.MaxBatchInterval = cfg.MaxBatchInterval
29+
sinkcfg := zapai.SinkConfig{
30+
GracePeriod: cfg.GracePeriod,
31+
TelemetryConfiguration: aicfg,
32+
}
33+
// open the AI zap sink
34+
sink, aiclose, err := zap.Open(sinkcfg.URI())
35+
if err != nil {
36+
return nil, aiclose, errors.Wrap(err, "failed to open AI sink")
37+
}
38+
// build the AI core
39+
core := zapai.NewCore(cfg.Level, sink)
40+
core = core.WithFieldMappers(zapai.DefaultMappers)
41+
// add normalized fields for the built-in AI Tags
42+
// TODO(rbtr): move to the caller
43+
return core.With([]zapcore.Field{
44+
zap.String("user_id", runtime.GOOS),
45+
zap.String("operation_id", ""),
46+
zap.String("parent_id", "v0.0.0"),
47+
zap.String("version", "v0.0.0"),
48+
zap.String("account", "SubscriptionID"),
49+
zap.String("anonymous_user_id", "VMName"),
50+
zap.String("session_id", "VMID"),
51+
zap.String("AppName", "name"),
52+
zap.String("Region", "Location"),
53+
zap.String("ResourceGroup", "ResourceGroupName"),
54+
zap.String("VMSize", "VMSize"),
55+
zap.String("OSVersion", "OSVersion"),
56+
zap.String("VMID", "VMID"),
57+
}), aiclose, nil
58+
}

cns/logger/v2/cores/etw_windows.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package logger
2+
3+
import (
4+
"github.com/Azure/azure-container-networking/zapetw"
5+
6+
"go.uber.org/zap"
7+
"go.uber.org/zap/zapcore"
8+
)
9+
10+
type ETWConfig struct {
11+
EventName string
12+
Level zapcore.Level
13+
ProviderName string
14+
}
15+
16+
// ETWCore builds a zapcore.Core that sends logs to ETW.
17+
// The first return is the core, the second is a function to close the sink.
18+
func ETWCore(cfg *ETWConfig) (zapcore.Core, func(), error) {
19+
encoderConfig := zap.NewProductionEncoderConfig()
20+
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
21+
jsonEncoder := zapcore.NewJSONEncoder(encoderConfig)
22+
return zapetw.New(cfg.ProviderName, cfg.EventName, jsonEncoder, cfg.Level) //nolint:wrapcheck // ignore
23+
}

cns/logger/v2/cores/file.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package logger
2+
3+
import (
4+
"go.uber.org/zap"
5+
"go.uber.org/zap/zapcore"
6+
"gopkg.in/natefinch/lumberjack.v2"
7+
)
8+
9+
type FileConfig struct {
10+
Filepath string
11+
Level zapcore.Level
12+
MaxBackups int
13+
MaxSize int
14+
}
15+
16+
// FileCore builds a zapcore.Core that writes to a file.
17+
// The first return is the core, the second is a function to close the file.
18+
func FileCore(cfg *FileConfig) (zapcore.Core, func(), error) {
19+
filesink := &lumberjack.Logger{
20+
Filename: cfg.Filepath,
21+
MaxSize: cfg.MaxSize, // MegaBytes
22+
MaxBackups: cfg.MaxBackups,
23+
}
24+
encoderConfig := zap.NewProductionEncoderConfig()
25+
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
26+
jsonEncoder := zapcore.NewJSONEncoder(encoderConfig)
27+
return zapcore.NewCore(jsonEncoder, zapcore.AddSync(filesink), cfg.Level), func() { _ = filesink.Close() }, nil
28+
}

cns/logger/v2/cores/stdout.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package logger
2+
3+
import (
4+
"os"
5+
6+
logfmt "github.com/jsternberg/zap-logfmt"
7+
"go.uber.org/zap"
8+
"go.uber.org/zap/zapcore"
9+
)
10+
11+
// StdoutCore builds a zapcore.Core that writes to stdout.
12+
func StdoutCore(l zapcore.Level) zapcore.Core {
13+
encoderConfig := zap.NewProductionEncoderConfig()
14+
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
15+
return zapcore.NewCore(logfmt.NewEncoder(encoderConfig), os.Stdout, l)
16+
}

cns/logger/v2/logger.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package logger
2+
3+
import (
4+
cores "github.com/Azure/azure-container-networking/cns/logger/v2/cores"
5+
"go.uber.org/zap"
6+
"go.uber.org/zap/zapcore"
7+
)
8+
9+
type Config struct {
10+
// Level is the general logging Level. If cores have more specific config it will override this.
11+
Level zapcore.Level
12+
AIConfig cores.AIConfig
13+
FileConfig cores.FileConfig
14+
}
15+
16+
type compoundCloser []func()
17+
18+
func (c compoundCloser) Close() {
19+
for _, closer := range c {
20+
closer()
21+
}
22+
}
23+
24+
func New(cfg *Config) (*zap.Logger, func(), error) {
25+
stdoutCore := cores.StdoutCore(cfg.Level)
26+
closer := compoundCloser{}
27+
fileCore, fileCloser, err := cores.FileCore(&cfg.FileConfig)
28+
closer = append(closer, fileCloser)
29+
if err != nil {
30+
return nil, closer.Close, err //nolint:wrapcheck // it's an internal pkg
31+
}
32+
aiCore, aiCloser, err := cores.ApplicationInsightsCore(&cfg.AIConfig)
33+
closer = append(closer, aiCloser)
34+
if err != nil {
35+
return nil, closer.Close, err //nolint:wrapcheck // it's an internal pkg
36+
}
37+
platformCore, platformCloser, err := platformCore(cfg)
38+
closer = append(closer, platformCloser)
39+
if err != nil {
40+
return nil, closer.Close, err
41+
}
42+
core := zapcore.NewTee(stdoutCore, fileCore, aiCore, platformCore)
43+
return zap.New(core), closer.Close, nil
44+
}

cns/logger/v2/logger_linux.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package logger
2+
3+
import (
4+
"go.uber.org/zap/zapcore"
5+
)
6+
7+
// platformCore returns a no-op core for Linux.
8+
func platformCore(*Config) (zapcore.Core, func(), error) {
9+
return zapcore.NewNopCore(), func() {}, nil
10+
}

cns/logger/v2/logger_windows.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package logger
2+
3+
import (
4+
cores "github.com/Azure/azure-container-networking/cns/logger/v2/cores"
5+
"go.uber.org/zap/zapcore"
6+
)
7+
8+
// platformCore returns a zapcore.Core that sends logs to ETW.
9+
func platformCore(cfg *Config) (zapcore.Core, func(), error) {
10+
return cores.ETWCore(&cores.ETWConfig{ //nolint:wrapcheck // ignore
11+
EventName: "AzureCNS",
12+
Level: cfg.Level,
13+
ProviderName: "ACN-Monitoring",
14+
})
15+
}

go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ require (
6868
github.com/go-openapi/jsonpointer v0.20.0 // indirect
6969
github.com/go-openapi/jsonreference v0.20.2 // indirect
7070
github.com/go-openapi/swag v0.22.4 // indirect
71-
github.com/gofrs/uuid v3.3.0+incompatible // indirect
71+
github.com/gofrs/uuid v4.2.0+incompatible // indirect
7272
github.com/gogo/protobuf v1.3.2 // indirect
7373
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
7474
github.com/google/gofuzz v1.2.0 // indirect
@@ -125,11 +125,13 @@ require (
125125
)
126126

127127
require (
128+
github.com/Azure/azure-container-networking/zapai v0.0.3
128129
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.7.0-beta.1
129130
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dashboard/armdashboard v1.2.0
130131
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0
131132
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5 v5.2.0
132133
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0
134+
github.com/jsternberg/zap-logfmt v1.3.0
133135
golang.org/x/sync v0.11.0
134136
gotest.tools/v3 v3.5.1
135137
k8s.io/kubectl v0.28.5

go.sum

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
22
code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8=
33
code.cloudfoundry.org/clock v1.0.0 h1:kFXWQM4bxYvdBw2X8BbBeXwQNgfoWv1vqAk2ZZyBN2o=
44
code.cloudfoundry.org/clock v1.0.0/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8=
5+
github.com/Azure/azure-container-networking/zapai v0.0.3 h1:73druF1cnne5Ign/ztiXP99Ss5D+UJ80EL2mzPgNRhk=
6+
github.com/Azure/azure-container-networking/zapai v0.0.3/go.mod h1:XV/aKJQAV6KqV4HQtZlDyxg2z7LaY9rsX8dqwyWFmUI=
57
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ=
68
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ=
79
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.1 h1:1mvYtZfWQAnwNah/C+Z+Jb9rQH95LPE2vlmMuWAHJk8=
@@ -111,8 +113,9 @@ github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+
111113
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
112114
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
113115
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
114-
github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84=
115116
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
117+
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
118+
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
116119
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
117120
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
118121
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
175178
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
176179
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
177180
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
181+
github.com/jsternberg/zap-logfmt v1.3.0 h1:z1n1AOHVVydOOVuyphbOKyR4NICDQFiJMn1IK5hVQ5Y=
182+
github.com/jsternberg/zap-logfmt v1.3.0/go.mod h1:N3DENp9WNmCZxvkBD/eReWwz1149BK6jEN9cQ4fNwZE=
178183
github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs=
179184
github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw=
180185
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=

0 commit comments

Comments
 (0)