Add line protocol uint64 support (#3946)
This commit is contained in:
@@ -63,6 +63,12 @@ func parseIntBytes(b []byte, base int, bitSize int) (i int64, err error) {
|
||||
return strconv.ParseInt(s, base, bitSize)
|
||||
}
|
||||
|
||||
// parseUintBytes is a zero-alloc wrapper around strconv.ParseUint.
|
||||
func parseUintBytes(b []byte, base int, bitSize int) (i uint64, err error) {
|
||||
s := unsafeBytesToString(b)
|
||||
return strconv.ParseUint(s, base, bitSize)
|
||||
}
|
||||
|
||||
// parseFloatBytes is a zero-alloc wrapper around strconv.ParseFloat.
|
||||
func parseFloatBytes(b []byte, bitSize int) (float64, error) {
|
||||
s := unsafeBytesToString(b)
|
||||
|
||||
@@ -54,6 +54,16 @@ func (h *MetricHandler) AddInt(key []byte, value []byte) {
|
||||
h.builder.AddField(fk, fv)
|
||||
}
|
||||
|
||||
func (h *MetricHandler) AddUint(key []byte, value []byte) {
|
||||
fk := unescape(key)
|
||||
fv, err := parseUintBytes(bytes.TrimSuffix(value, []byte("u")), 10, 64)
|
||||
if err != nil {
|
||||
log.Errorf("E! Received unparseable uint value: %q", value)
|
||||
return
|
||||
}
|
||||
h.builder.AddField(fk, fv)
|
||||
}
|
||||
|
||||
func (h *MetricHandler) AddFloat(key []byte, value []byte) {
|
||||
fk := unescape(key)
|
||||
fv, err := parseFloatBytes(value, 64)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -89,6 +89,10 @@ action integer {
|
||||
m.handler.AddInt(key, m.text())
|
||||
}
|
||||
|
||||
action unsigned {
|
||||
m.handler.AddUint(key, m.text())
|
||||
}
|
||||
|
||||
action float {
|
||||
m.handler.AddFloat(key, m.text())
|
||||
}
|
||||
@@ -114,6 +118,9 @@ non_zero_digit =
|
||||
integer =
|
||||
'-'? ( digit | ( non_zero_digit digit* ) );
|
||||
|
||||
unsigned =
|
||||
( digit | ( non_zero_digit digit* ) );
|
||||
|
||||
number =
|
||||
( integer ( '.' digit* )? ) | ( '.' digit* );
|
||||
|
||||
@@ -135,6 +142,9 @@ fieldfloat =
|
||||
fieldinteger =
|
||||
(integer 'i') >begin %integer;
|
||||
|
||||
fieldunsigned =
|
||||
(unsigned 'u') >begin %unsigned;
|
||||
|
||||
false =
|
||||
"false" | "FALSE" | "False" | "F" | "f";
|
||||
|
||||
@@ -153,7 +163,7 @@ fieldstring =
|
||||
fieldstringquoted =
|
||||
'"' fieldstring '"';
|
||||
|
||||
fieldvalue = fieldinteger | fieldfloat | fieldstringquoted | fieldbool;
|
||||
fieldvalue = fieldinteger | fieldunsigned | fieldfloat | fieldstringquoted | fieldbool;
|
||||
|
||||
field =
|
||||
fieldkey '=' fieldvalue;
|
||||
|
||||
@@ -43,6 +43,18 @@ func (h *TestingHandler) AddInt(key []byte, value []byte) {
|
||||
h.results = append(h.results, fieldkey, fieldvalue)
|
||||
}
|
||||
|
||||
func (h *TestingHandler) AddUint(key []byte, value []byte) {
|
||||
fieldkey := Result{
|
||||
Name: FieldKey,
|
||||
Value: key,
|
||||
}
|
||||
fieldvalue := Result{
|
||||
Name: FieldUint,
|
||||
Value: value,
|
||||
}
|
||||
h.results = append(h.results, fieldkey, fieldvalue)
|
||||
}
|
||||
|
||||
func (h *TestingHandler) AddFloat(key []byte, value []byte) {
|
||||
fieldkey := Result{
|
||||
Name: FieldKey,
|
||||
@@ -113,6 +125,9 @@ func (h *BenchmarkingHandler) AddTag(key []byte, value []byte) {
|
||||
func (h *BenchmarkingHandler) AddInt(key []byte, value []byte) {
|
||||
}
|
||||
|
||||
func (h *BenchmarkingHandler) AddUint(key []byte, value []byte) {
|
||||
}
|
||||
|
||||
func (h *BenchmarkingHandler) AddFloat(key []byte, value []byte) {
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ type Handler interface {
|
||||
SetMeasurement(name []byte)
|
||||
AddTag(key []byte, value []byte)
|
||||
AddInt(key []byte, value []byte)
|
||||
AddUint(key []byte, value []byte)
|
||||
AddFloat(key []byte, value []byte)
|
||||
AddString(key []byte, value []byte)
|
||||
AddBool(key []byte, value []byte)
|
||||
|
||||
@@ -16,6 +16,12 @@ func Metric(v telegraf.Metric, err error) telegraf.Metric {
|
||||
return v
|
||||
}
|
||||
|
||||
const (
|
||||
Uint64Overflow uint64 = 9223372036854775808
|
||||
Uint64Max uint64 = 18446744073709551615
|
||||
Uint64Test uint64 = 42
|
||||
)
|
||||
|
||||
var DefaultTime = func() time.Time {
|
||||
return time.Unix(42, 0)
|
||||
}
|
||||
@@ -256,6 +262,57 @@ var ptests = []struct {
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "field uint",
|
||||
input: []byte("cpu value=42u"),
|
||||
metrics: []telegraf.Metric{
|
||||
Metric(
|
||||
metric.New(
|
||||
"cpu",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"value": Uint64Test,
|
||||
},
|
||||
time.Unix(42, 0),
|
||||
),
|
||||
),
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "field uint int overflow",
|
||||
input: []byte("cpu value=9223372036854775808u"),
|
||||
metrics: []telegraf.Metric{
|
||||
Metric(
|
||||
metric.New(
|
||||
"cpu",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"value": Uint64Overflow,
|
||||
},
|
||||
time.Unix(42, 0),
|
||||
),
|
||||
),
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "field uint maximum",
|
||||
input: []byte("cpu value=18446744073709551615u"),
|
||||
metrics: []telegraf.Metric{
|
||||
Metric(
|
||||
metric.New(
|
||||
"cpu",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"value": Uint64Max,
|
||||
},
|
||||
time.Unix(42, 0),
|
||||
),
|
||||
),
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "field boolean",
|
||||
input: []byte("cpu value=true"),
|
||||
|
||||
@@ -237,6 +237,8 @@ func (s *Serializer) writeMetric(w io.Writer, m telegraf.Metric) error {
|
||||
|
||||
func appendFieldValue(buf []byte, value interface{}) ([]byte, error) {
|
||||
switch v := value.(type) {
|
||||
case uint64:
|
||||
return appendUintField(buf, v), nil
|
||||
case int64:
|
||||
return appendIntField(buf, v), nil
|
||||
case float64:
|
||||
@@ -257,6 +259,10 @@ func appendFieldValue(buf []byte, value interface{}) ([]byte, error) {
|
||||
return buf, ErrInvalidFieldType
|
||||
}
|
||||
|
||||
func appendUintField(buf []byte, value uint64) []byte {
|
||||
return append(strconv.AppendUint(buf, value, 10), 'u')
|
||||
}
|
||||
|
||||
func appendIntField(buf []byte, value int64) []byte {
|
||||
return append(strconv.AppendInt(buf, value, 10), 'i')
|
||||
}
|
||||
|
||||
@@ -11,12 +11,20 @@ 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
|
||||
@@ -128,6 +136,48 @@ var tests = []struct {
|
||||
),
|
||||
output: []byte("cpu value=42i 0\n"),
|
||||
},
|
||||
{
|
||||
name: "uint field",
|
||||
input: MustMetric(
|
||||
metric.New(
|
||||
"cpu",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"value": Uint64Test,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
),
|
||||
output: []byte("cpu value=42u 0\n"),
|
||||
},
|
||||
{
|
||||
name: "uint field int64 overflow",
|
||||
input: MustMetric(
|
||||
metric.New(
|
||||
"cpu",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"value": Uint64Overflow,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
),
|
||||
output: []byte("cpu value=9223372036854775808u 0\n"),
|
||||
},
|
||||
{
|
||||
name: "uint field uint64 max",
|
||||
input: MustMetric(
|
||||
metric.New(
|
||||
"cpu",
|
||||
map[string]string{},
|
||||
map[string]interface{}{
|
||||
"value": Uint64Max,
|
||||
},
|
||||
time.Unix(0, 0),
|
||||
),
|
||||
),
|
||||
output: []byte("cpu value=18446744073709551615u 0\n"),
|
||||
},
|
||||
{
|
||||
name: "bool field",
|
||||
input: MustMetric(
|
||||
|
||||
Reference in New Issue
Block a user