From 66dc5ce940f7c4a88abc1f715935331bceaed82b Mon Sep 17 00:00:00 2001 From: Matt Schmitz Date: Mon, 31 Jul 2023 15:26:22 -0400 Subject: [PATCH] fix(inputs.cisco_telemetry_mdt): Fix MDT source field overwrite (#13693) --- plugins/inputs/cisco_telemetry_mdt/README.md | 7 ++- .../cisco_telemetry_mdt.go | 10 +++- .../cisco_telemetry_mdt_test.go | 49 +++++++++++++++++++ .../inputs/cisco_telemetry_mdt/sample.conf | 7 ++- 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/plugins/inputs/cisco_telemetry_mdt/README.md b/plugins/inputs/cisco_telemetry_mdt/README.md index 3772a84c3..8cc5439ff 100644 --- a/plugins/inputs/cisco_telemetry_mdt/README.md +++ b/plugins/inputs/cisco_telemetry_mdt/README.md @@ -59,8 +59,11 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details. ## Define (for certain nested telemetry measurements with embedded tags) which fields are tags # embedded_tags = ["Cisco-IOS-XR-qos-ma-oper:qos/interface-table/interface/input/service-policy-names/service-policy-instance/statistics/class-stats/class-name"] - ## Include the delete field in every telemetry message. - # include_delete_field = false + ## Include the delete field in every telemetry message. + # include_delete_field = false + + ## Specify custom name for incoming MDT source field. + # source_field_name = "mdt_source" ## Define aliases to map telemetry encoding paths to simple measurement names [inputs.cisco_telemetry_mdt.aliases] diff --git a/plugins/inputs/cisco_telemetry_mdt/cisco_telemetry_mdt.go b/plugins/inputs/cisco_telemetry_mdt/cisco_telemetry_mdt.go index 0fc3d2631..61e9a7fed 100644 --- a/plugins/inputs/cisco_telemetry_mdt/cisco_telemetry_mdt.go +++ b/plugins/inputs/cisco_telemetry_mdt/cisco_telemetry_mdt.go @@ -60,6 +60,7 @@ type CiscoTelemetryMDT struct { EmbeddedTags []string `toml:"embedded_tags"` EnforcementPolicy GRPCEnforcementPolicy `toml:"grpc_enforcement_policy"` IncludeDeleteField bool `toml:"include_delete_field"` + SourceFieldName string `toml:"source_field_name"` Log telegraf.Logger @@ -397,6 +398,10 @@ func (c *CiscoTelemetryMDT) handleTelemetry(data []byte) { for _, subfield := range keys.Fields { c.parseKeyField(tags, subfield, "") } + // If incoming MDT contains source key, copy to mdt_src + if _, ok := tags["source"]; ok { + tags[c.SourceFieldName] = tags["source"] + } } else { tags = make(map[string]string, 3) } @@ -744,8 +749,9 @@ func (c *CiscoTelemetryMDT) Gather(_ telegraf.Accumulator) error { func init() { inputs.Add("cisco_telemetry_mdt", func() telegraf.Input { return &CiscoTelemetryMDT{ - Transport: "grpc", - ServiceAddress: "127.0.0.1:57000", + Transport: "grpc", + ServiceAddress: "127.0.0.1:57000", + SourceFieldName: "mdt_source", } }) } diff --git a/plugins/inputs/cisco_telemetry_mdt/cisco_telemetry_mdt_test.go b/plugins/inputs/cisco_telemetry_mdt/cisco_telemetry_mdt_test.go index bca9731bd..880330ed7 100644 --- a/plugins/inputs/cisco_telemetry_mdt/cisco_telemetry_mdt_test.go +++ b/plugins/inputs/cisco_telemetry_mdt/cisco_telemetry_mdt_test.go @@ -983,3 +983,52 @@ func TestGRPCDialoutKeepalive(t *testing.T) { c.Stop() require.NoError(t, conn.Close()) } + +func TestSourceFieldRewrite(t *testing.T) { + c := &CiscoTelemetryMDT{Log: testutil.Logger{}, Transport: "dummy", Aliases: map[string]string{"alias": "type:model/some/path"}} + c.SourceFieldName = "mdt_source" + acc := &testutil.Accumulator{} + err := c.Start(acc) + // error is expected since we are passing in dummy transport + require.Error(t, err) + + telemetry := &telemetryBis.Telemetry{ + MsgTimestamp: 1543236572000, + EncodingPath: "type:model/some/path", + NodeId: &telemetryBis.Telemetry_NodeIdStr{NodeIdStr: "hostname"}, + Subscription: &telemetryBis.Telemetry_SubscriptionIdStr{SubscriptionIdStr: "subscription"}, + DataGpbkv: []*telemetryBis.TelemetryField{ + { + Fields: []*telemetryBis.TelemetryField{ + { + Name: "keys", + Fields: []*telemetryBis.TelemetryField{ + { + Name: "source", + ValueByType: &telemetryBis.TelemetryField_StringValue{StringValue: "str"}, + }, + }, + }, + { + Name: "content", + Fields: []*telemetryBis.TelemetryField{ + { + Name: "bool", + ValueByType: &telemetryBis.TelemetryField_BoolValue{BoolValue: false}, + }, + }, + }, + }, + }, + }, + } + data, err := proto.Marshal(telemetry) + require.NoError(t, err) + + c.handleTelemetry(data) + require.Empty(t, acc.Errors) + + tags := map[string]string{"path": "type:model/some/path", "mdt_source": "str", "source": "hostname", "subscription": "subscription"} + fields := map[string]interface{}{"bool": false} + acc.AssertContainsTaggedFields(t, "alias", fields, tags) +} diff --git a/plugins/inputs/cisco_telemetry_mdt/sample.conf b/plugins/inputs/cisco_telemetry_mdt/sample.conf index 86be065b6..93c718c57 100644 --- a/plugins/inputs/cisco_telemetry_mdt/sample.conf +++ b/plugins/inputs/cisco_telemetry_mdt/sample.conf @@ -22,8 +22,11 @@ ## Define (for certain nested telemetry measurements with embedded tags) which fields are tags # embedded_tags = ["Cisco-IOS-XR-qos-ma-oper:qos/interface-table/interface/input/service-policy-names/service-policy-instance/statistics/class-stats/class-name"] - ## Include the delete field in every telemetry message. - # include_delete_field = false + ## Include the delete field in every telemetry message. + # include_delete_field = false + + ## Specify custom name for incoming MDT source field. + # source_field_name = "mdt_source" ## Define aliases to map telemetry encoding paths to simple measurement names [inputs.cisco_telemetry_mdt.aliases]