Skip to content

Commit

Permalink
Fix bool serialization when using carbon2
Browse files Browse the repository at this point in the history
  • Loading branch information
pmalek committed Sep 28, 2020
1 parent 998611f commit 9f8bdb4
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 5 deletions.
32 changes: 27 additions & 5 deletions plugins/serializers/carbon2/carbon2.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (s *Serializer) createObject(metric telegraf.Metric) []byte {
metricsFormat := s.getMetricsFormat()

for fieldName, fieldValue := range metric.Fields() {
if !isNumeric(fieldValue) {
if isString(fieldValue) {
continue
}

Expand Down Expand Up @@ -86,7 +86,7 @@ func (s *Serializer) createObject(metric telegraf.Metric) []byte {
m.WriteString(" ")
}
m.WriteString(" ")
m.WriteString(fmt.Sprintf("%v", fieldValue))
m.WriteString(formatValue(fieldValue))
m.WriteString(" ")
m.WriteString(strconv.FormatInt(metric.Time().Unix(), 10))
m.WriteString("\n")
Expand Down Expand Up @@ -126,11 +126,33 @@ func serializeMetricIncludeField(name, fieldName string) string {
)
}

func isNumeric(v interface{}) bool {
func formatValue(fieldValue interface{}) string {
switch v := fieldValue.(type) {
case bool:
// Print bools as 0s and 1s
return fmt.Sprintf("%d", bool2int(v))
default:
return fmt.Sprintf("%v", v)
}
}

func isString(v interface{}) bool {
switch v.(type) {
case string:
return false
default:
return true
default:
return false
}
}

func bool2int(b bool) int {
// Slightly more optimized than a usual if ... return ... else return ... .
// See: https://0x0f.me/blog/golang-compiler-optimization/
var i int
if b {
i = 1
} else {
i = 0
}
return i
}
57 changes: 57 additions & 0 deletions plugins/serializers/carbon2/carbon2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,63 @@ func TestSerializeMetricString(t *testing.T) {
}
}

func TestSerializeMetricBool(t *testing.T) {
requireMetric := func(t *testing.T, tim time.Time, value bool) telegraf.Metric {
tags := map[string]string{
"tag_name": "tag_value",
}
fields := map[string]interface{}{
"java_lang_GarbageCollector_Valid": value,
}

m, err := metric.New("cpu", tags, fields, tim)
require.NoError(t, err)

return m
}

now := time.Now()

testcases := []struct {
metric telegraf.Metric
format string
expected string
}{
{
metric: requireMetric(t, now, false),
format: Carbon2FormatFieldSeparate,
expected: fmt.Sprintf("metric=cpu field=java_lang_GarbageCollector_Valid tag_name=tag_value 0 %d\n", now.Unix()),
},
{
metric: requireMetric(t, now, false),
format: Carbon2FormatMetricIncludesField,
expected: fmt.Sprintf("metric=cpu_java_lang_GarbageCollector_Valid tag_name=tag_value 0 %d\n", now.Unix()),
},
{
metric: requireMetric(t, now, true),
format: Carbon2FormatFieldSeparate,
expected: fmt.Sprintf("metric=cpu field=java_lang_GarbageCollector_Valid tag_name=tag_value 1 %d\n", now.Unix()),
},
{
metric: requireMetric(t, now, true),
format: Carbon2FormatMetricIncludesField,
expected: fmt.Sprintf("metric=cpu_java_lang_GarbageCollector_Valid tag_name=tag_value 1 %d\n", now.Unix()),
},
}

for _, tc := range testcases {
t.Run(tc.format, func(t *testing.T) {
s, err := NewSerializer(tc.format)
require.NoError(t, err)

buf, err := s.Serialize(tc.metric)
require.NoError(t, err)

assert.Equal(t, tc.expected, string(buf))
})
}
}

func TestSerializeBatch(t *testing.T) {
m := MustMetric(
metric.New(
Expand Down

0 comments on commit 9f8bdb4

Please sign in to comment.