Skip to content

Commit bf2b3d2

Browse files
authored
[CNS] add config snapshot event metrics at an interval (Azure#3140)
* feat: add and expose new ConfigSnapshotIntervalInMins config * feat: add interval event emitting of CNS config snapshot * lint: address lint errors * chore: send CNS config snapshot immediately * test: refactor test to be less coupled * lint * fix: remove setting default ConfigSnapshotIntervalInMins * chore: remove unnecessary comment
1 parent 5058000 commit bf2b3d2

File tree

8 files changed

+108
-8
lines changed

8 files changed

+108
-8
lines changed

cns/configuration/cns_config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"HeartBeatIntervalInMins": 30,
66
"RefreshIntervalInSecs": 15,
77
"SnapshotIntervalInMins": 60,
8+
"ConfigSnapshotIntervalInMins": 60,
89
"TelemetryBatchIntervalInSecs": 15,
910
"TelemetryBatchSizeBytes": 16384
1011
},

cns/configuration/configuration.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ type TelemetrySettings struct {
8080
DebugMode bool
8181
// Interval for sending snapshot events.
8282
SnapshotIntervalInMins int
83+
// Interval for sending config snapshot events.
84+
ConfigSnapshotIntervalInMins int
8385
// AppInsightsInstrumentationKey allows the user to override the default appinsights ikey
8486
AppInsightsInstrumentationKey string
8587
}

cns/configuration/configuration_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ func TestReadConfigFromFile(t *testing.T) {
8080
HeartBeatIntervalInMins: 30,
8181
RefreshIntervalInSecs: 15,
8282
SnapshotIntervalInMins: 60,
83+
ConfigSnapshotIntervalInMins: 60,
8384
TelemetryBatchIntervalInSecs: 15,
8485
TelemetryBatchSizeBytes: 16384,
8586
},

cns/configuration/testdata/good.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"HeartBeatIntervalInMins": 30,
2727
"RefreshIntervalInSecs": 15,
2828
"SnapshotIntervalInMins": 60,
29+
"ConfigSnapshotIntervalInMins": 60,
2930
"TelemetryBatchIntervalInSecs": 15,
3031
"TelemetryBatchSizeBytes": 16384
3132
},

cns/logger/constants.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,20 @@ package logger
33

44
const (
55
// Metrics
6-
HeartBeatMetricStr = "HeartBeat"
6+
HeartBeatMetricStr = "HeartBeat"
7+
ConfigSnapshotMetricsStr = "ConfigSnapshot"
78

89
// Dimensions
9-
OrchestratorTypeStr = "OrchestratorType"
10-
NodeIDStr = "NodeID"
11-
HomeAZStr = "HomeAZ"
12-
IsAZRSupportedStr = "IsAZRSupported"
13-
HomeAZErrorCodeStr = "HomeAZErrorCode"
14-
HomeAZErrorMsgStr = "HomeAZErrorMsg"
10+
OrchestratorTypeStr = "OrchestratorType"
11+
NodeIDStr = "NodeID"
12+
HomeAZStr = "HomeAZ"
13+
IsAZRSupportedStr = "IsAZRSupported"
14+
HomeAZErrorCodeStr = "HomeAZErrorCode"
15+
HomeAZErrorMsgStr = "HomeAZErrorMsg"
16+
CNSConfigPropertyStr = "CNSConfiguration"
17+
CNSConfigMD5CheckSumPropertyStr = "CNSConfigurationMD5Checksum"
1518

16-
// CNS Snspshot properties
19+
// CNS NC Snspshot properties
1720
CnsNCSnapshotEventStr = "CNSNCSnapshot"
1821
IpConfigurationStr = "IPConfiguration"
1922
LocalIPConfigurationStr = "LocalIPConfiguration"

cns/metric/configsnapshot.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package metric
2+
3+
import (
4+
"context"
5+
"crypto/md5" //nolint:gosec // used for checksum
6+
"encoding/json"
7+
"time"
8+
9+
"github.com/Azure/azure-container-networking/aitelemetry"
10+
"github.com/Azure/azure-container-networking/cns/configuration"
11+
"github.com/Azure/azure-container-networking/cns/logger"
12+
"github.com/pkg/errors"
13+
)
14+
15+
// SendCNSConfigSnapshot emits CNS config periodically
16+
func SendCNSConfigSnapshot(ctx context.Context, config *configuration.CNSConfig) {
17+
ticker := time.NewTicker(time.Minute * time.Duration(config.TelemetrySettings.ConfigSnapshotIntervalInMins))
18+
defer ticker.Stop()
19+
20+
event, err := createCNSConfigSnapshotEvent(config)
21+
if err != nil {
22+
logger.Errorf("[Azure CNS] SendCNSConfigSnapshot: %v", err)
23+
return
24+
}
25+
26+
// Log the first event immediately
27+
logger.LogEvent(event)
28+
29+
for {
30+
select {
31+
case <-ctx.Done():
32+
return
33+
case <-ticker.C:
34+
logger.LogEvent(event)
35+
}
36+
}
37+
}
38+
39+
func createCNSConfigSnapshotEvent(config *configuration.CNSConfig) (aitelemetry.Event, error) {
40+
bb, err := json.Marshal(config) //nolint:musttag // no tag needed for config
41+
if err != nil {
42+
return aitelemetry.Event{}, errors.Wrap(err, "failed to marshal config")
43+
}
44+
45+
cs := md5.Sum(bb) //nolint:gosec // used for checksum
46+
csStr := string(cs[:])
47+
48+
event := aitelemetry.Event{
49+
EventName: logger.ConfigSnapshotMetricsStr,
50+
ResourceID: csStr, // not guaranteed unique, instead use VM ID and Subscription to correlate
51+
Properties: map[string]string{
52+
logger.CNSConfigPropertyStr: string(bb),
53+
logger.CNSConfigMD5CheckSumPropertyStr: csStr,
54+
},
55+
}
56+
57+
return event, nil
58+
}

cns/metric/configsnapshot_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package metric
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
7+
"github.com/Azure/azure-container-networking/cns/configuration"
8+
"github.com/Azure/azure-container-networking/cns/logger"
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestCreateCNSConfigSnapshotEvent(t *testing.T) {
14+
logger.InitLogger("testlogs", 0, 0, "./")
15+
16+
config, err := configuration.ReadConfig("../configuration/testdata/good.json")
17+
require.NoError(t, err)
18+
19+
event, err := createCNSConfigSnapshotEvent(config)
20+
require.NoError(t, err)
21+
22+
assert.Equal(t, logger.ConfigSnapshotMetricsStr, event.EventName)
23+
assert.NotEmpty(t, event.ResourceID)
24+
assert.Contains(t, event.Properties[logger.CNSConfigPropertyStr], "\"TLSPort\":\"10091\"")
25+
26+
eventConfig := &configuration.CNSConfig{}
27+
err = json.Unmarshal([]byte(event.Properties[logger.CNSConfigPropertyStr]), eventConfig) //nolint:musttag // no tag needed for config
28+
require.NoError(t, err)
29+
assert.EqualValues(t, config, eventConfig)
30+
}

cns/service/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,10 @@ func main() {
578578
} else {
579579
logger.InitAI(aiConfig, ts.DisableTrace, ts.DisableMetric, ts.DisableEvent)
580580
}
581+
582+
if cnsconfig.TelemetrySettings.ConfigSnapshotIntervalInMins > 0 {
583+
go metric.SendCNSConfigSnapshot(rootCtx, cnsconfig)
584+
}
581585
}
582586
logger.Printf("[Azure CNS] Using config: %+v", cnsconfig)
583587

0 commit comments

Comments
 (0)