Feature/1363: Additional configuration for JSON parser#4351
Feature/1363: Additional configuration for JSON parser#4351danielnelson merged 21 commits intomasterfrom
Conversation
plugins/parsers/registry.go
Outdated
| func NewJSONParser( | ||
| metricName string, | ||
| tagKeys []string, | ||
| fieldKeys []string, |
There was a problem hiding this comment.
Generally we want to avoid changing exported function signatures, as it destabilizes packages. Perhaps what we could do is add a newJSONParser that takes different (or functional) parameters. We could then update those things that call NewJSONParser directly to call NewParser, which will in turn call newJSONParser.
|
@maxunt As we discussed, let's have this be |
plugins/parsers/json/parser.go
Outdated
| nTime := time.Now().UTC() | ||
| if p.JSONTimeKey != "" { | ||
| if p.JSONTimeFormat == "" { | ||
| err := fmt.Errorf("E! If 'json_time_key' is specified, there must be a 'json_time_format'") |
There was a problem hiding this comment.
Since this is an error and not a log message, don't include the E!. As a nitpick, it would probably be good to try to come up with a shorter error string, perhaps: use of 'json_time_key' requires 'json_time_format'?
Remember to do this for the other errors, here is some more info on how "standard" Go error strings should look: https://github.com/golang/go/wiki/CodeReviewComments#error-strings
plugins/parsers/json/parser.go
Outdated
|
|
||
| func (p *JSONParser) Parse(buf []byte) ([]telegraf.Metric, error) { | ||
|
|
||
| //if json_query is specified |
There was a problem hiding this comment.
Remove this comment, it doesn't provide any new information on why and the what can be determined by looking at the code.
docs/DATA_FORMATS_INPUT.md
Outdated
| ## 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 |
There was a problem hiding this comment.
Wrap comments before 78 chars for readability.
plugins/parsers/json/parser.go
Outdated
| return nil, err | ||
| } | ||
|
|
||
| nTime, err = time.Parse(p.JSONTimeFormat, f.Fields[p.JSONTimeKey].(string)) |
There was a problem hiding this comment.
Make sure to test the type assertion since it comes from input and could be any type.
plugins/parsers/json/parser_test.go
Outdated
| } | ||
|
|
||
| _, err := parser.Parse([]byte(testString)) | ||
| assert.Error(t, err) |
There was a problem hiding this comment.
Use require instead of assert (almost) everywhere. Doesn't really matter here but this will prevent confusing chained errors.
plugins/parsers/json/parser_test.go
Outdated
| metrics, err := parser.Parse([]byte(testString)) | ||
| assert.NoError(t, err) | ||
| assert.Equal(t, metrics[0].Fields()["last"], "Murphy") | ||
| assert.Equal(t, 3, len(metrics)) |
There was a problem hiding this comment.
Check the length before indexing, this will make the test easier to understand if it fails.
plugins/parsers/json/parser_test.go
Outdated
| } | ||
| metrics, err := parser.Parse([]byte(testString)) | ||
| assert.NoError(t, err) | ||
| assert.Equal(t, false, metrics[0].Time() == metrics[1].Time()) |
There was a problem hiding this comment.
Check len(metrics) first, add some more tests to check error cases.
docs/DATA_FORMATS_INPUT.md
Outdated
|
|
||
| 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. | ||
| More info on time formats can be found here: https://golang.org/src/time/format.go |
There was a problem hiding this comment.
Use https://golang.org/pkg/time/#Parse as the link. This other link is still not great but the audience of this documentation is not Go developers.
Try to wrap around 78 chars
docs/DATA_FORMATS_INPUT.md
Outdated
|
|
||
| ## 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: |
There was a problem hiding this comment.
Add link to where gjson query paths are described
plugins/parsers/registry.go
Outdated
| // MetricName applies to JSON & value. This will be the name of the measurement. | ||
| MetricName string | ||
|
|
||
| //holds a gjson path for json parser |
There was a problem hiding this comment.
When adding comments, add a space before starting comment text (// This is my comment)
plugins/parsers/registry.go
Outdated
| timeKey string, | ||
| timeFormat string, | ||
| defaultTags map[string]string, | ||
| ) (Parser, error) { |
There was a problem hiding this comment.
Returning an error isn't useful here. Where it's an unexported function not matching any interface, I'd remove it, or remove the function altogether and just instantiate a JSONParser on line 120
There was a problem hiding this comment.
No error is ever returned by the new_Parser functions, but i thought i'd include it here to match the format of the rest of the parsers
plugins/parsers/json/parser.go
Outdated
|
|
||
| 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: influx ", line) |
There was a problem hiding this comment.
Also the copypasta, s/influx/json
There was a problem hiding this comment.
could you clarify what you mean here?
There was a problem hiding this comment.
Replace "influx" with "json", it appears to be copy paste code
There was a problem hiding this comment.
ah i see. good catch thanks
| json_time_key = "b_time" | ||
|
|
||
| ## holds the format of timestamp to be parsed | ||
| json_time_format = "02 Jan 06 15:04 MST" |
There was a problem hiding this comment.
This is an interesting example time format because there it doesn't include a year. This results in a pared time that is in year 0. I think after parsing the time we should do something similar to what we did in logparser and use the current year. While this would be pretty annoying if you actually want to store in a metric from year 0, I think it is much more likely to be what is wanted:
if ts.Year() == 0 {
ts = ts.AddDate(timestamp.Year(), 0, 0)
}
closes: #2986
Required for all PRs: