Add influx uint support as a runtime option (#3948)

This commit is contained in:
Daniel Nelson
2018-03-29 13:31:43 -07:00
committed by GitHub
parent c2108fcf09
commit b99cd14129
12 changed files with 168 additions and 84 deletions

View File

@@ -20,6 +20,12 @@ const (
SortFields
)
type FieldTypeSupport int
const (
UintSupport FieldTypeSupport = 1 << iota
)
var (
ErrNeedMoreSpace = errors.New("need more space")
ErrInvalidName = errors.New("invalid name")
@@ -32,9 +38,10 @@ var (
// Serializer is a serializer for line protocol.
type Serializer struct {
maxLineBytes int
bytesWritten int
fieldSortOrder FieldSortOrder
maxLineBytes int
bytesWritten int
fieldSortOrder FieldSortOrder
fieldTypeSupport FieldTypeSupport
buf bytes.Buffer
header []byte
@@ -61,6 +68,10 @@ func (s *Serializer) SetFieldSortOrder(order FieldSortOrder) {
s.fieldSortOrder = order
}
func (s *Serializer) SetFieldTypeSupport(typeSupport FieldTypeSupport) {
s.fieldTypeSupport = typeSupport
}
// Serialize writes the telegraf.Metric to a byte slice. May produce multiple
// lines of output if longer than maximum line length. Lines are terminated
// with a newline (LF) char.
@@ -142,7 +153,7 @@ func (s *Serializer) buildFieldPair(key string, value interface{}) error {
s.pair = append(s.pair, key...)
s.pair = append(s.pair, '=')
pair, err := appendFieldValue(s.pair, value)
pair, err := s.appendFieldValue(s.pair, value)
if err != nil {
return err
}
@@ -235,10 +246,18 @@ func (s *Serializer) writeMetric(w io.Writer, m telegraf.Metric) error {
}
func appendFieldValue(buf []byte, value interface{}) ([]byte, error) {
func (s *Serializer) appendFieldValue(buf []byte, value interface{}) ([]byte, error) {
switch v := value.(type) {
case uint64:
return appendUintField(buf, v), nil
if s.fieldTypeSupport&UintSupport != 0 {
return appendUintField(buf, v), nil
} else {
if v <= uint64(MaxInt) {
return appendIntField(buf, int64(v)), nil
} else {
return appendIntField(buf, int64(MaxInt)), nil
}
}
case int64:
return appendIntField(buf, v), nil
case float64:

View File

@@ -11,26 +11,19 @@ import (
)
func MustMetric(v telegraf.Metric, err error) telegraf.Metric {
// Force uint support to be enabled for testing.
metric.EnableUintSupport()
if err != nil {
panic(err)
}
return v
}
const (
Uint64Overflow uint64 = 9223372036854775808
Uint64Max uint64 = 18446744073709551615
Uint64Test uint64 = 42
)
var tests = []struct {
name string
maxBytes int
input telegraf.Metric
output []byte
err error
name string
maxBytes int
typeSupport FieldTypeSupport
input telegraf.Metric
output []byte
err error
}{
{
name: "minimal",
@@ -143,40 +136,56 @@ var tests = []struct {
"cpu",
map[string]string{},
map[string]interface{}{
"value": Uint64Test,
"value": uint64(42),
},
time.Unix(0, 0),
),
),
output: []byte("cpu value=42u 0\n"),
output: []byte("cpu value=42u 0\n"),
typeSupport: UintSupport,
},
{
name: "uint field int64 overflow",
name: "uint field max value",
input: MustMetric(
metric.New(
"cpu",
map[string]string{},
map[string]interface{}{
"value": Uint64Overflow,
"value": uint64(18446744073709551615),
},
time.Unix(0, 0),
),
),
output: []byte("cpu value=9223372036854775808u 0\n"),
output: []byte("cpu value=18446744073709551615u 0\n"),
typeSupport: UintSupport,
},
{
name: "uint field uint64 max",
name: "uint field no uint support",
input: MustMetric(
metric.New(
"cpu",
map[string]string{},
map[string]interface{}{
"value": Uint64Max,
"value": uint64(42),
},
time.Unix(0, 0),
),
),
output: []byte("cpu value=18446744073709551615u 0\n"),
output: []byte("cpu value=42i 0\n"),
},
{
name: "uint field no uint support overflow",
input: MustMetric(
metric.New(
"cpu",
map[string]string{},
map[string]interface{}{
"value": uint64(18446744073709551615),
},
time.Unix(0, 0),
),
),
output: []byte("cpu value=9223372036854775807i 0\n"),
},
{
name: "bool field",
@@ -358,6 +367,7 @@ func TestSerializer(t *testing.T) {
serializer := NewSerializer()
serializer.SetMaxLineBytes(tt.maxBytes)
serializer.SetFieldSortOrder(SortFields)
serializer.SetFieldTypeSupport(tt.typeSupport)
output, err := serializer.Serialize(tt.input)
require.Equal(t, tt.err, err)
require.Equal(t, string(tt.output), string(output))
@@ -370,6 +380,7 @@ func BenchmarkSerializer(b *testing.B) {
b.Run(tt.name, func(b *testing.B) {
serializer := NewSerializer()
serializer.SetMaxLineBytes(tt.maxBytes)
serializer.SetFieldTypeSupport(tt.typeSupport)
for n := 0; n < b.N; n++ {
output, err := serializer.Serialize(tt.input)
_ = err