Add option to use strict sanitization rules to wavefront output (#5664)
This commit is contained in:
parent
fb01b8ba28
commit
ff81811720
|
@ -32,6 +32,10 @@ This plugin writes to a [Wavefront](https://www.wavefront.com) proxy, in Wavefro
|
||||||
## When true will convert all _ (underscore) characters in final metric name. default is true
|
## When true will convert all _ (underscore) characters in final metric name. default is true
|
||||||
#convert_paths = true
|
#convert_paths = true
|
||||||
|
|
||||||
|
## Use Strict rules to sanitize metric and tag names from invalid characters
|
||||||
|
## When enabled forward slash (/) and comma (,) will be accpeted
|
||||||
|
#use_strict = false
|
||||||
|
|
||||||
## Use Regex to sanitize metric and tag names from invalid characters
|
## Use Regex to sanitize metric and tag names from invalid characters
|
||||||
## Regex is more thorough, but significantly slower. default is false
|
## Regex is more thorough, but significantly slower. default is false
|
||||||
#use_regex = false
|
#use_regex = false
|
||||||
|
|
|
@ -22,6 +22,7 @@ type Wavefront struct {
|
||||||
ConvertPaths bool
|
ConvertPaths bool
|
||||||
ConvertBool bool
|
ConvertBool bool
|
||||||
UseRegex bool
|
UseRegex bool
|
||||||
|
UseStrict bool
|
||||||
SourceOverride []string
|
SourceOverride []string
|
||||||
StringToNumber map[string][]map[string]float64
|
StringToNumber map[string][]map[string]float64
|
||||||
|
|
||||||
|
@ -37,6 +38,14 @@ var sanitizedChars = strings.NewReplacer(
|
||||||
"=", "-",
|
"=", "-",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// catch many of the invalid chars that could appear in a metric or tag name
|
||||||
|
var strictSanitizedChars = strings.NewReplacer(
|
||||||
|
"!", "-", "@", "-", "#", "-", "$", "-", "%", "-", "^", "-", "&", "-",
|
||||||
|
"*", "-", "(", "-", ")", "-", "+", "-", "`", "-", "'", "-", "\"", "-",
|
||||||
|
"[", "-", "]", "-", "{", "-", "}", "-", ":", "-", ";", "-", "<", "-",
|
||||||
|
">", "-", "?", "-", "\\", "-", "|", "-", " ", "-", "=", "-",
|
||||||
|
)
|
||||||
|
|
||||||
// instead of Replacer which may miss some special characters we can use a regex pattern, but this is significantly slower than Replacer
|
// instead of Replacer which may miss some special characters we can use a regex pattern, but this is significantly slower than Replacer
|
||||||
var sanitizedRegex = regexp.MustCompile("[^a-zA-Z\\d_.-]")
|
var sanitizedRegex = regexp.MustCompile("[^a-zA-Z\\d_.-]")
|
||||||
|
|
||||||
|
@ -71,6 +80,10 @@ var sampleConfig = `
|
||||||
## When true will convert all _ (underscore) characters in final metric name. default is true
|
## When true will convert all _ (underscore) characters in final metric name. default is true
|
||||||
#convert_paths = true
|
#convert_paths = true
|
||||||
|
|
||||||
|
## Use Strict rules to sanitize metric and tag names from invalid characters
|
||||||
|
## When enabled forward slash (/) and comma (,) will be accpeted
|
||||||
|
#use_strict = false
|
||||||
|
|
||||||
## Use Regex to sanitize metric and tag names from invalid characters
|
## Use Regex to sanitize metric and tag names from invalid characters
|
||||||
## Regex is more thorough, but significantly slower. default is false
|
## Regex is more thorough, but significantly slower. default is false
|
||||||
#use_regex = false
|
#use_regex = false
|
||||||
|
@ -163,6 +176,8 @@ func buildMetrics(m telegraf.Metric, w *Wavefront) []*MetricPoint {
|
||||||
|
|
||||||
if w.UseRegex {
|
if w.UseRegex {
|
||||||
name = sanitizedRegex.ReplaceAllLiteralString(name, "-")
|
name = sanitizedRegex.ReplaceAllLiteralString(name, "-")
|
||||||
|
} else if w.UseStrict {
|
||||||
|
name = strictSanitizedChars.Replace(name)
|
||||||
} else {
|
} else {
|
||||||
name = sanitizedChars.Replace(name)
|
name = sanitizedChars.Replace(name)
|
||||||
}
|
}
|
||||||
|
@ -238,6 +253,8 @@ func buildTags(mTags map[string]string, w *Wavefront) (string, map[string]string
|
||||||
var key string
|
var key string
|
||||||
if w.UseRegex {
|
if w.UseRegex {
|
||||||
key = sanitizedRegex.ReplaceAllLiteralString(k, "-")
|
key = sanitizedRegex.ReplaceAllLiteralString(k, "-")
|
||||||
|
} else if w.UseStrict {
|
||||||
|
key = strictSanitizedChars.Replace(k)
|
||||||
} else {
|
} else {
|
||||||
key = sanitizedChars.Replace(k)
|
key = sanitizedChars.Replace(k)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,13 @@ func TestBuildMetrics(t *testing.T) {
|
||||||
{Metric: w.Prefix + "testing.metric2", Value: 1, Timestamp: timestamp, Tags: map[string]string{"tag1": "value1"}},
|
{Metric: w.Prefix + "testing.metric2", Value: 1, Timestamp: timestamp, Tags: map[string]string{"tag1": "value1"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
testutil.TestMetric(float64(1), "testing_just/another,metric:float", "metric2"),
|
||||||
|
[]MetricPoint{
|
||||||
|
{Metric: w.Prefix + "testing.just-another-metric-float", Value: 1, Timestamp: timestamp, Tags: map[string]string{"tag1": "value1"}},
|
||||||
|
{Metric: w.Prefix + "testing.metric2", Value: 1, Timestamp: timestamp, Tags: map[string]string{"tag1": "value1"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
testMetric1,
|
testMetric1,
|
||||||
[]MetricPoint{{Metric: w.Prefix + "test.simple.metric", Value: 123, Timestamp: timestamp, Source: "testHost", Tags: map[string]string{"tag1": "value1"}}},
|
[]MetricPoint{{Metric: w.Prefix + "test.simple.metric", Value: 123, Timestamp: timestamp, Source: "testHost", Tags: map[string]string{"tag1": "value1"}}},
|
||||||
|
@ -67,6 +74,46 @@ func TestBuildMetrics(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuildMetricsStrict(t *testing.T) {
|
||||||
|
w := defaultWavefront()
|
||||||
|
w.Prefix = "testthis."
|
||||||
|
w.UseStrict = true
|
||||||
|
|
||||||
|
pathReplacer = strings.NewReplacer("_", w.MetricSeparator)
|
||||||
|
|
||||||
|
var timestamp int64 = 1257894000
|
||||||
|
|
||||||
|
var metricTests = []struct {
|
||||||
|
metric telegraf.Metric
|
||||||
|
metricPoints []MetricPoint
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
testutil.TestMetric(float64(1), "testing_just*a%metric:float", "metric2"),
|
||||||
|
[]MetricPoint{
|
||||||
|
{Metric: w.Prefix + "testing.just-a-metric-float", Value: 1, Timestamp: timestamp, Tags: map[string]string{"tag1": "value1"}},
|
||||||
|
{Metric: w.Prefix + "testing.metric2", Value: 1, Timestamp: timestamp, Tags: map[string]string{"tag1": "value1"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testutil.TestMetric(float64(1), "testing_just/another,metric:float", "metric2"),
|
||||||
|
[]MetricPoint{
|
||||||
|
{Metric: w.Prefix + "testing.just/another,metric-float", Value: 1, Timestamp: timestamp, Tags: map[string]string{"tag/1": "value1", "tag,2": "value2"}},
|
||||||
|
{Metric: w.Prefix + "testing.metric2", Value: 1, Timestamp: timestamp, Tags: map[string]string{"tag/1": "value1", "tag,2": "value2"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, mt := range metricTests {
|
||||||
|
ml := buildMetrics(mt.metric, w)
|
||||||
|
for i, line := range ml {
|
||||||
|
if mt.metricPoints[i].Metric != line.Metric || mt.metricPoints[i].Value != line.Value {
|
||||||
|
t.Errorf("\nexpected\t%+v %+v\nreceived\t%+v %+v\n", mt.metricPoints[i].Metric, mt.metricPoints[i].Value, line.Metric, line.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuildMetricsWithSimpleFields(t *testing.T) {
|
func TestBuildMetricsWithSimpleFields(t *testing.T) {
|
||||||
w := defaultWavefront()
|
w := defaultWavefront()
|
||||||
w.Prefix = "testthis."
|
w.Prefix = "testthis."
|
||||||
|
|
Loading…
Reference in New Issue