-
Notifications
You must be signed in to change notification settings - Fork 13
/
circonus.go
113 lines (94 loc) · 2.45 KB
/
circonus.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
105
106
107
108
109
110
111
112
113
package circonus
import (
"bytes"
"fmt"
"math"
"time"
"github.com/circonus-labs/circonus-unified-agent/cua"
"github.com/circonus-labs/go-trapmetrics"
)
type Serializer struct {
TimestampUnits time.Duration
}
func NewSerializer(timestampUnits time.Duration) (*Serializer, error) {
s := &Serializer{
TimestampUnits: truncateDuration(timestampUnits),
}
return s, nil
}
func (s *Serializer) Serialize(metric cua.Metric) ([]byte, error) {
return s.SerializeBatch([]cua.Metric{metric})
}
func (s *Serializer) SerializeBatch(metrics []cua.Metric) ([]byte, error) {
var buf bytes.Buffer
for _, metric := range metrics {
tags := s.convertTags(metric)
for _, field := range metric.FieldList() {
mt := ""
switch fv := field.Value.(type) {
case float64:
// JSON does not support these special values
if math.IsNaN(fv) || math.IsInf(fv, 0) { //nolint:staticcheck
continue
}
mt = "n"
case string:
mt = "s"
default:
mt = "L"
}
_, _ = buf.WriteString(fmt.Sprintf(
"{%q: {\"_value\": %v, \"_type\": %q, \"_ts\": %d}}\n",
field.Key+"|ST["+tags.String()+"]",
field.Value,
mt,
metric.Time().UnixNano()/int64(s.TimestampUnits),
))
}
}
return buf.Bytes(), nil
}
func truncateDuration(units time.Duration) time.Duration {
// Default precision is 1s
if units <= 0 {
return time.Second
}
// Search for the power of ten less than the duration
d := time.Nanosecond
for {
if d*10 > units {
return d
}
d *= 10
}
}
// convertTags reformats cua tags to cgm tags
func (s *Serializer) convertTags(m cua.Metric) trapmetrics.Tags { //nolint:unparam
var ctags trapmetrics.Tags
tags := m.TagList()
if len(tags) == 0 && m.Origin() == "" {
return ctags
}
ctags = make(trapmetrics.Tags, 0)
haveInputMetricGroup := false
if len(tags) > 0 {
for _, t := range tags {
if t.Key == "input_metric_group" {
haveInputMetricGroup = true
}
ctags = append(ctags, trapmetrics.Tag{Category: t.Key, Value: t.Value})
}
}
if m.Origin() != "" {
// from config file `inputs.*`, the part after period
ctags = append(ctags, trapmetrics.Tag{Category: "input_plugin", Value: m.Origin()})
}
if !haveInputMetricGroup {
if m.Name() != "" && m.Name() != m.Origin() {
// what the plugin identifies a subgroup of metrics as, some have multiple names
// e.g. internal, smart, aws, etc.
ctags = append(ctags, trapmetrics.Tag{Category: "input_metric_group", Value: m.Name()})
}
}
return ctags
}