Add name, time, path and string field options to JSON parser (#4351)
This commit is contained in:
parent
d6d6539e26
commit
2729378b7f
|
@ -107,9 +107,31 @@ but can be overridden using the `name_override` config option.
|
||||||
|
|
||||||
#### JSON Configuration:
|
#### JSON Configuration:
|
||||||
|
|
||||||
The JSON data format supports specifying "tag keys". If specified, keys
|
The JSON data format supports specifying "tag_keys", "string_keys", and "json_query".
|
||||||
will be searched for in the root-level of the JSON blob. If the key(s) exist,
|
If specified, keys in "tag_keys" and "string_keys" will be searched for in the root-level
|
||||||
they will be applied as tags to the Telegraf metrics.
|
and any nested lists of the JSON blob. All int and float values are added to fields by default.
|
||||||
|
If the key(s) exist, they will be applied as tags or fields to the Telegraf metrics.
|
||||||
|
If "string_keys" is specified, the string will be added as a field.
|
||||||
|
|
||||||
|
The "json_query" configuration is a gjson path to an JSON object or
|
||||||
|
list of JSON objects. If this path leads to an array of values or
|
||||||
|
single data point an error will be thrown. If this configuration
|
||||||
|
is specified, only the result of the query will be parsed and returned as metrics.
|
||||||
|
|
||||||
|
The "json_name_key" configuration specifies the key of the field whos value will be
|
||||||
|
added as the metric name.
|
||||||
|
|
||||||
|
Object paths are specified using gjson path format, which is denoted by object keys
|
||||||
|
concatenated with "." to go deeper in nested JSON objects.
|
||||||
|
Additional information on gjson paths can be found here: https://github.com/tidwall/gjson#path-syntax
|
||||||
|
|
||||||
|
The JSON data format also supports extracting time values through the
|
||||||
|
config "json_time_key" and "json_time_format". If "json_time_key" is set,
|
||||||
|
"json_time_format" must be specified. The "json_time_key" describes the
|
||||||
|
name of the field containing time information. The "json_time_format"
|
||||||
|
must be a recognized Go time format.
|
||||||
|
If there is no year provided, the metrics will have the current year.
|
||||||
|
More info on time formats can be found here: https://golang.org/pkg/time/#Parse
|
||||||
|
|
||||||
For example, if you had this configuration:
|
For example, if you had this configuration:
|
||||||
|
|
||||||
|
@ -127,11 +149,28 @@ For example, if you had this configuration:
|
||||||
## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
|
## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
|
||||||
data_format = "json"
|
data_format = "json"
|
||||||
|
|
||||||
## List of tag names to extract from top-level of JSON server response
|
## List of tag names to extract from JSON server response
|
||||||
tag_keys = [
|
tag_keys = [
|
||||||
"my_tag_1",
|
"my_tag_1",
|
||||||
"my_tag_2"
|
"my_tag_2"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
## The json path specifying where to extract the metric name from
|
||||||
|
# json_name_key = ""
|
||||||
|
|
||||||
|
## List of field names to extract from JSON and add as string fields
|
||||||
|
# json_string_fields = []
|
||||||
|
|
||||||
|
## gjson query path to specify a specific chunk of JSON to be parsed with
|
||||||
|
## the above configuration. If not specified, the whole file will be parsed.
|
||||||
|
## gjson query paths are described here: https://github.com/tidwall/gjson#path-syntax
|
||||||
|
# json_query = ""
|
||||||
|
|
||||||
|
## holds the name of the tag of timestamp
|
||||||
|
# json_time_key = ""
|
||||||
|
|
||||||
|
## holds the format of timestamp to be parsed
|
||||||
|
# json_time_format = ""
|
||||||
```
|
```
|
||||||
|
|
||||||
with this JSON output from a command:
|
with this JSON output from a command:
|
||||||
|
@ -152,8 +191,9 @@ Your Telegraf metrics would get tagged with "my_tag_1"
|
||||||
exec_mycollector,my_tag_1=foo a=5,b_c=6
|
exec_mycollector,my_tag_1=foo a=5,b_c=6
|
||||||
```
|
```
|
||||||
|
|
||||||
If the JSON data is an array, then each element of the array is parsed with the configured settings.
|
If the JSON data is an array, then each element of the array is
|
||||||
Each resulting metric will be output with the same timestamp.
|
parsed with the configured settings. Each resulting metric will
|
||||||
|
be output with the same timestamp.
|
||||||
|
|
||||||
For example, if the following configuration:
|
For example, if the following configuration:
|
||||||
|
|
||||||
|
@ -176,6 +216,19 @@ For example, if the following configuration:
|
||||||
"my_tag_1",
|
"my_tag_1",
|
||||||
"my_tag_2"
|
"my_tag_2"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
## List of field names to extract from JSON and add as string fields
|
||||||
|
# string_fields = []
|
||||||
|
|
||||||
|
## gjson query path to specify a specific chunk of JSON to be parsed with
|
||||||
|
## the above configuration. If not specified, the whole file will be parsed
|
||||||
|
# json_query = ""
|
||||||
|
|
||||||
|
## holds the name of the tag of timestamp
|
||||||
|
json_time_key = "b_time"
|
||||||
|
|
||||||
|
## holds the format of timestamp to be parsed
|
||||||
|
json_time_format = "02 Jan 06 15:04 MST"
|
||||||
```
|
```
|
||||||
|
|
||||||
with this JSON output from a command:
|
with this JSON output from a command:
|
||||||
|
@ -185,7 +238,8 @@ with this JSON output from a command:
|
||||||
{
|
{
|
||||||
"a": 5,
|
"a": 5,
|
||||||
"b": {
|
"b": {
|
||||||
"c": 6
|
"c": 6,
|
||||||
|
"time":"04 Jan 06 15:04 MST"
|
||||||
},
|
},
|
||||||
"my_tag_1": "foo",
|
"my_tag_1": "foo",
|
||||||
"my_tag_2": "baz"
|
"my_tag_2": "baz"
|
||||||
|
@ -193,7 +247,8 @@ with this JSON output from a command:
|
||||||
{
|
{
|
||||||
"a": 7,
|
"a": 7,
|
||||||
"b": {
|
"b": {
|
||||||
"c": 8
|
"c": 8,
|
||||||
|
"time":"11 Jan 07 15:04 MST"
|
||||||
},
|
},
|
||||||
"my_tag_1": "bar",
|
"my_tag_1": "bar",
|
||||||
"my_tag_2": "baz"
|
"my_tag_2": "baz"
|
||||||
|
@ -201,11 +256,71 @@ with this JSON output from a command:
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Your Telegraf metrics would get tagged with "my_tag_1" and "my_tag_2"
|
Your Telegraf metrics would get tagged with "my_tag_1" and "my_tag_2" and fielded with "b_c"
|
||||||
|
The metric's time will be a time.Time object, as specified by "b_time"
|
||||||
|
|
||||||
```
|
```
|
||||||
exec_mycollector,my_tag_1=foo,my_tag_2=baz a=5,b_c=6
|
exec_mycollector,my_tag_1=foo,my_tag_2=baz b_c=6 1136387040000000000
|
||||||
exec_mycollector,my_tag_1=bar,my_tag_2=baz a=7,b_c=8
|
exec_mycollector,my_tag_1=bar,my_tag_2=baz b_c=8 1168527840000000000
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to only use a specific portion of your JSON, use the "json_query"
|
||||||
|
configuration to specify a path to a JSON object.
|
||||||
|
|
||||||
|
For example, with the following config:
|
||||||
|
```toml
|
||||||
|
[[inputs.exec]]
|
||||||
|
## Commands array
|
||||||
|
commands = ["/usr/bin/mycollector --foo=bar"]
|
||||||
|
|
||||||
|
## measurement name suffix (for separating different commands)
|
||||||
|
name_suffix = "_mycollector"
|
||||||
|
|
||||||
|
## Data format to consume.
|
||||||
|
## Each data format has its own unique set of configuration options, read
|
||||||
|
## more about them here:
|
||||||
|
## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
|
||||||
|
data_format = "json"
|
||||||
|
|
||||||
|
## List of tag names to extract from top-level of JSON server response
|
||||||
|
tag_keys = ["first"]
|
||||||
|
|
||||||
|
## List of field names to extract from JSON and add as string fields
|
||||||
|
string_fields = ["last"]
|
||||||
|
|
||||||
|
## gjson query path to specify a specific chunk of JSON to be parsed with
|
||||||
|
## the above configuration. If not specified, the whole file will be parsed
|
||||||
|
json_query = "obj.friends"
|
||||||
|
|
||||||
|
## holds the name of the tag of timestamp
|
||||||
|
# json_time_key = ""
|
||||||
|
|
||||||
|
## holds the format of timestamp to be parsed
|
||||||
|
# json_time_format = ""
|
||||||
|
```
|
||||||
|
|
||||||
|
with this JSON as input:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"obj": {
|
||||||
|
"name": {"first": "Tom", "last": "Anderson"},
|
||||||
|
"age":37,
|
||||||
|
"children": ["Sara","Alex","Jack"],
|
||||||
|
"fav.movie": "Deer Hunter",
|
||||||
|
"friends": [
|
||||||
|
{"first": "Dale", "last": "Murphy", "age": 44},
|
||||||
|
{"first": "Roger", "last": "Craig", "age": 68},
|
||||||
|
{"first": "Jane", "last": "Murphy", "age": 47}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
You would recieve 3 metrics tagged with "first", and fielded with "last" and "age"
|
||||||
|
|
||||||
|
```
|
||||||
|
exec_mycollector, "first":"Dale" "last":"Murphy","age":44
|
||||||
|
exec_mycollector, "first":"Roger" "last":"Craig","age":68
|
||||||
|
exec_mycollector, "first":"Jane" "last":"Murphy","age":47
|
||||||
```
|
```
|
||||||
|
|
||||||
# Value:
|
# Value:
|
||||||
|
|
|
@ -1261,6 +1261,50 @@ func buildParser(name string, tbl *ast.Table) (parsers.Parser, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if node, ok := tbl.Fields["json_string_fields"]; ok {
|
||||||
|
if kv, ok := node.(*ast.KeyValue); ok {
|
||||||
|
if ary, ok := kv.Value.(*ast.Array); ok {
|
||||||
|
for _, elem := range ary.Value {
|
||||||
|
if str, ok := elem.(*ast.String); ok {
|
||||||
|
c.JSONStringFields = append(c.JSONStringFields, str.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node, ok := tbl.Fields["json_name_key"]; ok {
|
||||||
|
if kv, ok := node.(*ast.KeyValue); ok {
|
||||||
|
if str, ok := kv.Value.(*ast.String); ok {
|
||||||
|
c.JSONNameKey = str.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node, ok := tbl.Fields["json_query"]; ok {
|
||||||
|
if kv, ok := node.(*ast.KeyValue); ok {
|
||||||
|
if str, ok := kv.Value.(*ast.String); ok {
|
||||||
|
c.JSONQuery = str.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node, ok := tbl.Fields["json_time_key"]; ok {
|
||||||
|
if kv, ok := node.(*ast.KeyValue); ok {
|
||||||
|
if str, ok := kv.Value.(*ast.String); ok {
|
||||||
|
c.JSONTimeKey = str.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node, ok := tbl.Fields["json_time_format"]; ok {
|
||||||
|
if kv, ok := node.(*ast.KeyValue); ok {
|
||||||
|
if str, ok := kv.Value.(*ast.String); ok {
|
||||||
|
c.JSONTimeFormat = str.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if node, ok := tbl.Fields["data_type"]; ok {
|
if node, ok := tbl.Fields["data_type"]; ok {
|
||||||
if kv, ok := node.(*ast.KeyValue); ok {
|
if kv, ok := node.(*ast.KeyValue); ok {
|
||||||
if str, ok := kv.Value.(*ast.String); ok {
|
if str, ok := kv.Value.(*ast.String); ok {
|
||||||
|
@ -1405,6 +1449,11 @@ func buildParser(name string, tbl *ast.Table) (parsers.Parser, error) {
|
||||||
delete(tbl.Fields, "separator")
|
delete(tbl.Fields, "separator")
|
||||||
delete(tbl.Fields, "templates")
|
delete(tbl.Fields, "templates")
|
||||||
delete(tbl.Fields, "tag_keys")
|
delete(tbl.Fields, "tag_keys")
|
||||||
|
delete(tbl.Fields, "string_fields")
|
||||||
|
delete(tbl.Fields, "json_query")
|
||||||
|
delete(tbl.Fields, "json_name_key")
|
||||||
|
delete(tbl.Fields, "json_time_key")
|
||||||
|
delete(tbl.Fields, "json_time_format")
|
||||||
delete(tbl.Fields, "data_type")
|
delete(tbl.Fields, "data_type")
|
||||||
delete(tbl.Fields, "collectd_auth_file")
|
delete(tbl.Fields, "collectd_auth_file")
|
||||||
delete(tbl.Fields, "collectd_security_level")
|
delete(tbl.Fields, "collectd_security_level")
|
||||||
|
|
|
@ -143,7 +143,10 @@ func TestConfig_LoadDirectory(t *testing.T) {
|
||||||
"Testdata did not produce correct memcached metadata.")
|
"Testdata did not produce correct memcached metadata.")
|
||||||
|
|
||||||
ex := inputs.Inputs["exec"]().(*exec.Exec)
|
ex := inputs.Inputs["exec"]().(*exec.Exec)
|
||||||
p, err := parsers.NewJSONParser("exec", nil, nil)
|
p, err := parsers.NewParser(&parsers.Config{
|
||||||
|
MetricName: "exec",
|
||||||
|
DataFormat: "json",
|
||||||
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
ex.SetParser(p)
|
ex.SetParser(p)
|
||||||
ex.Command = "/usr/bin/myothercollector --foo=bar"
|
ex.Command = "/usr/bin/myothercollector --foo=bar"
|
||||||
|
|
|
@ -93,7 +93,10 @@ func (r runnerMock) Run(e *Exec, command string, acc telegraf.Accumulator) ([]by
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExec(t *testing.T) {
|
func TestExec(t *testing.T) {
|
||||||
parser, _ := parsers.NewJSONParser("exec", []string{}, nil)
|
parser, _ := parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: "exec",
|
||||||
|
})
|
||||||
e := &Exec{
|
e := &Exec{
|
||||||
runner: newRunnerMock([]byte(validJson), nil),
|
runner: newRunnerMock([]byte(validJson), nil),
|
||||||
Commands: []string{"testcommand arg1"},
|
Commands: []string{"testcommand arg1"},
|
||||||
|
@ -119,7 +122,10 @@ func TestExec(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExecMalformed(t *testing.T) {
|
func TestExecMalformed(t *testing.T) {
|
||||||
parser, _ := parsers.NewJSONParser("exec", []string{}, nil)
|
parser, _ := parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: "exec",
|
||||||
|
})
|
||||||
e := &Exec{
|
e := &Exec{
|
||||||
runner: newRunnerMock([]byte(malformedJson), nil),
|
runner: newRunnerMock([]byte(malformedJson), nil),
|
||||||
Commands: []string{"badcommand arg1"},
|
Commands: []string{"badcommand arg1"},
|
||||||
|
@ -132,7 +138,10 @@ func TestExecMalformed(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCommandError(t *testing.T) {
|
func TestCommandError(t *testing.T) {
|
||||||
parser, _ := parsers.NewJSONParser("exec", []string{}, nil)
|
parser, _ := parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: "exec",
|
||||||
|
})
|
||||||
e := &Exec{
|
e := &Exec{
|
||||||
runner: newRunnerMock(nil, fmt.Errorf("exit status code 1")),
|
runner: newRunnerMock(nil, fmt.Errorf("exit status code 1")),
|
||||||
Commands: []string{"badcommand"},
|
Commands: []string{"badcommand"},
|
||||||
|
|
|
@ -26,7 +26,11 @@ func TestHTTPwithJSONFormat(t *testing.T) {
|
||||||
URLs: []string{url},
|
URLs: []string{url},
|
||||||
}
|
}
|
||||||
metricName := "metricName"
|
metricName := "metricName"
|
||||||
p, _ := parsers.NewJSONParser(metricName, nil, nil)
|
|
||||||
|
p, _ := parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: "metricName",
|
||||||
|
})
|
||||||
plugin.SetParser(p)
|
plugin.SetParser(p)
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
|
@ -63,8 +67,11 @@ func TestHTTPHeaders(t *testing.T) {
|
||||||
URLs: []string{url},
|
URLs: []string{url},
|
||||||
Headers: map[string]string{header: headerValue},
|
Headers: map[string]string{header: headerValue},
|
||||||
}
|
}
|
||||||
metricName := "metricName"
|
|
||||||
p, _ := parsers.NewJSONParser(metricName, nil, nil)
|
p, _ := parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: "metricName",
|
||||||
|
})
|
||||||
plugin.SetParser(p)
|
plugin.SetParser(p)
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
|
@ -83,7 +90,10 @@ func TestInvalidStatusCode(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
metricName := "metricName"
|
metricName := "metricName"
|
||||||
p, _ := parsers.NewJSONParser(metricName, nil, nil)
|
p, _ := parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: metricName,
|
||||||
|
})
|
||||||
plugin.SetParser(p)
|
plugin.SetParser(p)
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
|
@ -105,8 +115,10 @@ func TestMethod(t *testing.T) {
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
}
|
}
|
||||||
|
|
||||||
metricName := "metricName"
|
p, _ := parsers.NewParser(&parsers.Config{
|
||||||
p, _ := parsers.NewJSONParser(metricName, nil, nil)
|
DataFormat: "json",
|
||||||
|
MetricName: "metricName",
|
||||||
|
})
|
||||||
plugin.SetParser(p)
|
plugin.SetParser(p)
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
|
|
|
@ -181,7 +181,12 @@ func (h *HttpJson) gatherServer(
|
||||||
"server": serverURL,
|
"server": serverURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
parser, err := parsers.NewJSONParser(msrmnt_name, h.TagKeys, tags)
|
parser, err := parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: msrmnt_name,
|
||||||
|
TagKeys: h.TagKeys,
|
||||||
|
DefaultTags: tags,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,10 @@ func TestRunParserAndGatherJSON(t *testing.T) {
|
||||||
k.acc = &acc
|
k.acc = &acc
|
||||||
defer close(k.done)
|
defer close(k.done)
|
||||||
|
|
||||||
k.parser, _ = parsers.NewJSONParser("kafka_json_test", []string{}, nil)
|
k.parser, _ = parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: "kafka_json_test",
|
||||||
|
})
|
||||||
go k.receiver()
|
go k.receiver()
|
||||||
in <- saramaMsg(testMsgJSON)
|
in <- saramaMsg(testMsgJSON)
|
||||||
acc.Wait(1)
|
acc.Wait(1)
|
||||||
|
|
|
@ -125,7 +125,10 @@ func TestRunParserAndGatherJSON(t *testing.T) {
|
||||||
k.acc = &acc
|
k.acc = &acc
|
||||||
defer close(k.done)
|
defer close(k.done)
|
||||||
|
|
||||||
k.parser, _ = parsers.NewJSONParser("kafka_json_test", []string{}, nil)
|
k.parser, _ = parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: "kafka_json_test",
|
||||||
|
})
|
||||||
go k.receiver()
|
go k.receiver()
|
||||||
in <- saramaMsg(testMsgJSON)
|
in <- saramaMsg(testMsgJSON)
|
||||||
acc.Wait(1)
|
acc.Wait(1)
|
||||||
|
|
|
@ -172,7 +172,10 @@ func TestRunParserAndGatherJSON(t *testing.T) {
|
||||||
n.acc = &acc
|
n.acc = &acc
|
||||||
defer close(n.done)
|
defer close(n.done)
|
||||||
|
|
||||||
n.parser, _ = parsers.NewJSONParser("nats_json_test", []string{}, nil)
|
n.parser, _ = parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: "nats_json_test",
|
||||||
|
})
|
||||||
go n.receiver()
|
go n.receiver()
|
||||||
in <- mqttMsg(testMsgJSON)
|
in <- mqttMsg(testMsgJSON)
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,10 @@ func TestRunParserAndGatherJSON(t *testing.T) {
|
||||||
n.acc = &acc
|
n.acc = &acc
|
||||||
defer close(n.done)
|
defer close(n.done)
|
||||||
|
|
||||||
n.parser, _ = parsers.NewJSONParser("nats_json_test", []string{}, nil)
|
n.parser, _ = parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: "nats_json_test",
|
||||||
|
})
|
||||||
n.wg.Add(1)
|
n.wg.Add(1)
|
||||||
go n.receiver()
|
go n.receiver()
|
||||||
in <- natsMsg(testMsgJSON)
|
in <- natsMsg(testMsgJSON)
|
||||||
|
|
|
@ -300,7 +300,10 @@ func TestRunParserJSONMsg(t *testing.T) {
|
||||||
listener.acc = &acc
|
listener.acc = &acc
|
||||||
defer close(listener.done)
|
defer close(listener.done)
|
||||||
|
|
||||||
listener.parser, _ = parsers.NewJSONParser("udp_json_test", []string{}, nil)
|
listener.parser, _ = parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: "udp_json_test",
|
||||||
|
})
|
||||||
listener.wg.Add(1)
|
listener.wg.Add(1)
|
||||||
go listener.tcpParser()
|
go listener.tcpParser()
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,10 @@ func TestRunParserJSONMsg(t *testing.T) {
|
||||||
listener.acc = &acc
|
listener.acc = &acc
|
||||||
defer close(listener.done)
|
defer close(listener.done)
|
||||||
|
|
||||||
listener.parser, _ = parsers.NewJSONParser("udp_json_test", []string{}, nil)
|
listener.parser, _ = parsers.NewParser(&parsers.Config{
|
||||||
|
DataFormat: "json",
|
||||||
|
MetricName: "udp_json_test",
|
||||||
|
})
|
||||||
listener.wg.Add(1)
|
listener.wg.Add(1)
|
||||||
go listener.udpParser()
|
go listener.udpParser()
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
"github.com/influxdata/telegraf/metric"
|
"github.com/influxdata/telegraf/metric"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -18,9 +19,14 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type JSONParser struct {
|
type JSONParser struct {
|
||||||
MetricName string
|
MetricName string
|
||||||
TagKeys []string
|
TagKeys []string
|
||||||
DefaultTags map[string]string
|
StringFields []string
|
||||||
|
JSONNameKey string
|
||||||
|
JSONQuery string
|
||||||
|
JSONTimeKey string
|
||||||
|
JSONTimeFormat string
|
||||||
|
DefaultTags map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *JSONParser) parseArray(buf []byte) ([]telegraf.Metric, error) {
|
func (p *JSONParser) parseArray(buf []byte) ([]telegraf.Metric, error) {
|
||||||
|
@ -34,6 +40,9 @@ func (p *JSONParser) parseArray(buf []byte) ([]telegraf.Metric, error) {
|
||||||
}
|
}
|
||||||
for _, item := range jsonOut {
|
for _, item := range jsonOut {
|
||||||
metrics, err = p.parseObject(metrics, item)
|
metrics, err = p.parseObject(metrics, item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return metrics, nil
|
return metrics, nil
|
||||||
}
|
}
|
||||||
|
@ -51,10 +60,42 @@ func (p *JSONParser) parseObject(metrics []telegraf.Metric, jsonOut map[string]i
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//checks if json_name_key is set
|
||||||
|
if p.JSONNameKey != "" {
|
||||||
|
p.MetricName = f.Fields[p.JSONNameKey].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
//if time key is specified, set it to nTime
|
||||||
|
nTime := time.Now().UTC()
|
||||||
|
if p.JSONTimeKey != "" {
|
||||||
|
if p.JSONTimeFormat == "" {
|
||||||
|
err := fmt.Errorf("use of 'json_time_key' requires 'json_time_format'")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Fields[p.JSONTimeKey] == nil {
|
||||||
|
err := fmt.Errorf("JSON time key could not be found")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
timeStr, ok := f.Fields[p.JSONTimeKey].(string)
|
||||||
|
if !ok {
|
||||||
|
err := fmt.Errorf("time: %v could not be converted to string", f.Fields[p.JSONTimeKey])
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nTime, err = time.Parse(p.JSONTimeFormat, timeStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//if the year is 0, set to current year
|
||||||
|
if nTime.Year() == 0 {
|
||||||
|
nTime = nTime.AddDate(time.Now().Year(), 0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tags, nFields := p.switchFieldToTag(tags, f.Fields)
|
tags, nFields := p.switchFieldToTag(tags, f.Fields)
|
||||||
|
metric, err := metric.New(p.MetricName, tags, nFields, nTime)
|
||||||
metric, err := metric.New(p.MetricName, tags, nFields, time.Now().UTC())
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -88,6 +129,17 @@ func (p *JSONParser) switchFieldToTag(tags map[string]string, fields map[string]
|
||||||
|
|
||||||
//remove any additional string/bool values from fields
|
//remove any additional string/bool values from fields
|
||||||
for k := range fields {
|
for k := range fields {
|
||||||
|
//check if field is in StringFields
|
||||||
|
sField := false
|
||||||
|
for _, v := range p.StringFields {
|
||||||
|
if v == k {
|
||||||
|
sField = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sField {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
switch fields[k].(type) {
|
switch fields[k].(type) {
|
||||||
case string:
|
case string:
|
||||||
delete(fields, k)
|
delete(fields, k)
|
||||||
|
@ -99,6 +151,15 @@ func (p *JSONParser) switchFieldToTag(tags map[string]string, fields map[string]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *JSONParser) Parse(buf []byte) ([]telegraf.Metric, error) {
|
func (p *JSONParser) Parse(buf []byte) ([]telegraf.Metric, error) {
|
||||||
|
if p.JSONQuery != "" {
|
||||||
|
result := gjson.GetBytes(buf, p.JSONQuery)
|
||||||
|
buf = []byte(result.Raw)
|
||||||
|
if !result.IsArray() && !result.IsObject() {
|
||||||
|
err := fmt.Errorf("E! Query path must lead to a JSON object or array of objects, but lead to: %v", result.Type)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buf = bytes.TrimSpace(buf)
|
buf = bytes.TrimSpace(buf)
|
||||||
buf = bytes.TrimPrefix(buf, utf8BOM)
|
buf = bytes.TrimPrefix(buf, utf8BOM)
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
|
@ -126,7 +187,7 @@ func (p *JSONParser) ParseLine(line string) (telegraf.Metric, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(metrics) < 1 {
|
if len(metrics) < 1 {
|
||||||
return nil, fmt.Errorf("Can not parse the line: %s, for data format: influx ", line)
|
return nil, fmt.Errorf("can not parse the line: %s, for data format: json ", line)
|
||||||
}
|
}
|
||||||
|
|
||||||
return metrics[0], nil
|
return metrics[0], nil
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,46 +56,46 @@ func TestParseValidJSON(t *testing.T) {
|
||||||
|
|
||||||
// Most basic vanilla test
|
// Most basic vanilla test
|
||||||
metrics, err := parser.Parse([]byte(validJSON))
|
metrics, err := parser.Parse([]byte(validJSON))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 1)
|
require.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "json_test", metrics[0].Name())
|
require.Equal(t, "json_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{}, metrics[0].Tags())
|
require.Equal(t, map[string]string{}, metrics[0].Tags())
|
||||||
|
|
||||||
// Test that newlines are fine
|
// Test that newlines are fine
|
||||||
metrics, err = parser.Parse([]byte(validJSONNewline))
|
metrics, err = parser.Parse([]byte(validJSONNewline))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 1)
|
require.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "json_test", metrics[0].Name())
|
require.Equal(t, "json_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"d": float64(7),
|
"d": float64(7),
|
||||||
"b_d": float64(8),
|
"b_d": float64(8),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{}, metrics[0].Tags())
|
require.Equal(t, map[string]string{}, metrics[0].Tags())
|
||||||
|
|
||||||
// Test that strings without TagKeys defined are ignored
|
// Test that strings without TagKeys defined are ignored
|
||||||
metrics, err = parser.Parse([]byte(validJSONTags))
|
metrics, err = parser.Parse([]byte(validJSONTags))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 1)
|
require.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "json_test", metrics[0].Name())
|
require.Equal(t, "json_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{}, metrics[0].Tags())
|
require.Equal(t, map[string]string{}, metrics[0].Tags())
|
||||||
|
|
||||||
// Test that whitespace only will parse as an empty list of metrics
|
// Test that whitespace only will parse as an empty list of metrics
|
||||||
metrics, err = parser.Parse([]byte("\n\t"))
|
metrics, err = parser.Parse([]byte("\n\t"))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 0)
|
require.Len(t, metrics, 0)
|
||||||
|
|
||||||
// Test that an empty string will parse as an empty list of metrics
|
// Test that an empty string will parse as an empty list of metrics
|
||||||
metrics, err = parser.Parse([]byte(""))
|
metrics, err = parser.Parse([]byte(""))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 0)
|
require.Len(t, metrics, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseLineValidJSON(t *testing.T) {
|
func TestParseLineValidJSON(t *testing.T) {
|
||||||
|
@ -104,33 +105,33 @@ func TestParseLineValidJSON(t *testing.T) {
|
||||||
|
|
||||||
// Most basic vanilla test
|
// Most basic vanilla test
|
||||||
metric, err := parser.ParseLine(validJSON)
|
metric, err := parser.ParseLine(validJSON)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "json_test", metric.Name())
|
require.Equal(t, "json_test", metric.Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metric.Fields())
|
}, metric.Fields())
|
||||||
assert.Equal(t, map[string]string{}, metric.Tags())
|
require.Equal(t, map[string]string{}, metric.Tags())
|
||||||
|
|
||||||
// Test that newlines are fine
|
// Test that newlines are fine
|
||||||
metric, err = parser.ParseLine(validJSONNewline)
|
metric, err = parser.ParseLine(validJSONNewline)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "json_test", metric.Name())
|
require.Equal(t, "json_test", metric.Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"d": float64(7),
|
"d": float64(7),
|
||||||
"b_d": float64(8),
|
"b_d": float64(8),
|
||||||
}, metric.Fields())
|
}, metric.Fields())
|
||||||
assert.Equal(t, map[string]string{}, metric.Tags())
|
require.Equal(t, map[string]string{}, metric.Tags())
|
||||||
|
|
||||||
// Test that strings without TagKeys defined are ignored
|
// Test that strings without TagKeys defined are ignored
|
||||||
metric, err = parser.ParseLine(validJSONTags)
|
metric, err = parser.ParseLine(validJSONTags)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "json_test", metric.Name())
|
require.Equal(t, "json_test", metric.Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metric.Fields())
|
}, metric.Fields())
|
||||||
assert.Equal(t, map[string]string{}, metric.Tags())
|
require.Equal(t, map[string]string{}, metric.Tags())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseInvalidJSON(t *testing.T) {
|
func TestParseInvalidJSON(t *testing.T) {
|
||||||
|
@ -139,11 +140,11 @@ func TestParseInvalidJSON(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := parser.Parse([]byte(invalidJSON))
|
_, err := parser.Parse([]byte(invalidJSON))
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
_, err = parser.Parse([]byte(invalidJSON2))
|
_, err = parser.Parse([]byte(invalidJSON2))
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
_, err = parser.ParseLine(invalidJSON)
|
_, err = parser.ParseLine(invalidJSON)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseWithTagKeys(t *testing.T) {
|
func TestParseWithTagKeys(t *testing.T) {
|
||||||
|
@ -153,14 +154,14 @@ func TestParseWithTagKeys(t *testing.T) {
|
||||||
TagKeys: []string{"wrongtagkey"},
|
TagKeys: []string{"wrongtagkey"},
|
||||||
}
|
}
|
||||||
metrics, err := parser.Parse([]byte(validJSONTags))
|
metrics, err := parser.Parse([]byte(validJSONTags))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 1)
|
require.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "json_test", metrics[0].Name())
|
require.Equal(t, "json_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{}, metrics[0].Tags())
|
require.Equal(t, map[string]string{}, metrics[0].Tags())
|
||||||
|
|
||||||
// Test that single tag key is found and applied
|
// Test that single tag key is found and applied
|
||||||
parser = JSONParser{
|
parser = JSONParser{
|
||||||
|
@ -168,14 +169,14 @@ func TestParseWithTagKeys(t *testing.T) {
|
||||||
TagKeys: []string{"mytag"},
|
TagKeys: []string{"mytag"},
|
||||||
}
|
}
|
||||||
metrics, err = parser.Parse([]byte(validJSONTags))
|
metrics, err = parser.Parse([]byte(validJSONTags))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 1)
|
require.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "json_test", metrics[0].Name())
|
require.Equal(t, "json_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"mytag": "foobar",
|
"mytag": "foobar",
|
||||||
}, metrics[0].Tags())
|
}, metrics[0].Tags())
|
||||||
|
|
||||||
|
@ -185,14 +186,14 @@ func TestParseWithTagKeys(t *testing.T) {
|
||||||
TagKeys: []string{"mytag", "othertag"},
|
TagKeys: []string{"mytag", "othertag"},
|
||||||
}
|
}
|
||||||
metrics, err = parser.Parse([]byte(validJSONTags))
|
metrics, err = parser.Parse([]byte(validJSONTags))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 1)
|
require.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "json_test", metrics[0].Name())
|
require.Equal(t, "json_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"mytag": "foobar",
|
"mytag": "foobar",
|
||||||
"othertag": "baz",
|
"othertag": "baz",
|
||||||
}, metrics[0].Tags())
|
}, metrics[0].Tags())
|
||||||
|
@ -205,13 +206,13 @@ func TestParseLineWithTagKeys(t *testing.T) {
|
||||||
TagKeys: []string{"wrongtagkey"},
|
TagKeys: []string{"wrongtagkey"},
|
||||||
}
|
}
|
||||||
metric, err := parser.ParseLine(validJSONTags)
|
metric, err := parser.ParseLine(validJSONTags)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "json_test", metric.Name())
|
require.Equal(t, "json_test", metric.Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metric.Fields())
|
}, metric.Fields())
|
||||||
assert.Equal(t, map[string]string{}, metric.Tags())
|
require.Equal(t, map[string]string{}, metric.Tags())
|
||||||
|
|
||||||
// Test that single tag key is found and applied
|
// Test that single tag key is found and applied
|
||||||
parser = JSONParser{
|
parser = JSONParser{
|
||||||
|
@ -219,13 +220,13 @@ func TestParseLineWithTagKeys(t *testing.T) {
|
||||||
TagKeys: []string{"mytag"},
|
TagKeys: []string{"mytag"},
|
||||||
}
|
}
|
||||||
metric, err = parser.ParseLine(validJSONTags)
|
metric, err = parser.ParseLine(validJSONTags)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "json_test", metric.Name())
|
require.Equal(t, "json_test", metric.Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metric.Fields())
|
}, metric.Fields())
|
||||||
assert.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"mytag": "foobar",
|
"mytag": "foobar",
|
||||||
}, metric.Tags())
|
}, metric.Tags())
|
||||||
|
|
||||||
|
@ -235,13 +236,13 @@ func TestParseLineWithTagKeys(t *testing.T) {
|
||||||
TagKeys: []string{"mytag", "othertag"},
|
TagKeys: []string{"mytag", "othertag"},
|
||||||
}
|
}
|
||||||
metric, err = parser.ParseLine(validJSONTags)
|
metric, err = parser.ParseLine(validJSONTags)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "json_test", metric.Name())
|
require.Equal(t, "json_test", metric.Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metric.Fields())
|
}, metric.Fields())
|
||||||
assert.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"mytag": "foobar",
|
"mytag": "foobar",
|
||||||
"othertag": "baz",
|
"othertag": "baz",
|
||||||
}, metric.Tags())
|
}, metric.Tags())
|
||||||
|
@ -258,25 +259,25 @@ func TestParseValidJSONDefaultTags(t *testing.T) {
|
||||||
|
|
||||||
// Most basic vanilla test
|
// Most basic vanilla test
|
||||||
metrics, err := parser.Parse([]byte(validJSON))
|
metrics, err := parser.Parse([]byte(validJSON))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 1)
|
require.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "json_test", metrics[0].Name())
|
require.Equal(t, "json_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{"t4g": "default"}, metrics[0].Tags())
|
require.Equal(t, map[string]string{"t4g": "default"}, metrics[0].Tags())
|
||||||
|
|
||||||
// Test that tagkeys and default tags are applied
|
// Test that tagkeys and default tags are applied
|
||||||
metrics, err = parser.Parse([]byte(validJSONTags))
|
metrics, err = parser.Parse([]byte(validJSONTags))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 1)
|
require.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "json_test", metrics[0].Name())
|
require.Equal(t, "json_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"t4g": "default",
|
"t4g": "default",
|
||||||
"mytag": "foobar",
|
"mytag": "foobar",
|
||||||
}, metrics[0].Tags())
|
}, metrics[0].Tags())
|
||||||
|
@ -294,25 +295,25 @@ func TestParseValidJSONDefaultTagsOverride(t *testing.T) {
|
||||||
|
|
||||||
// Most basic vanilla test
|
// Most basic vanilla test
|
||||||
metrics, err := parser.Parse([]byte(validJSON))
|
metrics, err := parser.Parse([]byte(validJSON))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 1)
|
require.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "json_test", metrics[0].Name())
|
require.Equal(t, "json_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{"mytag": "default"}, metrics[0].Tags())
|
require.Equal(t, map[string]string{"mytag": "default"}, metrics[0].Tags())
|
||||||
|
|
||||||
// Test that tagkeys override default tags
|
// Test that tagkeys override default tags
|
||||||
metrics, err = parser.Parse([]byte(validJSONTags))
|
metrics, err = parser.Parse([]byte(validJSONTags))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 1)
|
require.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "json_test", metrics[0].Name())
|
require.Equal(t, "json_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"mytag": "foobar",
|
"mytag": "foobar",
|
||||||
}, metrics[0].Tags())
|
}, metrics[0].Tags())
|
||||||
}
|
}
|
||||||
|
@ -325,31 +326,31 @@ func TestParseValidJSONArray(t *testing.T) {
|
||||||
|
|
||||||
// Most basic vanilla test
|
// Most basic vanilla test
|
||||||
metrics, err := parser.Parse([]byte(validJSONArray))
|
metrics, err := parser.Parse([]byte(validJSONArray))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 1)
|
require.Len(t, metrics, 1)
|
||||||
assert.Equal(t, "json_array_test", metrics[0].Name())
|
require.Equal(t, "json_array_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{}, metrics[0].Tags())
|
require.Equal(t, map[string]string{}, metrics[0].Tags())
|
||||||
|
|
||||||
// Basic multiple datapoints
|
// Basic multiple datapoints
|
||||||
metrics, err = parser.Parse([]byte(validJSONArrayMultiple))
|
metrics, err = parser.Parse([]byte(validJSONArrayMultiple))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 2)
|
require.Len(t, metrics, 2)
|
||||||
assert.Equal(t, "json_array_test", metrics[0].Name())
|
require.Equal(t, "json_array_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{}, metrics[1].Tags())
|
require.Equal(t, map[string]string{}, metrics[1].Tags())
|
||||||
assert.Equal(t, "json_array_test", metrics[1].Name())
|
require.Equal(t, "json_array_test", metrics[1].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(7),
|
"a": float64(7),
|
||||||
"b_c": float64(8),
|
"b_c": float64(8),
|
||||||
}, metrics[1].Fields())
|
}, metrics[1].Fields())
|
||||||
assert.Equal(t, map[string]string{}, metrics[1].Tags())
|
require.Equal(t, map[string]string{}, metrics[1].Tags())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseArrayWithTagKeys(t *testing.T) {
|
func TestParseArrayWithTagKeys(t *testing.T) {
|
||||||
|
@ -359,21 +360,21 @@ func TestParseArrayWithTagKeys(t *testing.T) {
|
||||||
TagKeys: []string{"wrongtagkey"},
|
TagKeys: []string{"wrongtagkey"},
|
||||||
}
|
}
|
||||||
metrics, err := parser.Parse([]byte(validJSONArrayTags))
|
metrics, err := parser.Parse([]byte(validJSONArrayTags))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 2)
|
require.Len(t, metrics, 2)
|
||||||
assert.Equal(t, "json_array_test", metrics[0].Name())
|
require.Equal(t, "json_array_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{}, metrics[0].Tags())
|
require.Equal(t, map[string]string{}, metrics[0].Tags())
|
||||||
|
|
||||||
assert.Equal(t, "json_array_test", metrics[1].Name())
|
require.Equal(t, "json_array_test", metrics[1].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(7),
|
"a": float64(7),
|
||||||
"b_c": float64(8),
|
"b_c": float64(8),
|
||||||
}, metrics[1].Fields())
|
}, metrics[1].Fields())
|
||||||
assert.Equal(t, map[string]string{}, metrics[1].Tags())
|
require.Equal(t, map[string]string{}, metrics[1].Tags())
|
||||||
|
|
||||||
// Test that single tag key is found and applied
|
// Test that single tag key is found and applied
|
||||||
parser = JSONParser{
|
parser = JSONParser{
|
||||||
|
@ -381,23 +382,23 @@ func TestParseArrayWithTagKeys(t *testing.T) {
|
||||||
TagKeys: []string{"mytag"},
|
TagKeys: []string{"mytag"},
|
||||||
}
|
}
|
||||||
metrics, err = parser.Parse([]byte(validJSONArrayTags))
|
metrics, err = parser.Parse([]byte(validJSONArrayTags))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 2)
|
require.Len(t, metrics, 2)
|
||||||
assert.Equal(t, "json_array_test", metrics[0].Name())
|
require.Equal(t, "json_array_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"mytag": "foo",
|
"mytag": "foo",
|
||||||
}, metrics[0].Tags())
|
}, metrics[0].Tags())
|
||||||
|
|
||||||
assert.Equal(t, "json_array_test", metrics[1].Name())
|
require.Equal(t, "json_array_test", metrics[1].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(7),
|
"a": float64(7),
|
||||||
"b_c": float64(8),
|
"b_c": float64(8),
|
||||||
}, metrics[1].Fields())
|
}, metrics[1].Fields())
|
||||||
assert.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"mytag": "bar",
|
"mytag": "bar",
|
||||||
}, metrics[1].Tags())
|
}, metrics[1].Tags())
|
||||||
|
|
||||||
|
@ -407,24 +408,24 @@ func TestParseArrayWithTagKeys(t *testing.T) {
|
||||||
TagKeys: []string{"mytag", "othertag"},
|
TagKeys: []string{"mytag", "othertag"},
|
||||||
}
|
}
|
||||||
metrics, err = parser.Parse([]byte(validJSONArrayTags))
|
metrics, err = parser.Parse([]byte(validJSONArrayTags))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, metrics, 2)
|
require.Len(t, metrics, 2)
|
||||||
assert.Equal(t, "json_array_test", metrics[0].Name())
|
require.Equal(t, "json_array_test", metrics[0].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(5),
|
"a": float64(5),
|
||||||
"b_c": float64(6),
|
"b_c": float64(6),
|
||||||
}, metrics[0].Fields())
|
}, metrics[0].Fields())
|
||||||
assert.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"mytag": "foo",
|
"mytag": "foo",
|
||||||
"othertag": "baz",
|
"othertag": "baz",
|
||||||
}, metrics[0].Tags())
|
}, metrics[0].Tags())
|
||||||
|
|
||||||
assert.Equal(t, "json_array_test", metrics[1].Name())
|
require.Equal(t, "json_array_test", metrics[1].Name())
|
||||||
assert.Equal(t, map[string]interface{}{
|
require.Equal(t, map[string]interface{}{
|
||||||
"a": float64(7),
|
"a": float64(7),
|
||||||
"b_c": float64(8),
|
"b_c": float64(8),
|
||||||
}, metrics[1].Fields())
|
}, metrics[1].Fields())
|
||||||
assert.Equal(t, map[string]string{
|
require.Equal(t, map[string]string{
|
||||||
"mytag": "bar",
|
"mytag": "bar",
|
||||||
"othertag": "baz",
|
"othertag": "baz",
|
||||||
}, metrics[1].Tags())
|
}, metrics[1].Tags())
|
||||||
|
@ -439,7 +440,7 @@ func TestHttpJsonBOM(t *testing.T) {
|
||||||
|
|
||||||
// Most basic vanilla test
|
// Most basic vanilla test
|
||||||
_, err := parser.Parse(jsonBOM)
|
_, err := parser.Parse(jsonBOM)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//for testing issue #4260
|
//for testing issue #4260
|
||||||
|
@ -448,22 +449,212 @@ func TestJSONParseNestedArray(t *testing.T) {
|
||||||
"total_devices": 5,
|
"total_devices": 5,
|
||||||
"total_threads": 10,
|
"total_threads": 10,
|
||||||
"shares": {
|
"shares": {
|
||||||
"total": 5,
|
"total": 5,
|
||||||
"accepted": 5,
|
"accepted": 5,
|
||||||
"rejected": 0,
|
"rejected": 0,
|
||||||
"avg_find_time": 4,
|
"avg_find_time": 4,
|
||||||
"tester": "work",
|
"tester": "work",
|
||||||
"tester2": "don't want this",
|
"tester2": "don't want this",
|
||||||
"tester3": 7.93
|
"tester3": {
|
||||||
|
"hello":"sup",
|
||||||
|
"fun":"money",
|
||||||
|
"break":9
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
parser := JSONParser{
|
parser := JSONParser{
|
||||||
MetricName: "json_test",
|
MetricName: "json_test",
|
||||||
TagKeys: []string{"total_devices", "total_threads", "shares_tester", "shares_tester3"},
|
TagKeys: []string{"total_devices", "total_threads", "shares_tester3_fun"},
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics, err := parser.Parse([]byte(testString))
|
||||||
|
log.Printf("m[0] name: %v, tags: %v, fields: %v", metrics[0].Name(), metrics[0].Tags(), metrics[0].Fields())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, len(parser.TagKeys), len(metrics[0].Tags()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONQueryErrorOnArray(t *testing.T) {
|
||||||
|
testString := `{
|
||||||
|
"total_devices": 5,
|
||||||
|
"total_threads": 10,
|
||||||
|
"shares": {
|
||||||
|
"total": 5,
|
||||||
|
"accepted": 6,
|
||||||
|
"test_string": "don't want this",
|
||||||
|
"test_obj": {
|
||||||
|
"hello":"sup",
|
||||||
|
"fun":"money",
|
||||||
|
"break":9
|
||||||
|
},
|
||||||
|
"myArr":[4,5,6]
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
parser := JSONParser{
|
||||||
|
MetricName: "json_test",
|
||||||
|
TagKeys: []string{},
|
||||||
|
JSONQuery: "shares.myArr",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := parser.Parse([]byte(testString))
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestArrayOfObjects(t *testing.T) {
|
||||||
|
testString := `{
|
||||||
|
"meta": {
|
||||||
|
"info":9,
|
||||||
|
"shares": [{
|
||||||
|
"channel": 6,
|
||||||
|
"time": 1130,
|
||||||
|
"ice":"man"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"channel": 5,
|
||||||
|
"time": 1030,
|
||||||
|
"ice":"bucket"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"channel": 10,
|
||||||
|
"time": 330,
|
||||||
|
"ice":"cream"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"more_stuff":"junk"
|
||||||
|
}`
|
||||||
|
|
||||||
|
parser := JSONParser{
|
||||||
|
MetricName: "json_test",
|
||||||
|
TagKeys: []string{"ice"},
|
||||||
|
JSONQuery: "meta.shares",
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics, err := parser.Parse([]byte(testString))
|
metrics, err := parser.Parse([]byte(testString))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, len(parser.TagKeys), len(metrics[0].Tags()))
|
require.Equal(t, 3, len(metrics))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUseCaseJSONQuery(t *testing.T) {
|
||||||
|
testString := `{
|
||||||
|
"obj": {
|
||||||
|
"name": {"first": "Tom", "last": "Anderson"},
|
||||||
|
"age":37,
|
||||||
|
"children": ["Sara","Alex","Jack"],
|
||||||
|
"fav.movie": "Deer Hunter",
|
||||||
|
"friends": [
|
||||||
|
{"first": "Dale", "last": "Murphy", "age": 44},
|
||||||
|
{"first": "Roger", "last": "Craig", "age": 68},
|
||||||
|
{"first": "Jane", "last": "Murphy", "age": 47}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
parser := JSONParser{
|
||||||
|
MetricName: "json_test",
|
||||||
|
StringFields: []string{"last"},
|
||||||
|
TagKeys: []string{"first"},
|
||||||
|
JSONQuery: "obj.friends",
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics, err := parser.Parse([]byte(testString))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 3, len(metrics))
|
||||||
|
require.Equal(t, metrics[0].Fields()["last"], "Murphy")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimeParser(t *testing.T) {
|
||||||
|
testString := `[
|
||||||
|
{
|
||||||
|
"a": 5,
|
||||||
|
"b": {
|
||||||
|
"c": 6,
|
||||||
|
"time":"04 Jan 06 15:04 MST"
|
||||||
|
},
|
||||||
|
"my_tag_1": "foo",
|
||||||
|
"my_tag_2": "baz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a": 7,
|
||||||
|
"b": {
|
||||||
|
"c": 8,
|
||||||
|
"time":"11 Jan 07 15:04 MST"
|
||||||
|
},
|
||||||
|
"my_tag_1": "bar",
|
||||||
|
"my_tag_2": "baz"
|
||||||
|
}
|
||||||
|
]`
|
||||||
|
|
||||||
|
parser := JSONParser{
|
||||||
|
MetricName: "json_test",
|
||||||
|
JSONTimeKey: "b_time",
|
||||||
|
JSONTimeFormat: "02 Jan 06 15:04 MST",
|
||||||
|
}
|
||||||
|
metrics, err := parser.Parse([]byte(testString))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 2, len(metrics))
|
||||||
|
require.Equal(t, false, metrics[0].Time() == metrics[1].Time())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimeErrors(t *testing.T) {
|
||||||
|
testString := `{
|
||||||
|
"a": 5,
|
||||||
|
"b": {
|
||||||
|
"c": 6,
|
||||||
|
"time":"04 Jan 06 15:04 MST"
|
||||||
|
},
|
||||||
|
"my_tag_1": "foo",
|
||||||
|
"my_tag_2": "baz"
|
||||||
|
}`
|
||||||
|
|
||||||
|
parser := JSONParser{
|
||||||
|
MetricName: "json_test",
|
||||||
|
JSONTimeKey: "b_time",
|
||||||
|
JSONTimeFormat: "02 January 06 15:04 MST",
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics, err := parser.Parse([]byte(testString))
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, 0, len(metrics))
|
||||||
|
|
||||||
|
testString2 := `{
|
||||||
|
"a": 5,
|
||||||
|
"b": {
|
||||||
|
"c": 6
|
||||||
|
},
|
||||||
|
"my_tag_1": "foo",
|
||||||
|
"my_tag_2": "baz"
|
||||||
|
}`
|
||||||
|
|
||||||
|
parser = JSONParser{
|
||||||
|
MetricName: "json_test",
|
||||||
|
JSONTimeKey: "b_time",
|
||||||
|
JSONTimeFormat: "02 January 06 15:04 MST",
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics, err = parser.Parse([]byte(testString2))
|
||||||
|
log.Printf("err: %v", err)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, 0, len(metrics))
|
||||||
|
require.Equal(t, fmt.Errorf("JSON time key could not be found"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNameKey(t *testing.T) {
|
||||||
|
testString := `{
|
||||||
|
"a": 5,
|
||||||
|
"b": {
|
||||||
|
"c": "this is my name",
|
||||||
|
"time":"04 Jan 06 15:04 MST"
|
||||||
|
},
|
||||||
|
"my_tag_1": "foo",
|
||||||
|
"my_tag_2": "baz"
|
||||||
|
}`
|
||||||
|
|
||||||
|
parser := JSONParser{
|
||||||
|
JSONNameKey: "b_c",
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics, err := parser.Parse([]byte(testString))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "this is my name", metrics[0].Name())
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,9 +59,22 @@ type Config struct {
|
||||||
|
|
||||||
// TagKeys only apply to JSON data
|
// TagKeys only apply to JSON data
|
||||||
TagKeys []string
|
TagKeys []string
|
||||||
|
// FieldKeys only apply to JSON
|
||||||
|
JSONStringFields []string
|
||||||
|
|
||||||
|
JSONNameKey string
|
||||||
// MetricName applies to JSON & value. This will be the name of the measurement.
|
// MetricName applies to JSON & value. This will be the name of the measurement.
|
||||||
MetricName string
|
MetricName string
|
||||||
|
|
||||||
|
// holds a gjson path for json parser
|
||||||
|
JSONQuery string
|
||||||
|
|
||||||
|
// key of time
|
||||||
|
JSONTimeKey string
|
||||||
|
|
||||||
|
// time format
|
||||||
|
JSONTimeFormat string
|
||||||
|
|
||||||
// Authentication file for collectd
|
// Authentication file for collectd
|
||||||
CollectdAuthFile string
|
CollectdAuthFile string
|
||||||
// One of none (default), sign, or encrypt
|
// One of none (default), sign, or encrypt
|
||||||
|
@ -108,8 +121,14 @@ func NewParser(config *Config) (Parser, error) {
|
||||||
var parser Parser
|
var parser Parser
|
||||||
switch config.DataFormat {
|
switch config.DataFormat {
|
||||||
case "json":
|
case "json":
|
||||||
parser, err = NewJSONParser(config.MetricName,
|
parser = newJSONParser(config.MetricName,
|
||||||
config.TagKeys, config.DefaultTags)
|
config.TagKeys,
|
||||||
|
config.JSONNameKey,
|
||||||
|
config.JSONStringFields,
|
||||||
|
config.JSONQuery,
|
||||||
|
config.JSONTimeKey,
|
||||||
|
config.JSONTimeFormat,
|
||||||
|
config.DefaultTags)
|
||||||
case "value":
|
case "value":
|
||||||
parser, err = NewValueParser(config.MetricName,
|
parser, err = NewValueParser(config.MetricName,
|
||||||
config.DataType, config.DefaultTags)
|
config.DataType, config.DefaultTags)
|
||||||
|
@ -151,6 +170,30 @@ func NewParser(config *Config) (Parser, error) {
|
||||||
return parser, err
|
return parser, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newJSONParser(
|
||||||
|
metricName string,
|
||||||
|
tagKeys []string,
|
||||||
|
jsonNameKey string,
|
||||||
|
stringFields []string,
|
||||||
|
jsonQuery string,
|
||||||
|
timeKey string,
|
||||||
|
timeFormat string,
|
||||||
|
defaultTags map[string]string,
|
||||||
|
) Parser {
|
||||||
|
parser := &json.JSONParser{
|
||||||
|
MetricName: metricName,
|
||||||
|
TagKeys: tagKeys,
|
||||||
|
StringFields: stringFields,
|
||||||
|
JSONNameKey: jsonNameKey,
|
||||||
|
JSONQuery: jsonQuery,
|
||||||
|
JSONTimeKey: timeKey,
|
||||||
|
JSONTimeFormat: timeFormat,
|
||||||
|
DefaultTags: defaultTags,
|
||||||
|
}
|
||||||
|
return parser
|
||||||
|
}
|
||||||
|
|
||||||
|
//Deprecated: Use NewParser to get a JSONParser object
|
||||||
func newGrokParser(metricName string,
|
func newGrokParser(metricName string,
|
||||||
patterns []string,
|
patterns []string,
|
||||||
nPatterns []string,
|
nPatterns []string,
|
||||||
|
|
Loading…
Reference in New Issue