Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
43
plugins/serializers/msgpack/README.md
Normal file
43
plugins/serializers/msgpack/README.md
Normal file
|
@ -0,0 +1,43 @@
|
|||
# MessagePack
|
||||
|
||||
[MessagePack](https://msgpack.org) is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON.
|
||||
|
||||
## Format Definitions
|
||||
|
||||
Output of this format is MessagePack binary representation of metrics that have identical structure of the below JSON.
|
||||
|
||||
```json
|
||||
{
|
||||
"name":"cpu",
|
||||
"time": <TIMESTAMP>, // https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type
|
||||
"tags":{
|
||||
"tag_1":"host01",
|
||||
...
|
||||
},
|
||||
"fields":{
|
||||
"field_1":30,
|
||||
"field_2":true,
|
||||
"field_3":"field_value"
|
||||
"field_4":30.1
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
MessagePack has it's own timestamp representation. You can find additional information from [MessagePack specification](https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type).
|
||||
|
||||
## MessagePack Configuration
|
||||
|
||||
There are no additional configuration options for MessagePack format.
|
||||
|
||||
```toml
|
||||
[[outputs.file]]
|
||||
## Files to write to, "stdout" is a specially handled file.
|
||||
files = ["stdout", "/tmp/metrics.out"]
|
||||
|
||||
## Data format to output.
|
||||
## Each data format has its own unique set of configuration options, read
|
||||
## more about them here:
|
||||
## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_OUTPUT.md
|
||||
data_format = "msgpack"
|
||||
```
|
104
plugins/serializers/msgpack/metric.go
Normal file
104
plugins/serializers/msgpack/metric.go
Normal file
|
@ -0,0 +1,104 @@
|
|||
package msgpack
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
//go:generate msgp
|
||||
|
||||
// Metric is structure to define MessagePack message format
|
||||
// will be used by msgp code generator
|
||||
type Metric struct {
|
||||
Name string `msg:"name"`
|
||||
Time MessagePackTime `msg:"time,extension"`
|
||||
Tags map[string]string `msg:"tags"`
|
||||
Fields map[string]interface{} `msg:"fields"`
|
||||
}
|
||||
|
||||
// MessagePackTime implements the official timestamp extension type
|
||||
// https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type
|
||||
//
|
||||
// tinylib/msgp has been using their own custom extension type and the official extension
|
||||
// is not available. (https://github.com/tinylib/msgp/issues/214)
|
||||
type MessagePackTime struct {
|
||||
time time.Time
|
||||
}
|
||||
|
||||
func init() {
|
||||
msgp.RegisterExtension(-1, func() msgp.Extension { return new(MessagePackTime) })
|
||||
}
|
||||
|
||||
// ExtensionType implements the Extension interface
|
||||
func (*MessagePackTime) ExtensionType() int8 {
|
||||
return -1
|
||||
}
|
||||
|
||||
// Len implements the Extension interface
|
||||
// The timestamp extension uses variable length encoding depending the input
|
||||
//
|
||||
// 32bits: [1970-01-01 00:00:00 UTC, 2106-02-07 06:28:16 UTC) range. If the nanoseconds part is 0
|
||||
// 64bits: [1970-01-01 00:00:00.000000000 UTC, 2514-05-30 01:53:04.000000000 UTC) range.
|
||||
// 96bits: [-584554047284-02-23 16:59:44 UTC, 584554051223-11-09 07:00:16.000000000 UTC) range.
|
||||
func (z *MessagePackTime) Len() int {
|
||||
sec := z.time.Unix()
|
||||
nsec := z.time.Nanosecond()
|
||||
|
||||
if sec < 0 || sec >= (1<<34) { // 96 bits encoding
|
||||
return 12
|
||||
}
|
||||
if sec >= (1<<32) || nsec != 0 {
|
||||
return 8
|
||||
}
|
||||
return 4
|
||||
}
|
||||
|
||||
// MarshalBinaryTo implements the Extension interface
|
||||
func (z *MessagePackTime) MarshalBinaryTo(buf []byte) error {
|
||||
length := z.Len()
|
||||
|
||||
if length == 4 {
|
||||
sec := z.time.Unix()
|
||||
binary.BigEndian.PutUint32(buf, uint32(sec))
|
||||
} else if length == 8 {
|
||||
sec := z.time.Unix()
|
||||
nsec := z.time.Nanosecond()
|
||||
|
||||
data := uint64(nsec)<<34 | (uint64(sec) & 0x03_ffff_ffff)
|
||||
binary.BigEndian.PutUint64(buf, data)
|
||||
} else if length == 12 {
|
||||
sec := z.time.Unix()
|
||||
nsec := z.time.Nanosecond()
|
||||
|
||||
binary.BigEndian.PutUint32(buf, uint32(nsec))
|
||||
binary.BigEndian.PutUint64(buf[4:], uint64(sec))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements the Extension interface
|
||||
func (z *MessagePackTime) UnmarshalBinary(buf []byte) error {
|
||||
length := len(buf)
|
||||
|
||||
if length == 4 {
|
||||
sec := binary.BigEndian.Uint32(buf)
|
||||
z.time = time.Unix(int64(sec), 0)
|
||||
} else if length == 8 {
|
||||
data := binary.BigEndian.Uint64(buf)
|
||||
|
||||
nsec := (data & 0xfffffffc_00000000) >> 34
|
||||
sec := data & 0x00000003_ffffffff
|
||||
|
||||
z.time = time.Unix(int64(sec), int64(nsec))
|
||||
} else if length == 12 {
|
||||
nsec := binary.BigEndian.Uint32(buf)
|
||||
sec := binary.BigEndian.Uint64(buf[4:])
|
||||
|
||||
z.time = time.Unix(int64(sec), int64(nsec))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
417
plugins/serializers/msgpack/metric_gen.go
Normal file
417
plugins/serializers/msgpack/metric_gen.go
Normal file
|
@ -0,0 +1,417 @@
|
|||
package msgpack
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *MessagePackTime) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z MessagePackTime) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 0
|
||||
err = en.Append(0x80)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z MessagePackTime) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 0
|
||||
o = append(o, 0x80)
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *MessagePackTime) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z MessagePackTime) Msgsize() (s int) {
|
||||
s = 1
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeMsg implements msgp.Decodable
|
||||
func (z *Metric) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, err = dc.ReadMapKeyPtr()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "name":
|
||||
z.Name, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Name")
|
||||
return
|
||||
}
|
||||
case "time":
|
||||
err = dc.ReadExtension(&z.Time)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Time")
|
||||
return
|
||||
}
|
||||
case "tags":
|
||||
var zb0002 uint32
|
||||
zb0002, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Tags")
|
||||
return
|
||||
}
|
||||
if z.Tags == nil {
|
||||
z.Tags = make(map[string]string, zb0002)
|
||||
} else if len(z.Tags) > 0 {
|
||||
for key := range z.Tags {
|
||||
delete(z.Tags, key)
|
||||
}
|
||||
}
|
||||
for zb0002 > 0 {
|
||||
zb0002--
|
||||
var za0001 string
|
||||
var za0002 string
|
||||
za0001, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Tags")
|
||||
return
|
||||
}
|
||||
za0002, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Tags", za0001)
|
||||
return
|
||||
}
|
||||
z.Tags[za0001] = za0002
|
||||
}
|
||||
case "fields":
|
||||
var zb0003 uint32
|
||||
zb0003, err = dc.ReadMapHeader()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Fields")
|
||||
return
|
||||
}
|
||||
if z.Fields == nil {
|
||||
z.Fields = make(map[string]interface{}, zb0003)
|
||||
} else if len(z.Fields) > 0 {
|
||||
for key := range z.Fields {
|
||||
delete(z.Fields, key)
|
||||
}
|
||||
}
|
||||
for zb0003 > 0 {
|
||||
zb0003--
|
||||
var za0003 string
|
||||
var za0004 interface{}
|
||||
za0003, err = dc.ReadString()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Fields")
|
||||
return
|
||||
}
|
||||
za0004, err = dc.ReadIntf()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Fields", za0003)
|
||||
return
|
||||
}
|
||||
z.Fields[za0003] = za0004
|
||||
}
|
||||
default:
|
||||
err = dc.Skip()
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// EncodeMsg implements msgp.Encodable
|
||||
func (z *Metric) EncodeMsg(en *msgp.Writer) (err error) {
|
||||
// map header, size 4
|
||||
// write "name"
|
||||
err = en.Append(0x84, 0xa4, 0x6e, 0x61, 0x6d, 0x65)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteString(z.Name)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Name")
|
||||
return
|
||||
}
|
||||
// write "time"
|
||||
err = en.Append(0xa4, 0x74, 0x69, 0x6d, 0x65)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteExtension(&z.Time)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Time")
|
||||
return
|
||||
}
|
||||
// write "tags"
|
||||
err = en.Append(0xa4, 0x74, 0x61, 0x67, 0x73)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteMapHeader(uint32(len(z.Tags)))
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Tags")
|
||||
return
|
||||
}
|
||||
for za0001, za0002 := range z.Tags {
|
||||
err = en.WriteString(za0001)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Tags")
|
||||
return
|
||||
}
|
||||
err = en.WriteString(za0002)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Tags", za0001)
|
||||
return
|
||||
}
|
||||
}
|
||||
// write "fields"
|
||||
err = en.Append(0xa6, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = en.WriteMapHeader(uint32(len(z.Fields)))
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Fields")
|
||||
return
|
||||
}
|
||||
for za0003, za0004 := range z.Fields {
|
||||
err = en.WriteString(za0003)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Fields")
|
||||
return
|
||||
}
|
||||
err = en.WriteIntf(za0004)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Fields", za0003)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalMsg implements msgp.Marshaler
|
||||
func (z *Metric) MarshalMsg(b []byte) (o []byte, err error) {
|
||||
o = msgp.Require(b, z.Msgsize())
|
||||
// map header, size 4
|
||||
// string "name"
|
||||
o = append(o, 0x84, 0xa4, 0x6e, 0x61, 0x6d, 0x65)
|
||||
o = msgp.AppendString(o, z.Name)
|
||||
// string "time"
|
||||
o = append(o, 0xa4, 0x74, 0x69, 0x6d, 0x65)
|
||||
o, err = msgp.AppendExtension(o, &z.Time)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Time")
|
||||
return
|
||||
}
|
||||
// string "tags"
|
||||
o = append(o, 0xa4, 0x74, 0x61, 0x67, 0x73)
|
||||
o = msgp.AppendMapHeader(o, uint32(len(z.Tags)))
|
||||
for za0001, za0002 := range z.Tags {
|
||||
o = msgp.AppendString(o, za0001)
|
||||
o = msgp.AppendString(o, za0002)
|
||||
}
|
||||
// string "fields"
|
||||
o = append(o, 0xa6, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73)
|
||||
o = msgp.AppendMapHeader(o, uint32(len(z.Fields)))
|
||||
for za0003, za0004 := range z.Fields {
|
||||
o = msgp.AppendString(o, za0003)
|
||||
o, err = msgp.AppendIntf(o, za0004)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Fields", za0003)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalMsg implements msgp.Unmarshaler
|
||||
func (z *Metric) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||
var field []byte
|
||||
_ = field
|
||||
var zb0001 uint32
|
||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
for zb0001 > 0 {
|
||||
zb0001--
|
||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
switch msgp.UnsafeString(field) {
|
||||
case "name":
|
||||
z.Name, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Name")
|
||||
return
|
||||
}
|
||||
case "time":
|
||||
bts, err = msgp.ReadExtensionBytes(bts, &z.Time)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Time")
|
||||
return
|
||||
}
|
||||
case "tags":
|
||||
var zb0002 uint32
|
||||
zb0002, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Tags")
|
||||
return
|
||||
}
|
||||
if z.Tags == nil {
|
||||
z.Tags = make(map[string]string, zb0002)
|
||||
} else if len(z.Tags) > 0 {
|
||||
for key := range z.Tags {
|
||||
delete(z.Tags, key)
|
||||
}
|
||||
}
|
||||
for zb0002 > 0 {
|
||||
var za0001 string
|
||||
var za0002 string
|
||||
zb0002--
|
||||
za0001, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Tags")
|
||||
return
|
||||
}
|
||||
za0002, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Tags", za0001)
|
||||
return
|
||||
}
|
||||
z.Tags[za0001] = za0002
|
||||
}
|
||||
case "fields":
|
||||
var zb0003 uint32
|
||||
zb0003, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Fields")
|
||||
return
|
||||
}
|
||||
if z.Fields == nil {
|
||||
z.Fields = make(map[string]interface{}, zb0003)
|
||||
} else if len(z.Fields) > 0 {
|
||||
for key := range z.Fields {
|
||||
delete(z.Fields, key)
|
||||
}
|
||||
}
|
||||
for zb0003 > 0 {
|
||||
var za0003 string
|
||||
var za0004 interface{}
|
||||
zb0003--
|
||||
za0003, bts, err = msgp.ReadStringBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Fields")
|
||||
return
|
||||
}
|
||||
za0004, bts, err = msgp.ReadIntfBytes(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err, "Fields", za0003)
|
||||
return
|
||||
}
|
||||
z.Fields[za0003] = za0004
|
||||
}
|
||||
default:
|
||||
bts, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
err = msgp.WrapError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
o = bts
|
||||
return
|
||||
}
|
||||
|
||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||
func (z *Metric) Msgsize() (s int) {
|
||||
s = 1 + 5 + msgp.StringPrefixSize + len(z.Name) + 5 + msgp.ExtensionPrefixSize + z.Time.Len() + 5 + msgp.MapHeaderSize
|
||||
if z.Tags != nil {
|
||||
for za0001, za0002 := range z.Tags {
|
||||
_ = za0002
|
||||
s += msgp.StringPrefixSize + len(za0001) + msgp.StringPrefixSize + len(za0002)
|
||||
}
|
||||
}
|
||||
s += 7 + msgp.MapHeaderSize
|
||||
if z.Fields != nil {
|
||||
for za0003, za0004 := range z.Fields {
|
||||
_ = za0004
|
||||
s += msgp.StringPrefixSize + len(za0003) + msgp.GuessSize(za0004)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
236
plugins/serializers/msgpack/metric_gen_test.go
Normal file
236
plugins/serializers/msgpack/metric_gen_test.go
Normal file
|
@ -0,0 +1,236 @@
|
|||
package msgpack
|
||||
|
||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/tinylib/msgp/msgp"
|
||||
)
|
||||
|
||||
func TestMarshalUnmarshalMessagePackTime(t *testing.T) {
|
||||
v := MessagePackTime{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsgMessagePackTime(b *testing.B) {
|
||||
v := MessagePackTime{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsgMessagePackTime(b *testing.B) {
|
||||
v := MessagePackTime{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalMessagePackTime(b *testing.B) {
|
||||
v := MessagePackTime{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodeMessagePackTime(t *testing.T) {
|
||||
v := MessagePackTime{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
|
||||
m := v.Msgsize()
|
||||
if buf.Len() > m {
|
||||
t.Log("WARNING: TestEncodeDecodeMessagePackTime Msgsize() is inaccurate")
|
||||
}
|
||||
|
||||
vn := MessagePackTime{}
|
||||
err := msgp.Decode(&buf, &vn)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
msgp.Encode(&buf, &v)
|
||||
err = msgp.NewReader(&buf).Skip()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodeMessagePackTime(b *testing.B) {
|
||||
v := MessagePackTime{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
en := msgp.NewWriter(msgp.Nowhere)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.EncodeMsg(en)
|
||||
}
|
||||
en.Flush()
|
||||
}
|
||||
|
||||
func BenchmarkDecodeMessagePackTime(b *testing.B) {
|
||||
v := MessagePackTime{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||
dc := msgp.NewReader(rd)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := v.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalUnmarshalMetric(t *testing.T) {
|
||||
v := Metric{}
|
||||
bts, err := v.MarshalMsg(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
left, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
|
||||
}
|
||||
|
||||
left, err = msgp.Skip(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(left) > 0 {
|
||||
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalMsgMetric(b *testing.B) {
|
||||
v := Metric{}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.MarshalMsg(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMsgMetric(b *testing.B) {
|
||||
v := Metric{}
|
||||
bts := make([]byte, 0, v.Msgsize())
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bts, _ = v.MarshalMsg(bts[0:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnmarshalMetric(b *testing.B) {
|
||||
v := Metric{}
|
||||
bts, _ := v.MarshalMsg(nil)
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(int64(len(bts)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := v.UnmarshalMsg(bts)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodeMetric(t *testing.T) {
|
||||
v := Metric{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
|
||||
m := v.Msgsize()
|
||||
if buf.Len() > m {
|
||||
t.Log("WARNING: TestEncodeDecodeMetric Msgsize() is inaccurate")
|
||||
}
|
||||
|
||||
vn := Metric{}
|
||||
err := msgp.Decode(&buf, &vn)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
msgp.Encode(&buf, &v)
|
||||
err = msgp.NewReader(&buf).Skip()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodeMetric(b *testing.B) {
|
||||
v := Metric{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
en := msgp.NewWriter(msgp.Nowhere)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.EncodeMsg(en)
|
||||
}
|
||||
en.Flush()
|
||||
}
|
||||
|
||||
func BenchmarkDecodeMetric(b *testing.B) {
|
||||
v := Metric{}
|
||||
var buf bytes.Buffer
|
||||
msgp.Encode(&buf, &v)
|
||||
b.SetBytes(int64(buf.Len()))
|
||||
rd := msgp.NewEndlessReader(buf.Bytes(), b)
|
||||
dc := msgp.NewReader(rd)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := v.DecodeMsg(dc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
162
plugins/serializers/msgpack/metric_test.go
Normal file
162
plugins/serializers/msgpack/metric_test.go
Normal file
|
@ -0,0 +1,162 @@
|
|||
package msgpack
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMsgPackTime32(t *testing.T) {
|
||||
// Maximum of 4 bytes encodable time
|
||||
var sec int64 = 0xFFFFFFFF
|
||||
var nsec int64
|
||||
t1 := MessagePackTime{time: time.Unix(sec, nsec)}
|
||||
|
||||
require.Equal(t, 4, t1.Len())
|
||||
|
||||
buf := make([]byte, t1.Len())
|
||||
require.NoError(t, t1.MarshalBinaryTo(buf))
|
||||
|
||||
t2 := new(MessagePackTime)
|
||||
err := t2.UnmarshalBinary(buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, t1.time, t2.time)
|
||||
}
|
||||
|
||||
func TestMsgPackTime64(t *testing.T) {
|
||||
// Maximum of 8 bytes encodable time
|
||||
var sec int64 = 0x3FFFFFFFF
|
||||
var nsec int64 = 999999999
|
||||
t1 := MessagePackTime{time: time.Unix(sec, nsec)}
|
||||
|
||||
require.Equal(t, 8, t1.Len())
|
||||
|
||||
buf := make([]byte, t1.Len())
|
||||
require.NoError(t, t1.MarshalBinaryTo(buf))
|
||||
|
||||
t2 := new(MessagePackTime)
|
||||
err := t2.UnmarshalBinary(buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, t1.time, t2.time)
|
||||
}
|
||||
|
||||
func TestMsgPackTime96(t *testing.T) {
|
||||
// Testing 12 bytes timestamp
|
||||
var sec int64 = 0x400000001
|
||||
var nsec int64 = 111111111
|
||||
t1 := MessagePackTime{time: time.Unix(sec, nsec)}
|
||||
|
||||
require.Equal(t, 12, t1.Len())
|
||||
|
||||
buf := make([]byte, t1.Len())
|
||||
require.NoError(t, t1.MarshalBinaryTo(buf))
|
||||
|
||||
t2 := new(MessagePackTime)
|
||||
err := t2.UnmarshalBinary(buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.True(t, t1.time.Equal(t2.time))
|
||||
|
||||
// Testing the default value: 0001-01-01T00:00:00Z
|
||||
t1 = MessagePackTime{}
|
||||
|
||||
require.Equal(t, 12, t1.Len())
|
||||
require.NoError(t, t1.MarshalBinaryTo(buf))
|
||||
|
||||
t2 = new(MessagePackTime)
|
||||
err = t2.UnmarshalBinary(buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.True(t, t1.time.Equal(t2.time))
|
||||
}
|
||||
|
||||
func TestMsgPackTimeEdgeCases(t *testing.T) {
|
||||
times := make([]time.Time, 0)
|
||||
expected := make([][]byte, 0)
|
||||
|
||||
// Unix epoch. Begin of 4bytes dates
|
||||
// Nanoseconds: 0x00000000, Seconds: 0x0000000000000000
|
||||
ts, err := time.Parse(time.RFC3339, "1970-01-01T00:00:00Z")
|
||||
require.NoError(t, err)
|
||||
bs, err := hex.DecodeString("d6ff00000000")
|
||||
require.NoError(t, err)
|
||||
times = append(times, ts)
|
||||
expected = append(expected, bs)
|
||||
|
||||
// End of 4bytes dates
|
||||
// Nanoseconds: 0x00000000, Seconds: 0x00000000ffffffff
|
||||
ts, err = time.Parse(time.RFC3339, "2106-02-07T06:28:15Z")
|
||||
require.NoError(t, err)
|
||||
bs, err = hex.DecodeString("d6ffffffffff")
|
||||
require.NoError(t, err)
|
||||
times = append(times, ts)
|
||||
expected = append(expected, bs)
|
||||
|
||||
// Begin of 8bytes dates
|
||||
// Nanoseconds: 0x00000000, Seconds: 0x0000000100000000
|
||||
ts, err = time.Parse(time.RFC3339, "2106-02-07T06:28:16Z")
|
||||
require.NoError(t, err)
|
||||
bs, err = hex.DecodeString("d7ff0000000100000000")
|
||||
require.NoError(t, err)
|
||||
times = append(times, ts)
|
||||
expected = append(expected, bs)
|
||||
|
||||
// Just after Unix epoch. Non zero nanoseconds
|
||||
// Nanoseconds: 0x00000001, Seconds: 0x0000000000000000
|
||||
ts, err = time.Parse(time.RFC3339Nano, "1970-01-01T00:00:00.000000001Z")
|
||||
require.NoError(t, err)
|
||||
bs, err = hex.DecodeString("d7ff0000000400000000")
|
||||
require.NoError(t, err)
|
||||
times = append(times, ts)
|
||||
expected = append(expected, bs)
|
||||
|
||||
// End of 8bytes dates
|
||||
// Nanoseconds: 0x00000000, Seconds: 0x00000003ffffffff
|
||||
ts, err = time.Parse(time.RFC3339Nano, "2514-05-30T01:53:03.000000000Z")
|
||||
require.NoError(t, err)
|
||||
bs, err = hex.DecodeString("d7ff00000003ffffffff")
|
||||
require.NoError(t, err)
|
||||
times = append(times, ts)
|
||||
expected = append(expected, bs)
|
||||
|
||||
// Begin of 12bytes date
|
||||
// Nanoseconds: 0x00000000, Seconds: 0x0000000400000000
|
||||
ts, err = time.Parse(time.RFC3339Nano, "2514-05-30T01:53:04.000000000Z")
|
||||
require.NoError(t, err)
|
||||
bs, err = hex.DecodeString("c70cff000000000000000400000000")
|
||||
require.NoError(t, err)
|
||||
times = append(times, ts)
|
||||
expected = append(expected, bs)
|
||||
|
||||
// Zero value, 0001-01-01T00:00:00Z
|
||||
// Nanoseconds: 0x00000000, Seconds: 0xfffffff1886e0900
|
||||
ts = time.Time{}
|
||||
bs, err = hex.DecodeString("c70cff00000000fffffff1886e0900")
|
||||
require.NoError(t, err)
|
||||
times = append(times, ts)
|
||||
expected = append(expected, bs)
|
||||
|
||||
// Max value
|
||||
// Nanoseconds: 0x3b9ac9ff, Seconds: 0x7fffffffffffffff
|
||||
ts = time.Unix(math.MaxInt64, 999_999_999).UTC()
|
||||
bs, err = hex.DecodeString("c70cff3b9ac9ff7fffffffffffffff")
|
||||
require.NoError(t, err)
|
||||
times = append(times, ts)
|
||||
expected = append(expected, bs)
|
||||
|
||||
buf := make([]byte, 0)
|
||||
for i, ts := range times {
|
||||
t1 := MessagePackTime{time: ts}
|
||||
m := Metric{Time: t1}
|
||||
|
||||
buf = buf[:0]
|
||||
buf, err = m.MarshalMsg(buf)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected[i], buf[12:len(buf)-14])
|
||||
}
|
||||
}
|
47
plugins/serializers/msgpack/msgpack.go
Normal file
47
plugins/serializers/msgpack/msgpack.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package msgpack
|
||||
|
||||
import (
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/serializers"
|
||||
)
|
||||
|
||||
// Serializer encodes metrics in MessagePack format
|
||||
type Serializer struct{}
|
||||
|
||||
func marshalMetric(buf []byte, metric telegraf.Metric) ([]byte, error) {
|
||||
return (&Metric{
|
||||
Name: metric.Name(),
|
||||
Time: MessagePackTime{time: metric.Time()},
|
||||
Tags: metric.Tags(),
|
||||
Fields: metric.Fields(),
|
||||
}).MarshalMsg(buf)
|
||||
}
|
||||
|
||||
// Serialize implements serializers.Serializer.Serialize
|
||||
// github.com/influxdata/telegraf/plugins/serializers/Serializer
|
||||
func (*Serializer) Serialize(metric telegraf.Metric) ([]byte, error) {
|
||||
return marshalMetric(nil, metric)
|
||||
}
|
||||
|
||||
// SerializeBatch implements serializers.Serializer.SerializeBatch
|
||||
// github.com/influxdata/telegraf/plugins/serializers/Serializer
|
||||
func (*Serializer) SerializeBatch(metrics []telegraf.Metric) ([]byte, error) {
|
||||
buf := make([]byte, 0)
|
||||
for _, m := range metrics {
|
||||
var err error
|
||||
buf, err = marshalMetric(buf, m)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
serializers.Add("msgpack",
|
||||
func() telegraf.Serializer {
|
||||
return &Serializer{}
|
||||
},
|
||||
)
|
||||
}
|
154
plugins/serializers/msgpack/msgpack_test.go
Normal file
154
plugins/serializers/msgpack/msgpack_test.go
Normal file
|
@ -0,0 +1,154 @@
|
|||
package msgpack
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/metric"
|
||||
"github.com/influxdata/telegraf/plugins/serializers"
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
func toTelegrafMetric(m Metric) telegraf.Metric {
|
||||
tm := metric.New(m.Name, m.Tags, m.Fields, m.Time.time)
|
||||
return tm
|
||||
}
|
||||
|
||||
func TestSerializeMetricInt(t *testing.T) {
|
||||
m := testutil.TestMetric(int64(90))
|
||||
|
||||
s := Serializer{}
|
||||
var buf []byte
|
||||
buf, err := s.Serialize(m)
|
||||
require.NoError(t, err)
|
||||
|
||||
m2 := &Metric{}
|
||||
left, err := m2.UnmarshalMsg(buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Empty(t, left)
|
||||
|
||||
testutil.RequireMetricEqual(t, m, toTelegrafMetric(*m2))
|
||||
}
|
||||
|
||||
func TestSerializeMetricString(t *testing.T) {
|
||||
m := testutil.TestMetric("foobar")
|
||||
|
||||
s := Serializer{}
|
||||
var buf []byte
|
||||
buf, err := s.Serialize(m)
|
||||
require.NoError(t, err)
|
||||
|
||||
m2 := &Metric{}
|
||||
left, err := m2.UnmarshalMsg(buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Empty(t, left)
|
||||
|
||||
testutil.RequireMetricEqual(t, m, toTelegrafMetric(*m2))
|
||||
}
|
||||
|
||||
func TestSerializeMultiFields(t *testing.T) {
|
||||
m := testutil.TestMetric(90)
|
||||
m.AddField("value2", 8559615)
|
||||
|
||||
s := Serializer{}
|
||||
var buf []byte
|
||||
buf, err := s.Serialize(m)
|
||||
require.NoError(t, err)
|
||||
|
||||
m2 := &Metric{}
|
||||
left, err := m2.UnmarshalMsg(buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Empty(t, left)
|
||||
|
||||
testutil.RequireMetricEqual(t, m, toTelegrafMetric(*m2))
|
||||
}
|
||||
|
||||
func TestSerializeMetricWithEscapes(t *testing.T) {
|
||||
m := testutil.TestMetric(90)
|
||||
m.AddField("U,age=Idle", int64(90))
|
||||
m.AddTag("cpu tag", "cpu0")
|
||||
|
||||
s := Serializer{}
|
||||
var buf []byte
|
||||
buf, err := s.Serialize(m)
|
||||
require.NoError(t, err)
|
||||
|
||||
m2 := &Metric{}
|
||||
left, err := m2.UnmarshalMsg(buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Empty(t, left)
|
||||
|
||||
testutil.RequireMetricEqual(t, m, toTelegrafMetric(*m2))
|
||||
}
|
||||
|
||||
func TestSerializeMultipleMetric(t *testing.T) {
|
||||
m := testutil.TestMetric(90)
|
||||
|
||||
s := Serializer{}
|
||||
|
||||
encoded, err := s.Serialize(m)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Multiple metrics in continuous bytes stream
|
||||
var buf []byte
|
||||
buf = append(buf, encoded...)
|
||||
buf = append(buf, encoded...)
|
||||
buf = append(buf, encoded...)
|
||||
buf = append(buf, encoded...)
|
||||
|
||||
left := buf
|
||||
for len(left) > 0 {
|
||||
decodeM := &Metric{}
|
||||
left, err = decodeM.UnmarshalMsg(left)
|
||||
|
||||
require.NoError(t, err)
|
||||
testutil.RequireMetricEqual(t, m, toTelegrafMetric(*decodeM))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSerializeBatch(t *testing.T) {
|
||||
m := testutil.TestMetric(90)
|
||||
|
||||
metrics := []telegraf.Metric{m, m, m, m}
|
||||
|
||||
s := Serializer{}
|
||||
|
||||
buf, err := s.SerializeBatch(metrics)
|
||||
require.NoError(t, err)
|
||||
|
||||
left := buf
|
||||
for len(left) > 0 {
|
||||
decodeM := &Metric{}
|
||||
left, err = decodeM.UnmarshalMsg(left)
|
||||
|
||||
require.NoError(t, err)
|
||||
testutil.RequireMetricEqual(t, m, toTelegrafMetric(*decodeM))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSerialize(b *testing.B) {
|
||||
s := &Serializer{}
|
||||
metrics := serializers.BenchmarkMetrics(b)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := s.Serialize(metrics[i%len(metrics)])
|
||||
require.NoError(b, err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSerializeBatch(b *testing.B) {
|
||||
s := &Serializer{}
|
||||
m := serializers.BenchmarkMetrics(b)
|
||||
metrics := m[:]
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := s.SerializeBatch(metrics)
|
||||
require.NoError(b, err)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue