From 4e43a8eba7aafd3ab15e977fa26c6550efa99765 Mon Sep 17 00:00:00 2001 From: Josh Powers Date: Fri, 14 Oct 2022 14:10:53 -0600 Subject: [PATCH 1/2] fix(serializers.splunkmetric): omit event metric tag with option fixes: #11237 --- config/config.go | 3 +- plugins/serializers/registry.go | 9 ++-- .../serializers/splunkmetric/splunkmetric.go | 14 +++++-- .../splunkmetric/splunkmetric_test.go | 42 ++++++++++++++----- 4 files changed, 49 insertions(+), 19 deletions(-) diff --git a/config/config.go b/config/config.go index 7d865aebf524a..3f6a665356c21 100644 --- a/config/config.go +++ b/config/config.go @@ -1179,6 +1179,7 @@ func (c *Config) buildSerializer(tbl *ast.Table) (serializers.Serializer, error) c.getFieldBool(tbl, "splunkmetric_hec_routing", &sc.HecRouting) c.getFieldBool(tbl, "splunkmetric_multimetric", &sc.SplunkmetricMultiMetric) + c.getFieldBool(tbl, "splunkmetric_omit_event_tag", &sc.SplunkmetricOmitEventTag) c.getFieldStringSlice(tbl, "wavefront_source_override", &sc.WavefrontSourceOverride) c.getFieldBool(tbl, "wavefront_use_strict", &sc.WavefrontUseStrict) @@ -1257,7 +1258,7 @@ func (c *Config) missingTomlField(_ reflect.Type, key string) error { "json_timestamp_format", "json_timestamp_units", "json_transformation", "prometheus_export_timestamp", "prometheus_sort_metrics", "prometheus_string_as_label", "prometheus_compact_encoding", - "splunkmetric_hec_routing", "splunkmetric_multimetric", + "splunkmetric_hec_routing", "splunkmetric_multimetric", "splunkmetric_omit_event_tag", "wavefront_disable_prefix_conversion", "wavefront_source_override", "wavefront_use_strict": default: c.unusedFieldsMutex.Lock() diff --git a/plugins/serializers/registry.go b/plugins/serializers/registry.go index 61d48dabf3958..839b1bdb22596 100644 --- a/plugins/serializers/registry.go +++ b/plugins/serializers/registry.go @@ -110,6 +110,9 @@ type Config struct { // Enable Splunk MultiMetric output (Splunk 8.0+) SplunkmetricMultiMetric bool `toml:"splunkmetric_multi_metric"` + // Omit the Splunk Event "metric" tag + SplunkmetricOmitEventTag bool `toml:"splunkmetric_omit_event_tag"` + // Point tags to use as the source name for Wavefront (if none found, host will be used). WavefrontSourceOverride []string `toml:"wavefront_source_override"` @@ -149,7 +152,7 @@ func NewSerializer(config *Config) (Serializer, error) { case "json": serializer, err = NewJSONSerializer(config.TimestampUnits, config.TimestampFormat, config.Transformation) case "splunkmetric": - serializer, err = NewSplunkmetricSerializer(config.HecRouting, config.SplunkmetricMultiMetric) + serializer, err = NewSplunkmetricSerializer(config.HecRouting, config.SplunkmetricMultiMetric, config.SplunkmetricOmitEventTag) case "nowmetric": serializer, err = NewNowSerializer() case "carbon2": @@ -225,8 +228,8 @@ func NewCarbon2Serializer(carbon2format string, carbon2SanitizeReplaceChar strin return carbon2.NewSerializer(carbon2format, carbon2SanitizeReplaceChar) } -func NewSplunkmetricSerializer(splunkmetricHecRouting bool, splunkmetricMultimetric bool) (Serializer, error) { - return splunkmetric.NewSerializer(splunkmetricHecRouting, splunkmetricMultimetric) +func NewSplunkmetricSerializer(splunkmetricHecRouting bool, splunkmetricMultimetric bool, splunkmetricOmitEventTag bool) (Serializer, error) { + return splunkmetric.NewSerializer(splunkmetricHecRouting, splunkmetricMultimetric, splunkmetricOmitEventTag) } func NewNowSerializer() (Serializer, error) { diff --git a/plugins/serializers/splunkmetric/splunkmetric.go b/plugins/serializers/splunkmetric/splunkmetric.go index c4d2d5ed92a92..cb41f6048d601 100644 --- a/plugins/serializers/splunkmetric/splunkmetric.go +++ b/plugins/serializers/splunkmetric/splunkmetric.go @@ -10,6 +10,7 @@ import ( type serializer struct { HecRouting bool SplunkmetricMultiMetric bool + OmitEventTag bool } type CommonTags struct { @@ -22,7 +23,7 @@ type CommonTags struct { type HECTimeSeries struct { Time float64 `json:"time"` - Event string `json:"event"` + Event string `json:"event,omitempty"` Host string `json:"host,omitempty"` Index string `json:"index,omitempty"` Source string `json:"source,omitempty"` @@ -30,11 +31,12 @@ type HECTimeSeries struct { } // NewSerializer Setup our new serializer -func NewSerializer(splunkmetricHecRouting bool, splunkmetricMultimetric bool) (*serializer, error) { +func NewSerializer(splunkmetricHecRouting bool, splunkmetricMultimetric bool, splunkmetricOmitEventTag bool) (*serializer, error) { /* Define output params */ s := &serializer{ HecRouting: splunkmetricHecRouting, SplunkmetricMultiMetric: splunkmetricMultimetric, + OmitEventTag: splunkmetricOmitEventTag, } return s, nil } @@ -66,7 +68,9 @@ func (s *serializer) createMulti(metric telegraf.Metric, dataGroup HECTimeSeries var metricJSON []byte // Set the event data from the commonTags above. - dataGroup.Event = "metric" + if !s.OmitEventTag { + dataGroup.Event = "metric" + } dataGroup.Time = commonTags.Time dataGroup.Host = commonTags.Host dataGroup.Index = commonTags.Index @@ -123,7 +127,9 @@ func (s *serializer) createSingle(metric telegraf.Metric, dataGroup HECTimeSerie dataGroup.Time = commonTags.Time // Apply the common tags from above to every record. - dataGroup.Event = "metric" + if !s.OmitEventTag { + dataGroup.Event = "metric" + } dataGroup.Host = commonTags.Host dataGroup.Index = commonTags.Index dataGroup.Source = commonTags.Source diff --git a/plugins/serializers/splunkmetric/splunkmetric_test.go b/plugins/serializers/splunkmetric/splunkmetric_test.go index 39e9d996ff250..0035867fe13df 100644 --- a/plugins/serializers/splunkmetric/splunkmetric_test.go +++ b/plugins/serializers/splunkmetric/splunkmetric_test.go @@ -21,7 +21,7 @@ func TestSerializeMetricFloat(t *testing.T) { } m := metric.New("cpu", tags, fields, now) - s, _ := NewSerializer(false, false) + s, _ := NewSerializer(false, false, false) var buf []byte buf, err := s.Serialize(m) require.NoError(t, err) @@ -40,7 +40,7 @@ func TestSerializeMetricFloatHec(t *testing.T) { } m := metric.New("cpu", tags, fields, now) - s, _ := NewSerializer(true, false) + s, _ := NewSerializer(true, false, false) var buf []byte buf, err := s.Serialize(m) require.NoError(t, err) @@ -58,7 +58,7 @@ func TestSerializeMetricInt(t *testing.T) { } m := metric.New("cpu", tags, fields, now) - s, _ := NewSerializer(false, false) + s, _ := NewSerializer(false, false, false) var buf []byte buf, err := s.Serialize(m) require.NoError(t, err) @@ -77,7 +77,7 @@ func TestSerializeMetricIntHec(t *testing.T) { } m := metric.New("cpu", tags, fields, now) - s, _ := NewSerializer(true, false) + s, _ := NewSerializer(true, false, false) var buf []byte buf, err := s.Serialize(m) require.NoError(t, err) @@ -96,7 +96,7 @@ func TestSerializeMetricBool(t *testing.T) { } m := metric.New("docker", tags, fields, now) - s, _ := NewSerializer(false, false) + s, _ := NewSerializer(false, false, false) var buf []byte buf, err := s.Serialize(m) require.NoError(t, err) @@ -115,7 +115,7 @@ func TestSerializeMetricBoolHec(t *testing.T) { } m := metric.New("docker", tags, fields, now) - s, _ := NewSerializer(true, false) + s, _ := NewSerializer(true, false, false) var buf []byte buf, err := s.Serialize(m) require.NoError(t, err) @@ -135,7 +135,7 @@ func TestSerializeMetricString(t *testing.T) { } m := metric.New("cpu", tags, fields, now) - s, _ := NewSerializer(false, false) + s, _ := NewSerializer(false, false, false) var buf []byte buf, err := s.Serialize(m) require.NoError(t, err) @@ -165,7 +165,7 @@ func TestSerializeBatch(t *testing.T) { ) metrics := []telegraf.Metric{m, n} - s, _ := NewSerializer(false, false) + s, _ := NewSerializer(false, false, false) buf, err := s.SerializeBatch(metrics) require.NoError(t, err) @@ -185,7 +185,7 @@ func TestSerializeMulti(t *testing.T) { ) metrics := []telegraf.Metric{m} - s, _ := NewSerializer(false, true) + s, _ := NewSerializer(false, true, false) buf, err := s.SerializeBatch(metrics) require.NoError(t, err) @@ -211,7 +211,7 @@ func TestSerializeBatchHec(t *testing.T) { time.Unix(0, 0), ) metrics := []telegraf.Metric{m, n} - s, _ := NewSerializer(true, false) + s, _ := NewSerializer(true, false, false) buf, err := s.SerializeBatch(metrics) require.NoError(t, err) @@ -231,10 +231,30 @@ func TestSerializeMultiHec(t *testing.T) { ) metrics := []telegraf.Metric{m} - s, _ := NewSerializer(true, true) + s, _ := NewSerializer(true, true, false) buf, err := s.SerializeBatch(metrics) require.NoError(t, err) expS := `{"time":0,"event":"metric","fields":{"metric_name:cpu.system":8,"metric_name:cpu.usage":42}}` require.Equal(t, expS, string(buf)) } + +func TestSerializeOmitEvent(t *testing.T) { + m := metric.New( + "cpu", + map[string]string{}, + map[string]interface{}{ + "usage": 42.0, + "system": 8.0, + }, + time.Unix(0, 0), + ) + + metrics := []telegraf.Metric{m} + s, _ := NewSerializer(true, true, true) + buf, err := s.SerializeBatch(metrics) + require.NoError(t, err) + + expS := `{"time":0,"fields":{"metric_name:cpu.system":8,"metric_name:cpu.usage":42}}` + require.Equal(t, expS, string(buf)) +} From 7bb6561936adb2a2bdfdbed7e6c1ee2a864c4c51 Mon Sep 17 00:00:00 2001 From: Josh Powers Date: Thu, 27 Oct 2022 13:01:53 -0600 Subject: [PATCH 2/2] update readme --- plugins/serializers/splunkmetric/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/serializers/splunkmetric/README.md b/plugins/serializers/splunkmetric/README.md index feeabbacaaf04..27fdee76def0a 100644 --- a/plugins/serializers/splunkmetric/README.md +++ b/plugins/serializers/splunkmetric/README.md @@ -94,6 +94,7 @@ to manage the HEC authorization, here's a sample config for an HTTP output: ## Provides time, index, source overrides for the HEC splunkmetric_hec_routing = true # splunkmetric_multimetric = true + # splunkmetric_omit_event_tag = false ## Additional HTTP headers [outputs.http.headers] @@ -173,6 +174,7 @@ An example configuration of a file based output is: data_format = "splunkmetric" splunkmetric_hec_routing = false splunkmetric_multimetric = true + splunkmetric_omit_event_tag = false ``` ## Non-numeric metric values