forked from mirrors/statsd_exporter
Merge pull request #315 from glightfoot/signalfx
[268] Support SignalFx Tags
This commit is contained in:
commit
36de8c9e12
4 changed files with 153 additions and 1 deletions
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/go-kit/kit/log"
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
"github.com/prometheus/statsd_exporter/pkg/clock"
|
"github.com/prometheus/statsd_exporter/pkg/clock"
|
||||||
"github.com/prometheus/statsd_exporter/pkg/event"
|
"github.com/prometheus/statsd_exporter/pkg/event"
|
||||||
"github.com/prometheus/statsd_exporter/pkg/exporter"
|
"github.com/prometheus/statsd_exporter/pkg/exporter"
|
||||||
|
@ -169,6 +170,76 @@ func TestHandlePacket(t *testing.T) {
|
||||||
CLabels: map[string]string{"tag1": "bar", "tag2": "baz"},
|
CLabels: map[string]string{"tag1": "bar", "tag2": "baz"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
}, {
|
||||||
|
name: "SignalFx tag extension",
|
||||||
|
in: "foo.[tag1=bar,tag2=baz]test:100|c",
|
||||||
|
out: event.Events{
|
||||||
|
&event.CounterEvent{
|
||||||
|
CMetricName: "foo.test",
|
||||||
|
CValue: 100,
|
||||||
|
CLabels: map[string]string{"tag1": "bar", "tag2": "baz"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "SignalFx tag extension, tags at end of name",
|
||||||
|
in: "foo.test[tag1=bar,tag2=baz]:100|c",
|
||||||
|
out: event.Events{
|
||||||
|
&event.CounterEvent{
|
||||||
|
CMetricName: "foo.test",
|
||||||
|
CValue: 100,
|
||||||
|
CLabels: map[string]string{"tag1": "bar", "tag2": "baz"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "SignalFx tag extension, tags at beginning of name",
|
||||||
|
in: "[tag1=bar,tag2=baz]foo.test:100|c",
|
||||||
|
out: event.Events{
|
||||||
|
&event.CounterEvent{
|
||||||
|
CMetricName: "foo.test",
|
||||||
|
CValue: 100,
|
||||||
|
CLabels: map[string]string{"tag1": "bar", "tag2": "baz"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "SignalFx tag extension, no tags",
|
||||||
|
in: "foo.[]test:100|c",
|
||||||
|
out: event.Events{
|
||||||
|
&event.CounterEvent{
|
||||||
|
CMetricName: "foo.test",
|
||||||
|
CValue: 100,
|
||||||
|
CLabels: map[string]string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "SignalFx tag extension, non-kv tags",
|
||||||
|
in: "foo.[tag1,tag2]test:100|c",
|
||||||
|
out: event.Events{
|
||||||
|
&event.CounterEvent{
|
||||||
|
CMetricName: "foo.test",
|
||||||
|
CValue: 100,
|
||||||
|
CLabels: map[string]string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "SignalFx tag extension, missing closing bracket",
|
||||||
|
in: "[tag1=bar,tag2=bazfoo.test:100|c",
|
||||||
|
out: event.Events{
|
||||||
|
&event.CounterEvent{
|
||||||
|
CMetricName: "[tag1=bar,tag2=bazfoo.test",
|
||||||
|
CValue: 100,
|
||||||
|
CLabels: map[string]string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "SignalFx tag extension, missing opening bracket",
|
||||||
|
in: "tag1=bar,tag2=baz]foo.test:100|c",
|
||||||
|
out: event.Events{
|
||||||
|
&event.CounterEvent{
|
||||||
|
CMetricName: "tag1=bar,tag2=baz]foo.test",
|
||||||
|
CValue: 100,
|
||||||
|
CLabels: map[string]string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "influxdb tag extension with tag keys unsupported by prometheus",
|
name: "influxdb tag extension with tag keys unsupported by prometheus",
|
||||||
in: "foo,09digits=0,tag.with.dots=1:100|c",
|
in: "foo,09digits=0,tag.with.dots=1:100|c",
|
||||||
|
@ -253,6 +324,10 @@ func TestHandlePacket(t *testing.T) {
|
||||||
name: "librato/dogstatsd mixed tag styles without sampling",
|
name: "librato/dogstatsd mixed tag styles without sampling",
|
||||||
in: "foo#tag1=foo,tag3=bing:100|c|#tag1:bar,#tag2:baz",
|
in: "foo#tag1=foo,tag3=bing:100|c|#tag1:bar,#tag2:baz",
|
||||||
out: event.Events{},
|
out: event.Events{},
|
||||||
|
}, {
|
||||||
|
name: "signalfx/dogstatsd mixed tag styles without sampling",
|
||||||
|
in: "foo[tag1=foo,tag3=bing]:100|c|#tag1:bar,#tag2:baz",
|
||||||
|
out: event.Events{},
|
||||||
}, {
|
}, {
|
||||||
name: "influxdb/dogstatsd mixed tag styles without sampling",
|
name: "influxdb/dogstatsd mixed tag styles without sampling",
|
||||||
in: "foo,tag1=foo,tag3=bing:100|c|#tag1:bar,#tag2:baz",
|
in: "foo,tag1=foo,tag3=bing:100|c|#tag1:bar,#tag2:baz",
|
||||||
|
|
|
@ -35,6 +35,7 @@ func benchmarkUDPListener(times int, b *testing.B) {
|
||||||
"foo6:100|c|#09digits:0,tag.with.dots:1",
|
"foo6:100|c|#09digits:0,tag.with.dots:1",
|
||||||
"foo10:100|c|@0.1|#tag1:bar,#tag2:baz",
|
"foo10:100|c|@0.1|#tag1:bar,#tag2:baz",
|
||||||
"foo11:100|c|@0.1|#tag1:foo:bar",
|
"foo11:100|c|@0.1|#tag1:foo:bar",
|
||||||
|
"foo.[foo=bar,dim=val]test:1|g",
|
||||||
"foo15:200|ms:300|ms:5|c|@0.1:6|g\nfoo15a:1|c:5|ms",
|
"foo15:200|ms:300|ms:5|c|@0.1:6|g\nfoo15a:1|c:5|ms",
|
||||||
"some_very_useful_metrics_with_quite_a_log_name:13|c",
|
"some_very_useful_metrics_with_quite_a_log_name:13|c",
|
||||||
}
|
}
|
||||||
|
|
57
line_benchmark_test.go
Normal file
57
line_benchmark_test.go
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright 2020 The Prometheus Authors
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-kit/kit/log"
|
||||||
|
|
||||||
|
"github.com/prometheus/statsd_exporter/pkg/line"
|
||||||
|
)
|
||||||
|
|
||||||
|
func benchmarkLineToEvents(times int, b *testing.B) {
|
||||||
|
input := []string{
|
||||||
|
"foo1:2|c",
|
||||||
|
"foo2:3|g",
|
||||||
|
"foo3:200|ms",
|
||||||
|
"foo4:100|c|#tag1:bar,tag2:baz",
|
||||||
|
"foo5:100|c|#tag1:bar,#tag2:baz",
|
||||||
|
"foo6:100|c|#09digits:0,tag.with.dots:1",
|
||||||
|
"foo10:100|c|@0.1|#tag1:bar,#tag2:baz",
|
||||||
|
"foo11:100|c|@0.1|#tag1:foo:bar",
|
||||||
|
"foo.[foo=bar,dim=val]test:1|g",
|
||||||
|
"foo15:200|ms:300|ms:5|c|@0.1:6|g\nfoo15a:1|c:5|ms",
|
||||||
|
"some_very_useful_metrics_with_quite_a_log_name:13|c",
|
||||||
|
}
|
||||||
|
logger := log.NewNopLogger()
|
||||||
|
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
for i := 0; i < times; i++ {
|
||||||
|
for _, l := range input {
|
||||||
|
line.LineToEvents(l, *sampleErrors, samplesReceived, tagErrors, tagsReceived, logger)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLineToEvents1(b *testing.B) {
|
||||||
|
benchmarkLineToEvents(1, b)
|
||||||
|
}
|
||||||
|
func BenchmarkLineToEvents5(b *testing.B) {
|
||||||
|
benchmarkLineToEvents(5, b)
|
||||||
|
}
|
||||||
|
func BenchmarkLineToEvents50(b *testing.B) {
|
||||||
|
benchmarkLineToEvents(50, b)
|
||||||
|
}
|
|
@ -21,8 +21,8 @@ import (
|
||||||
|
|
||||||
"github.com/go-kit/kit/log"
|
"github.com/go-kit/kit/log"
|
||||||
"github.com/go-kit/kit/log/level"
|
"github.com/go-kit/kit/log/level"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
"github.com/prometheus/statsd_exporter/pkg/event"
|
"github.com/prometheus/statsd_exporter/pkg/event"
|
||||||
"github.com/prometheus/statsd_exporter/pkg/mapper"
|
"github.com/prometheus/statsd_exporter/pkg/mapper"
|
||||||
)
|
)
|
||||||
|
@ -132,6 +132,25 @@ func ParseDogStatsDTags(component string, labels map[string]string, tagErrors pr
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNameAndTags(name string, labels map[string]string, tagErrors prometheus.Counter, logger log.Logger) string {
|
func parseNameAndTags(name string, labels map[string]string, tagErrors prometheus.Counter, logger log.Logger) string {
|
||||||
|
// check for SignalFx tags first
|
||||||
|
// `[` delimits start of tags by SignalFx
|
||||||
|
// `]` delimits end of tags by SignalFx
|
||||||
|
// https://docs.signalfx.com/en/latest/integrations/agent/monitors/collectd-statsd.html
|
||||||
|
startIdx := strings.IndexRune(name, '[')
|
||||||
|
endIdx := strings.IndexRune(name, ']')
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case startIdx != -1 && endIdx != -1:
|
||||||
|
// good signalfx tags
|
||||||
|
parseNameTags(name[startIdx+1:endIdx], labels, tagErrors, logger)
|
||||||
|
return name[:startIdx] + name[endIdx+1:]
|
||||||
|
case (startIdx != -1) != (endIdx != -1):
|
||||||
|
// only one bracket, return unparsed
|
||||||
|
level.Debug(logger).Log("msg", "invalid SignalFx tags, not parsing", "metric", name)
|
||||||
|
tagErrors.Inc()
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
for i, c := range name {
|
for i, c := range name {
|
||||||
// `#` delimits start of tags by Librato
|
// `#` delimits start of tags by Librato
|
||||||
// https://www.librato.com/docs/kb/collect/collection_agents/stastd/#stat-level-tags
|
// https://www.librato.com/docs/kb/collect/collection_agents/stastd/#stat-level-tags
|
||||||
|
|
Loading…
Reference in a new issue