Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
1 change: 1 addition & 0 deletions cns/configuration/cns_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"HeartBeatIntervalInMins": 30,
"RefreshIntervalInSecs": 15,
"SnapshotIntervalInMins": 60,
"ConfigSnapshotIntervalInMins": 60,
"TelemetryBatchIntervalInSecs": 15,
"TelemetryBatchSizeBytes": 16384
},
Expand Down
6 changes: 6 additions & 0 deletions cns/configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ type TelemetrySettings struct {
DebugMode bool
// Interval for sending snapshot events.
SnapshotIntervalInMins int
// Interval for sending config snapshot events.
ConfigSnapshotIntervalInMins int
// AppInsightsInstrumentationKey allows the user to override the default appinsights ikey
AppInsightsInstrumentationKey string
}
Expand Down Expand Up @@ -176,6 +178,10 @@ func setTelemetrySettingDefaults(telemetrySettings *TelemetrySettings) {
if telemetrySettings.SnapshotIntervalInMins == 0 {
telemetrySettings.SnapshotIntervalInMins = 60
}

if telemetrySettings.ConfigSnapshotIntervalInMins == 0 {
telemetrySettings.ConfigSnapshotIntervalInMins = 60
}
}

// set managed setting defaults
Expand Down
7 changes: 7 additions & 0 deletions cns/configuration/configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func TestReadConfigFromFile(t *testing.T) {
HeartBeatIntervalInMins: 30,
RefreshIntervalInSecs: 15,
SnapshotIntervalInMins: 60,
ConfigSnapshotIntervalInMins: 60,
TelemetryBatchIntervalInSecs: 15,
TelemetryBatchSizeBytes: 16384,
},
Expand Down Expand Up @@ -122,6 +123,7 @@ func TestSetTelemetrySettingDefaults(t *testing.T) {
TelemetryBatchSizeBytes: 32768,
HeartBeatIntervalInMins: 30,
SnapshotIntervalInMins: 60,
ConfigSnapshotIntervalInMins: 60,
},
},
{
Expand All @@ -132,13 +134,15 @@ func TestSetTelemetrySettingDefaults(t *testing.T) {
TelemetryBatchSizeBytes: 5,
HeartBeatIntervalInMins: 6,
SnapshotIntervalInMins: 7,
ConfigSnapshotIntervalInMins: 8,
},
want: TelemetrySettings{
RefreshIntervalInSecs: 3,
TelemetryBatchIntervalInSecs: 4,
TelemetryBatchSizeBytes: 5,
HeartBeatIntervalInMins: 6,
SnapshotIntervalInMins: 7,
ConfigSnapshotIntervalInMins: 8,
},
},
}
Expand Down Expand Up @@ -206,6 +210,7 @@ func TestSetCNSConfigDefaults(t *testing.T) {
HeartBeatIntervalInMins: 30,
RefreshIntervalInSecs: 15,
SnapshotIntervalInMins: 60,
ConfigSnapshotIntervalInMins: 60,
},
KeyVaultSettings: KeyVaultSettings{
RefreshIntervalInHrs: 12,
Expand Down Expand Up @@ -238,6 +243,7 @@ func TestSetCNSConfigDefaults(t *testing.T) {
HeartBeatIntervalInMins: 3,
RefreshIntervalInSecs: 1,
SnapshotIntervalInMins: 6,
ConfigSnapshotIntervalInMins: 7,
},
KeyVaultSettings: KeyVaultSettings{
RefreshIntervalInHrs: 3,
Expand Down Expand Up @@ -265,6 +271,7 @@ func TestSetCNSConfigDefaults(t *testing.T) {
HeartBeatIntervalInMins: 3,
RefreshIntervalInSecs: 1,
SnapshotIntervalInMins: 6,
ConfigSnapshotIntervalInMins: 7,
},
KeyVaultSettings: KeyVaultSettings{
RefreshIntervalInHrs: 3,
Expand Down
1 change: 1 addition & 0 deletions cns/configuration/testdata/good.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"HeartBeatIntervalInMins": 30,
"RefreshIntervalInSecs": 15,
"SnapshotIntervalInMins": 60,
"ConfigSnapshotIntervalInMins": 60,
"TelemetryBatchIntervalInSecs": 15,
"TelemetryBatchSizeBytes": 16384
},
Expand Down
19 changes: 11 additions & 8 deletions cns/logger/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ package logger

const (
// Metrics
HeartBeatMetricStr = "HeartBeat"
HeartBeatMetricStr = "HeartBeat"
ConfigSnapshotMetricsStr = "ConfigSnapshot"

// Dimensions
OrchestratorTypeStr = "OrchestratorType"
NodeIDStr = "NodeID"
HomeAZStr = "HomeAZ"
IsAZRSupportedStr = "IsAZRSupported"
HomeAZErrorCodeStr = "HomeAZErrorCode"
HomeAZErrorMsgStr = "HomeAZErrorMsg"
OrchestratorTypeStr = "OrchestratorType"
NodeIDStr = "NodeID"
HomeAZStr = "HomeAZ"
IsAZRSupportedStr = "IsAZRSupported"
HomeAZErrorCodeStr = "HomeAZErrorCode"
HomeAZErrorMsgStr = "HomeAZErrorMsg"
CNSConfigPropertyStr = "CNSConfiguration"
CNSConfigMD5CheckSumPropertyStr = "CNSConfigurationMD5Checksum"

// CNS Snspshot properties
// CNS NC Snspshot properties
CnsNCSnapshotEventStr = "CNSNCSnapshot"
IpConfigurationStr = "IPConfiguration"
LocalIPConfigurationStr = "LocalIPConfiguration"
Expand Down
61 changes: 61 additions & 0 deletions cns/metric/configsnapshot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2018 Microsoft. All rights reserved.
// MIT License

package metric

import (
"context"
"crypto/md5" //nolint:gosec // used for checksum
"encoding/json"
"time"

"github.com/Azure/azure-container-networking/aitelemetry"
"github.com/Azure/azure-container-networking/cns/configuration"
"github.com/Azure/azure-container-networking/cns/logger"
"github.com/pkg/errors"
)

// SendCNSConfigSnapshot emits CNS config periodically
func SendCNSConfigSnapshot(ctx context.Context, config *configuration.CNSConfig) {
ticker := time.NewTicker(time.Minute * time.Duration(config.TelemetrySettings.ConfigSnapshotIntervalInMins))
defer ticker.Stop()

event, err := createCNSConfigSnapshotEvent(config)
if err != nil {
logger.Errorf("[Azure CNS] SendCNSConfigSnapshot: %v", err)
return
}

// Log the first event immediately
logger.LogEvent(event)

for {
select {
case <-ctx.Done():
return
case <-ticker.C:
logger.LogEvent(event)
}
}
}

func createCNSConfigSnapshotEvent(config *configuration.CNSConfig) (aitelemetry.Event, error) {
bb, err := json.Marshal(config) //nolint:musttag // no tag needed for config
if err != nil {
return aitelemetry.Event{}, errors.Wrap(err, "failed to marshal config")
}

cs := md5.Sum(bb) //nolint:gosec // used for checksum
csStr := string(cs[:])

event := aitelemetry.Event{
EventName: logger.ConfigSnapshotMetricsStr,
ResourceID: csStr, // not guaranteed unique, instead use VM ID and Subscription to correlate
Properties: map[string]string{
logger.CNSConfigPropertyStr: string(bb),
logger.CNSConfigMD5CheckSumPropertyStr: csStr,
},
}

return event, nil
}
30 changes: 30 additions & 0 deletions cns/metric/configsnapshot_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package metric

import (
"encoding/json"
"testing"

"github.com/Azure/azure-container-networking/cns/configuration"
"github.com/Azure/azure-container-networking/cns/logger"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestCreateCNSConfigSnapshotEvent(t *testing.T) {
logger.InitLogger("testlogs", 0, 0, "./")

config, err := configuration.ReadConfig("../configuration/testdata/good.json")
require.NoError(t, err)

event, err := createCNSConfigSnapshotEvent(config)
require.NoError(t, err)

assert.Equal(t, logger.ConfigSnapshotMetricsStr, event.EventName)
assert.NotEmpty(t, event.ResourceID)
assert.Contains(t, event.Properties[logger.CNSConfigPropertyStr], "\"TLSPort\":\"10091\"")

eventConfig := &configuration.CNSConfig{}
err = json.Unmarshal([]byte(event.Properties[logger.CNSConfigPropertyStr]), eventConfig) //nolint:musttag // no tag needed for config
require.NoError(t, err)
assert.EqualValues(t, config, eventConfig)
}
2 changes: 2 additions & 0 deletions cns/service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,8 @@ func main() {
} else {
logger.InitAI(aiConfig, ts.DisableTrace, ts.DisableMetric, ts.DisableEvent)
}

go metric.SendCNSConfigSnapshot(rootCtx, cnsconfig)
}
logger.Printf("[Azure CNS] Using config: %+v", cnsconfig)

Expand Down
Loading