forked from influxdata/telegraf
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmetric.go
104 lines (84 loc) · 2.72 KB
/
metric.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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 (t *MessagePackTime) Len() int {
sec := t.time.Unix()
nsec := t.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 (t *MessagePackTime) MarshalBinaryTo(buf []byte) error {
len := t.Len()
if len == 4 {
sec := t.time.Unix()
binary.BigEndian.PutUint32(buf, uint32(sec))
} else if len == 8 {
sec := t.time.Unix()
nsec := t.time.Nanosecond()
data := uint64(nsec)<<34 | (uint64(sec) & 0x03_ffff_ffff)
binary.BigEndian.PutUint64(buf, data)
} else if len == 12 {
sec := t.time.Unix()
nsec := t.time.Nanosecond()
binary.BigEndian.PutUint32(buf, uint32(nsec))
binary.BigEndian.PutUint64(buf[4:], uint64(sec))
}
return nil
}
// UnmarshalBinary implements the Extension interface
func (t *MessagePackTime) UnmarshalBinary(buf []byte) error {
len := len(buf)
if len == 4 {
sec := binary.BigEndian.Uint32(buf)
t.time = time.Unix(int64(sec), 0)
} else if len == 8 {
data := binary.BigEndian.Uint64(buf)
nsec := (data & 0xfffffffc_00000000) >> 34
sec := (data & 0x00000003_ffffffff)
t.time = time.Unix(int64(sec), int64(nsec))
} else if len == 12 {
nsec := binary.BigEndian.Uint32(buf)
sec := binary.BigEndian.Uint64(buf[4:])
t.time = time.Unix(int64(sec), int64(nsec))
}
return nil
}