Add string and boolean support to dropwizard; fix escaping of tags/fields (#3664)
This commit is contained in:
parent
26b34ef6ab
commit
72a235d9cf
|
@ -483,7 +483,7 @@ You can also change the path to the typesdb or add additional typesdb using
|
||||||
|
|
||||||
# Dropwizard:
|
# Dropwizard:
|
||||||
|
|
||||||
The dropwizard format can parse the JSON representation of a single dropwizard metric registry. By default, tags are parsed from metric names as if they were actual influxdb line protocol keys (`measurement<,tag_set>`) which can be overriden by defining custom [measurement & tag templates](./DATA_FORMATS_INPUT.md#measurement--tag-templates). All field values are collected as float64 fields.
|
The dropwizard format can parse the JSON representation of a single dropwizard metric registry. By default, tags are parsed from metric names as if they were actual influxdb line protocol keys (`measurement<,tag_set>`) which can be overriden by defining custom [measurement & tag templates](./DATA_FORMATS_INPUT.md#measurement--tag-templates). All field value types are supported, `string`, `number` and `boolean`.
|
||||||
|
|
||||||
A typical JSON of a dropwizard metric registry:
|
A typical JSON of a dropwizard metric registry:
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,9 @@ import (
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var fieldEscaper = strings.NewReplacer("\\", "\\\\", "\"", "\\\"")
|
||||||
|
var keyEscaper = strings.NewReplacer(" ", "\\ ", ",", "\\,", "=", "\\=")
|
||||||
|
|
||||||
// Parser parses json inputs containing dropwizard metrics,
|
// Parser parses json inputs containing dropwizard metrics,
|
||||||
// either top-level or embedded inside a json field.
|
// either top-level or embedded inside a json field.
|
||||||
// This parser is using gjon for retrieving paths within the json file.
|
// This parser is using gjon for retrieving paths within the json file.
|
||||||
|
@ -211,7 +214,7 @@ func (p *Parser) readDWMetrics(metricType string, dwms interface{}, metrics []te
|
||||||
|
|
||||||
measurementWithTags := measurementName
|
measurementWithTags := measurementName
|
||||||
for tagName, tagValue := range tags {
|
for tagName, tagValue := range tags {
|
||||||
tagKeyValue := fmt.Sprintf("%s=%s", tagName, tagValue)
|
tagKeyValue := fmt.Sprintf("%s=%s", keyEscaper.Replace(tagName), keyEscaper.Replace(tagValue))
|
||||||
measurementWithTags = fmt.Sprintf("%s,%s", measurementWithTags, tagKeyValue)
|
measurementWithTags = fmt.Sprintf("%s,%s", measurementWithTags, tagKeyValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,10 +222,14 @@ func (p *Parser) readDWMetrics(metricType string, dwms interface{}, metrics []te
|
||||||
switch t := dwmFields.(type) {
|
switch t := dwmFields.(type) {
|
||||||
case map[string]interface{}: // json object
|
case map[string]interface{}: // json object
|
||||||
for fieldName, fieldValue := range t {
|
for fieldName, fieldValue := range t {
|
||||||
|
key := keyEscaper.Replace(fieldPrefix + fieldName)
|
||||||
switch v := fieldValue.(type) {
|
switch v := fieldValue.(type) {
|
||||||
case float64:
|
case float64:
|
||||||
fields = append(fields, fmt.Sprintf("%s%s=%f", fieldPrefix, fieldName, v))
|
fields = append(fields, fmt.Sprintf("%s=%f", key, v))
|
||||||
|
case string:
|
||||||
|
fields = append(fields, fmt.Sprintf("%s=\"%s\"", key, fieldEscaper.Replace(v)))
|
||||||
|
case bool:
|
||||||
|
fields = append(fields, fmt.Sprintf("%s=%t", key, v))
|
||||||
default: // ignore
|
default: // ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,8 @@ const validEmbeddedCounterJSON = `
|
||||||
"time" : "2017-02-22T14:33:03.662+02:00",
|
"time" : "2017-02-22T14:33:03.662+02:00",
|
||||||
"tags" : {
|
"tags" : {
|
||||||
"tag1" : "green",
|
"tag1" : "green",
|
||||||
"tag2" : "yellow"
|
"tag2" : "yellow",
|
||||||
|
"tag3 space,comma=equals" : "red ,="
|
||||||
},
|
},
|
||||||
"metrics" : {
|
"metrics" : {
|
||||||
"counters" : {
|
"counters" : {
|
||||||
|
@ -99,7 +100,12 @@ func TestParseValidEmbeddedCounterJSON(t *testing.T) {
|
||||||
assert.Equal(t, map[string]interface{}{
|
assert.Equal(t, map[string]interface{}{
|
||||||
"count": float64(1),
|
"count": float64(1),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{"metric_type": "counter", "tag1": "green", "tag2": "yellow"}, metrics[0].Tags())
|
assert.Equal(t, map[string]string{
|
||||||
|
"metric_type": "counter",
|
||||||
|
"tag1": "green",
|
||||||
|
"tag2": "yellow",
|
||||||
|
"tag3 space,comma=equals": "red ,=",
|
||||||
|
}, metrics[0].Tags())
|
||||||
assert.True(t, metricTime.Equal(metrics[0].Time()), fmt.Sprintf("%s should be equal to %s", metrics[0].Time(), metricTime))
|
assert.True(t, metricTime.Equal(metrics[0].Time()), fmt.Sprintf("%s should be equal to %s", metrics[0].Time(), metricTime))
|
||||||
|
|
||||||
// now test json tags through TagPathsMap
|
// now test json tags through TagPathsMap
|
||||||
|
@ -147,6 +153,7 @@ func TestParseValidMeterJSON1(t *testing.T) {
|
||||||
"m1_rate": float64(1),
|
"m1_rate": float64(1),
|
||||||
"m5_rate": float64(1),
|
"m5_rate": float64(1),
|
||||||
"mean_rate": float64(1),
|
"mean_rate": float64(1),
|
||||||
|
"units": "events/second",
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
|
|
||||||
assert.Equal(t, map[string]string{"metric_type": "meter"}, metrics[0].Tags())
|
assert.Equal(t, map[string]string{"metric_type": "meter"}, metrics[0].Tags())
|
||||||
|
@ -186,6 +193,7 @@ func TestParseValidMeterJSON2(t *testing.T) {
|
||||||
"m1_rate": float64(2),
|
"m1_rate": float64(2),
|
||||||
"m5_rate": float64(2),
|
"m5_rate": float64(2),
|
||||||
"mean_rate": float64(2),
|
"mean_rate": float64(2),
|
||||||
|
"units": "events/second",
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{"metric_type": "meter", "key": "value"}, metrics[0].Tags())
|
assert.Equal(t, map[string]string{"metric_type": "meter", "key": "value"}, metrics[0].Tags())
|
||||||
}
|
}
|
||||||
|
@ -198,7 +206,7 @@ const validGaugeJSON = `
|
||||||
"meters" : {},
|
"meters" : {},
|
||||||
"gauges" : {
|
"gauges" : {
|
||||||
"measurement" : {
|
"measurement" : {
|
||||||
"value" : 0
|
"value" : true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"histograms" : {},
|
"histograms" : {},
|
||||||
|
@ -214,7 +222,7 @@ func TestParseValidGaugeJSON(t *testing.T) {
|
||||||
assert.Len(t, metrics, 1)
|
assert.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "measurement", metrics[0].Name())
|
assert.Equal(t, "measurement", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
assert.Equal(t, map[string]interface{}{
|
||||||
"value": float64(0),
|
"value": true,
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{"metric_type": "gauge"}, metrics[0].Tags())
|
assert.Equal(t, map[string]string{"metric_type": "gauge"}, metrics[0].Tags())
|
||||||
}
|
}
|
||||||
|
@ -308,21 +316,23 @@ func TestParseValidTimerJSON(t *testing.T) {
|
||||||
assert.Len(t, metrics, 1)
|
assert.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "measurement", metrics[0].Name())
|
assert.Equal(t, "measurement", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
assert.Equal(t, map[string]interface{}{
|
||||||
"count": float64(1),
|
"count": float64(1),
|
||||||
"max": float64(2),
|
"max": float64(2),
|
||||||
"mean": float64(3),
|
"mean": float64(3),
|
||||||
"min": float64(4),
|
"min": float64(4),
|
||||||
"p50": float64(5),
|
"p50": float64(5),
|
||||||
"p75": float64(6),
|
"p75": float64(6),
|
||||||
"p95": float64(7),
|
"p95": float64(7),
|
||||||
"p98": float64(8),
|
"p98": float64(8),
|
||||||
"p99": float64(9),
|
"p99": float64(9),
|
||||||
"p999": float64(10),
|
"p999": float64(10),
|
||||||
"stddev": float64(11),
|
"stddev": float64(11),
|
||||||
"m15_rate": float64(12),
|
"m15_rate": float64(12),
|
||||||
"m1_rate": float64(13),
|
"m1_rate": float64(13),
|
||||||
"m5_rate": float64(14),
|
"m5_rate": float64(14),
|
||||||
"mean_rate": float64(15),
|
"mean_rate": float64(15),
|
||||||
|
"duration_units": "seconds",
|
||||||
|
"rate_units": "calls/second",
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{"metric_type": "timer"}, metrics[0].Tags())
|
assert.Equal(t, map[string]string{"metric_type": "timer"}, metrics[0].Tags())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue