Skip to content

Commit 09cd3b2

Browse files
authored
feat: Enhancing ETW logging for CNI (#4426)
Enahancing ETW logging for CNS
1 parent 4e5da84 commit 09cd3b2

4 files changed

Lines changed: 91 additions & 1 deletion

File tree

cni/log/logger.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func initZapLog(logFile string) *zap.Logger {
3838
// If we fail to join the platform cores, fallback to the original core.
3939
core = textFileCore
4040
}
41-
return zap.New(core, zap.AddCaller()).With(zap.Int("pid", os.Getpid()))
41+
return zap.New(&metadataCore{Core: core}, zap.AddCaller()).With(zap.Int("pid", os.Getpid()))
4242
}
4343

4444
var (

cni/log/metadata_core.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package log
2+
3+
import (
4+
"fmt"
5+
"sync/atomic"
6+
7+
"go.uber.org/zap"
8+
"go.uber.org/zap/zapcore"
9+
)
10+
11+
// globalMetadata holds metadata fields shared across all loggers built from initZapLog.
12+
// It is set once from main() via SetMetadata after host metadata becomes available.
13+
var globalMetadata atomic.Pointer[[]zapcore.Field]
14+
15+
// SetMetadata sets metadata fields that will be appended to every log entry
16+
// written through CNILogger, IPamLogger, and TelemetryLogger (and any loggers
17+
// derived from them). Safe to call once from main() after metadata is available.
18+
func SetMetadata(fields ...zap.Field) {
19+
globalMetadata.Store(&fields)
20+
}
21+
22+
// metadataCore is a zapcore.Core wrapper that appends shared metadata fields
23+
// to every log entry at write time. All cores derived via With() share the
24+
// same globalMetadata pointer, so setting metadata once propagates everywhere.
25+
type metadataCore struct {
26+
zapcore.Core
27+
}
28+
29+
func (c *metadataCore) With(fields []zapcore.Field) zapcore.Core {
30+
return &metadataCore{Core: c.Core.With(fields)}
31+
}
32+
33+
// Check registers this wrapper (not the inner core) as the writer so that
34+
// Write is called on metadataCore, allowing metadata fields to be appended.
35+
func (c *metadataCore) Check(entry zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
36+
if c.Enabled(entry.Level) {
37+
return ce.AddCore(entry, c)
38+
}
39+
return ce
40+
}
41+
42+
func (c *metadataCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
43+
if extra := globalMetadata.Load(); extra != nil {
44+
fields = append(fields, *extra...)
45+
}
46+
if err := c.Core.Write(entry, fields); err != nil {
47+
return fmt.Errorf("writing log entry: %w", err)
48+
}
49+
return nil
50+
}

cni/network/plugin/main.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package main
66
import (
77
"fmt"
88
"os"
9+
"path/filepath"
910
"time"
1011

1112
"github.com/Azure/azure-container-networking/cni"
@@ -50,6 +51,25 @@ func printVersion() {
5051
}
5152

5253
func rootExecute() error {
54+
// Enrich all CNI loggers with host metadata so ETW events carry VM identity for diagnostics.
55+
metadataFile := filepath.Join(os.TempDir(), "azuremetadata.json")
56+
if metadata, err := common.GetHostMetadata(metadataFile); err == nil {
57+
host, _ := os.Hostname()
58+
zaplog.SetMetadata(
59+
zap.String("hostname", host),
60+
zap.String("version", version),
61+
zap.String("kubernetes_apiserver", os.Getenv("KUBERNETES_SERVICE_HOST")),
62+
zap.String("account", metadata.SubscriptionID),
63+
zap.String("anonymous_user_id", metadata.VMName),
64+
zap.String("location", metadata.Location),
65+
zap.String("resource_group", metadata.ResourceGroupName),
66+
zap.String("vm_size", metadata.VMSize),
67+
zap.String("os_version", metadata.OSVersion),
68+
zap.String("vm_id", metadata.VMID),
69+
zap.String("session_id", metadata.VMID),
70+
)
71+
}
72+
5373
var config common.PluginConfig
5474

5575
config.Version = version

cni/network/stateless/main.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package main
66
import (
77
"fmt"
88
"os"
9+
"path/filepath"
910
"time"
1011

1112
"github.com/Azure/azure-container-networking/cni"
@@ -50,6 +51,25 @@ func printVersion() {
5051
}
5152

5253
func rootExecute() error {
54+
// Enrich all CNI loggers with host metadata so ETW events carry VM identity for diagnostics.
55+
metadataFile := filepath.Join(os.TempDir(), "azuremetadata.json")
56+
if metadata, err := common.GetHostMetadata(metadataFile); err == nil {
57+
host, _ := os.Hostname()
58+
zapLog.SetMetadata(
59+
zap.String("hostname", host),
60+
zap.String("version", version),
61+
zap.String("kubernetes_apiserver", os.Getenv("KUBERNETES_SERVICE_HOST")),
62+
zap.String("account", metadata.SubscriptionID),
63+
zap.String("anonymous_user_id", metadata.VMName),
64+
zap.String("location", metadata.Location),
65+
zap.String("resource_group", metadata.ResourceGroupName),
66+
zap.String("vm_size", metadata.VMSize),
67+
zap.String("os_version", metadata.OSVersion),
68+
zap.String("vm_id", metadata.VMID),
69+
zap.String("session_id", metadata.VMID),
70+
)
71+
}
72+
5373
var config common.PluginConfig
5474

5575
log.SetName(name)

0 commit comments

Comments
 (0)