From 6a4b27005a90093b693024e57003a3492614a9b4 Mon Sep 17 00:00:00 2001 From: Akash Suresh Date: Tue, 19 Jan 2021 14:49:26 -0500 Subject: [PATCH 1/2] sfxexporter: Add option to include metrics Add a "include_metrics" option. This option can be used to override metrics that are excluded by default. --- exporter/signalfxexporter/README.md | 14 ++ exporter/signalfxexporter/config.go | 5 + exporter/signalfxexporter/config_test.go | 8 + exporter/signalfxexporter/exporter.go | 2 +- exporter/signalfxexporter/exporter_test.go | 4 +- exporter/signalfxexporter/factory_test.go | 2 +- .../signalfxexporter/testdata/config.yaml | 4 + .../signalfxexporter/translation/converter.go | 8 +- .../translation/converter_test.go | 77 +++++++- .../translation/dpfilters/filterset.go | 41 +++- .../translation/dpfilters/filterset_test.go | 183 ++++++++++-------- .../translation/translator_test.go | 2 +- 12 files changed, 252 insertions(+), 98 deletions(-) diff --git a/exporter/signalfxexporter/README.md b/exporter/signalfxexporter/README.md index 1337a636f09a..97af8c5b488c 100644 --- a/exporter/signalfxexporter/README.md +++ b/exporter/signalfxexporter/README.md @@ -45,6 +45,20 @@ The following configuration options can also be configured: excluded from sending to Signalfx backend. If `send_compatible_metrics` or `translation_rules` options are enabled, the exclusion will be applied on translated metrics. See [here](./testdata/config.yaml) for examples. +- `include_metrics`: List of filters to override exclusion of any metrics. + This option can be used to included metrics that are otherwise dropped by + default. See [here](./translation/default_metrics.go) for a list of metrics + that are dropped by default. For example, the following configuration can be + used to send through some of that are dropped by default. + ```yaml + include_metrics + # When sending in translated metrics. + - metric_names: [cpu.interrupt, cpu.user, cpu.system] + # When sending in metrics in OTel convention. + - metric_name: system.cpu.time + dimensions: + state: [interrupt, user, system] + ``` - `headers` (no default): Headers to pass in the payload. - `log_dimension_updates` (default = `false`): Whether or not to log dimension updates. diff --git a/exporter/signalfxexporter/config.go b/exporter/signalfxexporter/config.go index 5721fde8ce0f..f734396c3094 100644 --- a/exporter/signalfxexporter/config.go +++ b/exporter/signalfxexporter/config.go @@ -92,6 +92,11 @@ type Config struct { // on translated metrics. ExcludeMetrics []dpfilters.MetricFilter `mapstructure:"exclude_metrics"` + // IncludeMetrics defines dpfilter.MetricFilters to override exclusion any of metric. + // This option can be used to included metrics that are otherwise dropped by default. + // See ./translation/default_metrics.go for a list of metrics that are dropped by default. + IncludeMetrics []dpfilters.MetricFilter `mapstructure:"include_metrics"` + // Correlation configuration for syncing traces service and environment to metrics. Correlation *correlation.Config `mapstructure:"correlation"` } diff --git a/exporter/signalfxexporter/config_test.go b/exporter/signalfxexporter/config_test.go index 53d212211fed..550caf84a1e2 100644 --- a/exporter/signalfxexporter/config_test.go +++ b/exporter/signalfxexporter/config_test.go @@ -127,6 +127,14 @@ func TestLoadConfig(t *testing.T) { }, }, }, + IncludeMetrics: []dpfilters.MetricFilter{ + { + MetricName: "metric1", + }, + { + MetricNames: []string{"metric2", "metric3"}, + }, + }, DeltaTranslationTTL: 3600, Correlation: &correlation.Config{ HTTPClientSettings: confighttp.HTTPClientSettings{ diff --git a/exporter/signalfxexporter/exporter.go b/exporter/signalfxexporter/exporter.go index 8ffbc8f2f33b..4b9d7a9e4762 100644 --- a/exporter/signalfxexporter/exporter.go +++ b/exporter/signalfxexporter/exporter.go @@ -90,7 +90,7 @@ func newSignalFxExporter( headers := buildHeaders(config) - converter, err := translation.NewMetricsConverter(logger, options.metricTranslator, config.ExcludeMetrics) + converter, err := translation.NewMetricsConverter(logger, options.metricTranslator, config.ExcludeMetrics, config.IncludeMetrics) if err != nil { return nil, fmt.Errorf("failed to create metric converter: %v", err) } diff --git a/exporter/signalfxexporter/exporter_test.go b/exporter/signalfxexporter/exporter_test.go index 18b6f3acaa4f..595489bed4fa 100644 --- a/exporter/signalfxexporter/exporter_test.go +++ b/exporter/signalfxexporter/exporter_test.go @@ -194,7 +194,7 @@ func TestConsumeMetrics(t *testing.T) { serverURL, err := url.Parse(server.URL) assert.NoError(t, err) - c, err := translation.NewMetricsConverter(zap.NewNop(), nil, nil) + c, err := translation.NewMetricsConverter(zap.NewNop(), nil, nil, nil) require.NoError(t, err) require.NotNil(t, c) dpClient := &sfxDPClient{ @@ -974,7 +974,7 @@ func BenchmarkExporterConsumeData(b *testing.B) { serverURL, err := url.Parse(server.URL) assert.NoError(b, err) - c, err := translation.NewMetricsConverter(zap.NewNop(), nil, nil) + c, err := translation.NewMetricsConverter(zap.NewNop(), nil, nil, nil) require.NoError(b, err) require.NotNil(b, c) dpClient := &sfxDPClient{ diff --git a/exporter/signalfxexporter/factory_test.go b/exporter/signalfxexporter/factory_test.go index de717a401da7..564c7e0b7595 100644 --- a/exporter/signalfxexporter/factory_test.go +++ b/exporter/signalfxexporter/factory_test.go @@ -245,7 +245,7 @@ func TestDefaultTranslationRules(t *testing.T) { require.NoError(t, err) data := testMetricsData() - c, err := translation.NewMetricsConverter(zap.NewNop(), tr, nil) + c, err := translation.NewMetricsConverter(zap.NewNop(), tr, nil, nil) require.NoError(t, err) translated := c.MetricDataToSignalFxV2(data) require.NotNil(t, translated) diff --git a/exporter/signalfxexporter/testdata/config.yaml b/exporter/signalfxexporter/testdata/config.yaml index e9ec79b0fa78..16a63e56a138 100644 --- a/exporter/signalfxexporter/testdata/config.yaml +++ b/exporter/signalfxexporter/testdata/config.yaml @@ -44,6 +44,10 @@ exporters: - metric_name: cpu.utilization dimensions: container_name: /^[A-Z][A-Z]$/ + include_metrics: + - metric_name: metric1 + - metric_names: [metric2, metric3] + diff --git a/exporter/signalfxexporter/translation/converter.go b/exporter/signalfxexporter/translation/converter.go index fdf23da876d6..3e62c414681d 100644 --- a/exporter/signalfxexporter/translation/converter.go +++ b/exporter/signalfxexporter/translation/converter.go @@ -58,8 +58,12 @@ type MetricsConverter struct { // NewMetricsConverter creates a MetricsConverter from the passed in logger and // MetricTranslator. Pass in a nil MetricTranslator to not use translation // rules. -func NewMetricsConverter(logger *zap.Logger, t *MetricTranslator, excludes []dpfilters.MetricFilter) (*MetricsConverter, error) { - fs, err := dpfilters.NewFilterSet(excludes) +func NewMetricsConverter( + logger *zap.Logger, + t *MetricTranslator, + excludes []dpfilters.MetricFilter, + includes []dpfilters.MetricFilter) (*MetricsConverter, error) { + fs, err := dpfilters.NewFilterSet(excludes, includes) if err != nil { return nil, err } diff --git a/exporter/signalfxexporter/translation/converter_test.go b/exporter/signalfxexporter/translation/converter_test.go index 76693bfbfbf4..604340b1770a 100644 --- a/exporter/signalfxexporter/translation/converter_test.go +++ b/exporter/signalfxexporter/translation/converter_test.go @@ -101,6 +101,7 @@ func Test_MetricDataToSignalFxV2(t *testing.T) { name string metricsDataFn func() pdata.ResourceMetrics excludeMetrics []dpfilters.MetricFilter + includeMetrics []dpfilters.MetricFilter wantSfxDataPoints []*sfxpb.DataPoint }{ { @@ -559,10 +560,80 @@ func Test_MetricDataToSignalFxV2(t *testing.T) { doubleSFxDataPoint("cumulative_double_with_dims", tsMSecs, &sfxMetricTypeCumulativeCounter, differentLabelMap, doubleVal), }, }, + { + // To validate that filters in include serves as override to the ones in exclude list. + name: "with_include_and_exclude_metrics_filter", + metricsDataFn: func() pdata.ResourceMetrics { + out := pdata.NewResourceMetrics() + out.InstrumentationLibraryMetrics().Resize(1) + ilm := out.InstrumentationLibraryMetrics().At(0) + ilm.Metrics().Resize(4) + + { + m := ilm.Metrics().At(0) + m.SetName("gauge_double_with_dims") + m.SetDataType(pdata.MetricDataTypeDoubleGauge) + m.DoubleGauge().DataPoints().Append(doublePtWithLabels) + } + { + m := ilm.Metrics().At(1) + m.SetName("gauge_int_with_dims") + m.SetDataType(pdata.MetricDataTypeIntGauge) + m.IntGauge().DataPoints().Append(int64PtWithLabels) + } + { + m := ilm.Metrics().At(2) + m.SetName("cumulative_double_with_dims") + m.SetDataType(pdata.MetricDataTypeDoubleSum) + m.DoubleSum().SetIsMonotonic(true) + m.DoubleSum().DataPoints().Append(doublePtWithLabels) + m.DoubleSum().DataPoints().Append(doublePtWithDifferentLabels) + } + { + m := ilm.Metrics().At(3) + m.SetName("cumulative_int_with_dims") + m.SetDataType(pdata.MetricDataTypeIntSum) + m.IntSum().SetIsMonotonic(true) + m.IntSum().DataPoints().Append(int64PtWithLabels) + } + + return out + }, + excludeMetrics: []dpfilters.MetricFilter{ + { + MetricNames: []string{"gauge_double_with_dims"}, + }, + { + MetricName: "cumulative_int_with_dims", + }, + { + MetricName: "gauge_int_with_dims", + Dimensions: map[string]interface{}{ + "k0": []interface{}{"v1"}, + }, + }, + { + MetricName: "cumulative_double_with_dims", + Dimensions: map[string]interface{}{ + "k0": []interface{}{"v0"}, + }, + }, + }, + includeMetrics: []dpfilters.MetricFilter{ + { + MetricName: "cumulative_int_with_dims", + }, + }, + wantSfxDataPoints: []*sfxpb.DataPoint{ + int64SFxDataPoint("gauge_int_with_dims", tsMSecs, &sfxMetricTypeGauge, labelMap, int64Val), + doubleSFxDataPoint("cumulative_double_with_dims", tsMSecs, &sfxMetricTypeCumulativeCounter, differentLabelMap, doubleVal), + int64SFxDataPoint("cumulative_int_with_dims", tsMSecs, &sfxMetricTypeCumulativeCounter, labelMap, int64Val), + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - c, err := NewMetricsConverter(logger, nil, tt.excludeMetrics) + c, err := NewMetricsConverter(logger, nil, tt.excludeMetrics, tt.includeMetrics) require.NoError(t, err) gotSfxDataPoints := c.MetricDataToSignalFxV2(tt.metricsDataFn()) // Sort SFx dimensions since they are built from maps and the order @@ -611,7 +682,7 @@ func TestMetricDataToSignalFxV2WithTranslation(t *testing.T) { }, }, } - c, err := NewMetricsConverter(zap.NewNop(), translator, nil) + c, err := NewMetricsConverter(zap.NewNop(), translator, nil, nil) require.NoError(t, err) assert.EqualValues(t, expected, c.MetricDataToSignalFxV2(wrapMetric(md))) } @@ -780,7 +851,7 @@ func TestNewMetricsConverter(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NewMetricsConverter(zap.NewNop(), nil, tt.excludes) + got, err := NewMetricsConverter(zap.NewNop(), nil, tt.excludes, nil) if (err != nil) != tt.wantErr { t.Errorf("NewMetricsConverter() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/exporter/signalfxexporter/translation/dpfilters/filterset.go b/exporter/signalfxexporter/translation/dpfilters/filterset.go index dc6099756597..41e8243139c9 100644 --- a/exporter/signalfxexporter/translation/dpfilters/filterset.go +++ b/exporter/signalfxexporter/translation/dpfilters/filterset.go @@ -19,23 +19,48 @@ import sfxpb "github.com/signalfx/com_signalfx_metrics_protobuf/model" // FilterSet is a collection of datapont filters, any one of which must match // for a datapoint to be matched. type FilterSet struct { - ExcludeFilters []*dataPointFilter + excludeFilters []*dataPointFilter + includeFilters []*dataPointFilter } // Matches sends a datapoint through each of the filters in the set and returns // true if at least one of them matches the datapoint. func (fs *FilterSet) Matches(dp *sfxpb.DataPoint) bool { - for _, ex := range fs.ExcludeFilters { + for _, ex := range fs.excludeFilters { if ex.Matches(dp) { + // If we match an exclusionary filter, run through each inclusion + // filter and see if anything includes the metrics. + for _, in := range fs.includeFilters { + if in.Matches(dp) { + return false + } + } return true } } return false } -func NewFilterSet(excludes []MetricFilter) (*FilterSet, error) { - var excludeSet []*dataPointFilter - for _, f := range excludes { +func NewFilterSet(excludes []MetricFilter, includes []MetricFilter) (*FilterSet, error) { + excludeSet, err := getDataPointFilters(excludes) + if err != nil { + return nil, err + } + + includeSet, err := getDataPointFilters(includes) + if err != nil { + return nil, err + } + + return &FilterSet{ + excludeFilters: excludeSet, + includeFilters: includeSet, + }, nil +} + +func getDataPointFilters(metricFilters []MetricFilter) ([]*dataPointFilter, error) { + var out []*dataPointFilter + for _, f := range metricFilters { dimSet, err := f.normalize() if err != nil { return nil, err @@ -46,9 +71,7 @@ func NewFilterSet(excludes []MetricFilter) (*FilterSet, error) { return nil, err } - excludeSet = append(excludeSet, dpf) + out = append(out, dpf) } - return &FilterSet{ - ExcludeFilters: excludeSet, - }, nil + return out, nil } diff --git a/exporter/signalfxexporter/translation/dpfilters/filterset_test.go b/exporter/signalfxexporter/translation/dpfilters/filterset_test.go index 27703273b5da..54e9f7a65b3f 100644 --- a/exporter/signalfxexporter/translation/dpfilters/filterset_test.go +++ b/exporter/signalfxexporter/translation/dpfilters/filterset_test.go @@ -23,18 +23,17 @@ import ( func TestFilterSet(t *testing.T) { tests := []struct { - name string - metricNameInFilter string - metricsNamesInFilter []string - dimensionsInFilter map[string]interface{} - expectedMatches []*sfxpb.DataPoint - expectedNonMatches []*sfxpb.DataPoint - wantErr bool - wantErrMsg string + name string + excludes []MetricFilter + includes []MetricFilter + expectedMatches []*sfxpb.DataPoint + expectedNonMatches []*sfxpb.DataPoint + wantErr bool + wantErrMsg string }{ { - name: "Match based on simple metric name as string", - metricNameInFilter: "cpu.utilization", + name: "Match based on simple metric name as string", + excludes: []MetricFilter{{MetricName: "cpu.utilization"}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -47,8 +46,8 @@ func TestFilterSet(t *testing.T) { }, }, { - name: "Match based on simple metric name", - metricsNamesInFilter: []string{"cpu.utilization"}, + name: "Match based on simple metric name", + excludes: []MetricFilter{{MetricNames: []string{"cpu.utilization"}}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -61,8 +60,8 @@ func TestFilterSet(t *testing.T) { }, }, { - name: "Match based on multiple metric names", - metricsNamesInFilter: []string{"cpu.utilization", "memory.utilization"}, + name: "Match based on multiple metric names", + excludes: []MetricFilter{{MetricNames: []string{"cpu.utilization", "memory.utilization"}}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -78,8 +77,8 @@ func TestFilterSet(t *testing.T) { }, }, { - name: "Match based on regex metric name", - metricsNamesInFilter: []string{`/cpu\..*/`}, + name: "Match based on regex metric name", + excludes: []MetricFilter{{MetricNames: []string{`/cpu\..*/`}}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -92,8 +91,8 @@ func TestFilterSet(t *testing.T) { }, }, { - name: "Match based on glob metric name", - metricsNamesInFilter: []string{`cpu.util*`, "memor*"}, + name: "Match based on glob metric name", + excludes: []MetricFilter{{MetricNames: []string{`cpu.util*`, "memor*"}}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -110,9 +109,10 @@ func TestFilterSet(t *testing.T) { }, { name: "Match based on dimension name as string", - dimensionsInFilter: map[string]interface{}{ - "container_name": "PO", - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "container_name": "PO", + }}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -128,9 +128,10 @@ func TestFilterSet(t *testing.T) { }, { name: "Match based on dimension name", - dimensionsInFilter: map[string]interface{}{ - "container_name": []interface{}{"PO"}, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "container_name": []interface{}{"PO"}, + }}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -146,9 +147,10 @@ func TestFilterSet(t *testing.T) { }, { name: "Match based on dimension name regex", - dimensionsInFilter: map[string]interface{}{ - "container_name": []interface{}{`/^[A-Z][A-Z]$/`}, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "container_name": []interface{}{`/^[A-Z][A-Z]$/`}, + }}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -164,9 +166,10 @@ func TestFilterSet(t *testing.T) { }, { name: "Match based on dimension presence", - dimensionsInFilter: map[string]interface{}{ - "container_name": []interface{}{`/.+/`}, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "container_name": []interface{}{`/.+/`}, + }}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -182,9 +185,10 @@ func TestFilterSet(t *testing.T) { }, { name: "Match based on dimension name glob", - dimensionsInFilter: map[string]interface{}{ - "container_name": []interface{}{`*O*`}, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "container_name": []interface{}{`*O*`}, + }}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -203,11 +207,13 @@ func TestFilterSet(t *testing.T) { }, }, { - name: "Match based on conjunction of both dimensions and metric name", - metricsNamesInFilter: []string{"*.utilization"}, - dimensionsInFilter: map[string]interface{}{ - "container_name": []interface{}{"test"}, - }, + name: "Match based on conjunction of both dimensions and metric name", + excludes: []MetricFilter{{ + MetricNames: []string{"*.utilization"}, + Dimensions: map[string]interface{}{ + "container_name": []interface{}{"test"}, + }, + }}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "disk.utilization", @@ -225,8 +231,8 @@ func TestFilterSet(t *testing.T) { }, }, { - name: "Doesn't match if no dimension filter specified", - metricsNamesInFilter: []string{"cpu.utilization"}, + name: "Doesn't match if no dimension filter specified", + excludes: []MetricFilter{{MetricNames: []string{"cpu.utilization"}}}, expectedNonMatches: []*sfxpb.DataPoint{ { Metric: "disk.utilization", @@ -236,9 +242,10 @@ func TestFilterSet(t *testing.T) { }, { name: "Doesn't match if no metric name filter specified", - dimensionsInFilter: map[string]interface{}{ - "container_name": []interface{}{"mycontainer"}, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "container_name": []interface{}{"mycontainer"}, + }}}, expectedNonMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -247,10 +254,11 @@ func TestFilterSet(t *testing.T) { }, { name: "Doesn't match metric when no (matching) dimensions exist", - dimensionsInFilter: map[string]interface{}{ - "host": []interface{}{"localhost"}, - "system": []interface{}{"r4"}, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "host": []interface{}{"localhost"}, + "system": []interface{}{"r4"}, + }}}, expectedNonMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -265,10 +273,11 @@ func TestFilterSet(t *testing.T) { }, { name: "Matches on at least one dimension", - dimensionsInFilter: map[string]interface{}{ - "host": []interface{}{"localhost"}, - "system": []interface{}{"r4"}, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "host": []interface{}{"localhost"}, + "system": []interface{}{"r4"}, + }}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -280,10 +289,11 @@ func TestFilterSet(t *testing.T) { }, { name: "Matches against all dimension pairs", - dimensionsInFilter: map[string]interface{}{ - "host": []interface{}{"localhost"}, - "system": []interface{}{"r4"}, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "host": []interface{}{"localhost"}, + "system": []interface{}{"r4"}, + }}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -305,9 +315,10 @@ func TestFilterSet(t *testing.T) { }, { name: "Negated dim values take precedent", - dimensionsInFilter: map[string]interface{}{ - "container_name": []interface{}{"*", "!pause", "!/.*idle/"}, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "container_name": []interface{}{"*", "!pause", "!/.*idle/"}, + }}}, expectedMatches: []*sfxpb.DataPoint{ { Metric: "cpu.utilization", @@ -329,51 +340,65 @@ func TestFilterSet(t *testing.T) { }, }, { - name: "Error creating empty filter", + name: "Error creating exclude empty filter", + excludes: []MetricFilter{{}}, + wantErr: true, + wantErrMsg: "metric filter must have at least one metric or dimension defined on it", + }, + { + name: "Error creating include empty filter", + includes: []MetricFilter{{}}, wantErr: true, wantErrMsg: "metric filter must have at least one metric or dimension defined on it", }, { name: "Error creating filter with empty dimension list", - dimensionsInFilter: map[string]interface{}{ - "dim": []interface{}{}, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "dim": []interface{}{}, + }}}, wantErr: true, wantErrMsg: "string map value in filter cannot be empty", }, { - name: "Error creating filter with invalid glob", - metricsNamesInFilter: []string{"cpu.*["}, - wantErr: true, - wantErrMsg: "unexpected end of input", + name: "Error creating filter with invalid glob", + excludes: []MetricFilter{{MetricNames: []string{"cpu.*["}}}, + wantErr: true, + wantErrMsg: "unexpected end of input", }, { name: "Error creating filter with invalid glob in dimensions", - dimensionsInFilter: map[string]interface{}{ - "container_name": []interface{}{"cpu.*["}, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "container_name": []interface{}{"cpu.*["}, + }}}, wantErr: true, wantErrMsg: "unexpected end of input", }, { name: "Error on invalid dimensions input", - dimensionsInFilter: map[string]interface{}{ - "host": 1, - }, + excludes: []MetricFilter{{ + Dimensions: map[string]interface{}{ + "host": 1, + }}}, wantErr: true, wantErrMsg: "1 should be either a string or string list", }, + { + name: "Match in include filters correctly overrides exclude", + excludes: []MetricFilter{{MetricNames: []string{"cpu.utilization"}}}, + includes: []MetricFilter{{MetricNames: []string{"cpu.utilization"}}}, + expectedNonMatches: []*sfxpb.DataPoint{ + { + Metric: "cpu.utilization", + }, + }, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - f, err := NewFilterSet([]MetricFilter{ - { - MetricName: test.metricNameInFilter, - MetricNames: test.metricsNamesInFilter, - Dimensions: test.dimensionsInFilter, - }, - }) + f, err := NewFilterSet(test.excludes, test.includes) if test.wantErr { require.EqualError(t, err, test.wantErrMsg) require.Nil(t, f) diff --git a/exporter/signalfxexporter/translation/translator_test.go b/exporter/signalfxexporter/translation/translator_test.go index 72ac7bcc0957..2c103e609812 100644 --- a/exporter/signalfxexporter/translation/translator_test.go +++ b/exporter/signalfxexporter/translation/translator_test.go @@ -2586,7 +2586,7 @@ func testConverter(t *testing.T, mapping map[string]string) *MetricsConverter { tr, err := NewMetricTranslator(rules, 1) require.NoError(t, err) - c, err := NewMetricsConverter(zap.NewNop(), tr, nil) + c, err := NewMetricsConverter(zap.NewNop(), tr, nil, nil) require.NoError(t, err) return c } From 3313d86f185dda6edb39055aa61dd211476ee884 Mon Sep 17 00:00:00 2001 From: Akash Suresh Date: Wed, 20 Jan 2021 13:02:02 -0500 Subject: [PATCH 2/2] Update exporter/signalfxexporter/README.md Co-authored-by: Jay Camp --- exporter/signalfxexporter/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter/signalfxexporter/README.md b/exporter/signalfxexporter/README.md index 97af8c5b488c..68f6168f0178 100644 --- a/exporter/signalfxexporter/README.md +++ b/exporter/signalfxexporter/README.md @@ -51,7 +51,7 @@ The following configuration options can also be configured: that are dropped by default. For example, the following configuration can be used to send through some of that are dropped by default. ```yaml - include_metrics + include_metrics: # When sending in translated metrics. - metric_names: [cpu.interrupt, cpu.user, cpu.system] # When sending in metrics in OTel convention.