Use an 'auto' parser by default for value input format

This commit is contained in:
Cameron Sparr 2016-04-05 18:37:46 -06:00
parent 0f16c0f4cf
commit 416591006b
3 changed files with 90 additions and 4 deletions

View File

@ -150,8 +150,14 @@ as the parsed metric.
#### Value Configuration: #### Value Configuration:
You **must** tell Telegraf what type of metric to collect by using the You **should** tell Telegraf what type of metric to collect by using the
`data_type` configuration option. `data_type` configuration option. The options are:
1. integer
1. float
1. string
1. boolean
1. auto (this will try parsing into the above types, in order)
**Note:** It is also recommended that you set `name_override` to a measurement **Note:** It is also recommended that you set `name_override` to a measurement
name that makes sense for your metric, otherwise it will just be set to the name that makes sense for your metric, otherwise it will just be set to the
@ -170,7 +176,7 @@ name of the plugin.
## more about them here: ## more about them here:
## 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 = "value" data_format = "value"
data_type = "integer" # required data_type = "integer"
``` ```
# Graphite: # Graphite:

View File

@ -26,7 +26,9 @@ func (v *ValueParser) Parse(buf []byte) ([]telegraf.Metric, error) {
var value interface{} var value interface{}
var err error var err error
switch v.DataType { switch v.DataType {
case "", "int", "integer": case "", "auto":
value, err = autoParse(valueStr)
case "int", "integer":
value, err = strconv.Atoi(valueStr) value, err = strconv.Atoi(valueStr)
case "float", "long": case "float", "long":
value, err = strconv.ParseFloat(valueStr, 64) value, err = strconv.ParseFloat(valueStr, 64)
@ -49,6 +51,30 @@ func (v *ValueParser) Parse(buf []byte) ([]telegraf.Metric, error) {
return []telegraf.Metric{metric}, nil return []telegraf.Metric{metric}, nil
} }
// autoParse tries to parse the given string into (in order):
// 1. integer
// 2. float
// 3. boolean
// 4. string
func autoParse(valueStr string) (interface{}, error) {
var value interface{}
var err error
// 1st try integer:
if value, err = strconv.Atoi(valueStr); err == nil {
return value, err
}
// 2nd try float:
if value, err = strconv.ParseFloat(valueStr, 64); err == nil {
return value, err
}
// 3rd try boolean:
if value, err = strconv.ParseBool(valueStr); err == nil {
return value, err
}
// 4th, none worked, so string
return valueStr, nil
}
func (v *ValueParser) ParseLine(line string) (telegraf.Metric, error) { func (v *ValueParser) ParseLine(line string) (telegraf.Metric, error) {
metrics, err := v.Parse([]byte(line)) metrics, err := v.Parse([]byte(line))

View File

@ -60,6 +60,60 @@ func TestParseValidValues(t *testing.T) {
assert.Equal(t, map[string]string{}, metrics[0].Tags()) assert.Equal(t, map[string]string{}, metrics[0].Tags())
} }
func TestParseAutoValues(t *testing.T) {
parser := ValueParser{
MetricName: "value_test",
DataType: "auto",
}
metrics, err := parser.Parse([]byte("55"))
assert.NoError(t, err)
assert.Len(t, metrics, 1)
assert.Equal(t, "value_test", metrics[0].Name())
assert.Equal(t, map[string]interface{}{
"value": int64(55),
}, metrics[0].Fields())
assert.Equal(t, map[string]string{}, metrics[0].Tags())
parser = ValueParser{
MetricName: "value_test",
DataType: "auto",
}
metrics, err = parser.Parse([]byte("64.1"))
assert.NoError(t, err)
assert.Len(t, metrics, 1)
assert.Equal(t, "value_test", metrics[0].Name())
assert.Equal(t, map[string]interface{}{
"value": float64(64.1),
}, metrics[0].Fields())
assert.Equal(t, map[string]string{}, metrics[0].Tags())
parser = ValueParser{
MetricName: "value_test",
DataType: "auto",
}
metrics, err = parser.Parse([]byte("foobar"))
assert.NoError(t, err)
assert.Len(t, metrics, 1)
assert.Equal(t, "value_test", metrics[0].Name())
assert.Equal(t, map[string]interface{}{
"value": "foobar",
}, metrics[0].Fields())
assert.Equal(t, map[string]string{}, metrics[0].Tags())
parser = ValueParser{
MetricName: "value_test",
DataType: "auto",
}
metrics, err = parser.Parse([]byte("true"))
assert.NoError(t, err)
assert.Len(t, metrics, 1)
assert.Equal(t, "value_test", metrics[0].Name())
assert.Equal(t, map[string]interface{}{
"value": true,
}, metrics[0].Fields())
assert.Equal(t, map[string]string{}, metrics[0].Tags())
}
func TestParseMultipleValues(t *testing.T) { func TestParseMultipleValues(t *testing.T) {
parser := ValueParser{ parser := ValueParser{
MetricName: "value_test", MetricName: "value_test",