This repository has been archived by the owner on Aug 18, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 31
/
signalfx.go
168 lines (145 loc) · 4.74 KB
/
signalfx.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package signalfx
import (
"fmt"
"time"
"errors"
"github.com/signalfx/com_signalfx_metrics_protobuf"
"github.com/signalfx/gateway/protocol/signalfx/format"
"github.com/signalfx/golib/datapoint"
"github.com/signalfx/golib/event"
)
// ValueToSend is an alias
type ValueToSend signalfxformat.ValueToSend
// NewDatumValue creates new datapoint value referenced from a value of the datum protobuf
func NewDatumValue(val *com_signalfx_metrics_protobuf.Datum) datapoint.Value {
if val.DoubleValue != nil {
return datapoint.NewFloatValue(val.GetDoubleValue())
}
if val.IntValue != nil {
return datapoint.NewIntValue(val.GetIntValue())
}
return datapoint.NewStringValue(val.GetStrValue())
}
// ValueToValue converts the v2 JSON value to a core api Value
func ValueToValue(v ValueToSend) (datapoint.Value, error) {
f, ok := v.(float64)
if ok {
if f == float64(int64(f)) {
return datapoint.NewIntValue(int64(f)), nil
}
return datapoint.NewFloatValue(f), nil
}
i, ok := v.(int64)
if ok {
return datapoint.NewIntValue(i), nil
}
i2, ok := v.(int)
if ok {
return datapoint.NewIntValue(int64(i2)), nil
}
s, ok := v.(string)
if ok {
return datapoint.NewStringValue(s), nil
}
return nil, fmt.Errorf("unable to convert value: %s", v)
}
// MetricCreationStruct is the API format for /v1/metric POST
type MetricCreationStruct struct {
MetricName string `json:"sf_metric"`
MetricType string `json:"sf_metricType"`
}
// MetricCreationResponse is the API response for /v1/metric POST
type MetricCreationResponse struct {
Code int `json:"code,omitempty"`
Error bool `json:"error,omitempty"`
Message string `json:"message,omitempty"`
}
var fromMTMap = map[com_signalfx_metrics_protobuf.MetricType]datapoint.MetricType{
com_signalfx_metrics_protobuf.MetricType_CUMULATIVE_COUNTER: datapoint.Counter,
com_signalfx_metrics_protobuf.MetricType_GAUGE: datapoint.Gauge,
com_signalfx_metrics_protobuf.MetricType_COUNTER: datapoint.Count,
}
func fromMT(mt com_signalfx_metrics_protobuf.MetricType) datapoint.MetricType {
ret, exists := fromMTMap[mt]
if exists {
return ret
}
panic(fmt.Sprintf("Unknown metric type: %v\n", mt))
}
func fromTs(ts int64) time.Time {
if ts > 0 {
return time.Unix(0, ts*time.Millisecond.Nanoseconds())
}
return time.Now().Add(-time.Duration(time.Millisecond.Nanoseconds() * ts))
}
var errDatapointValueNotSet = errors.New("datapoint value not set")
// NewProtobufDataPointWithType creates a new datapoint from SignalFx's protobuf definition (backwards compatable with old API)
func NewProtobufDataPointWithType(dp *com_signalfx_metrics_protobuf.DataPoint, mType com_signalfx_metrics_protobuf.MetricType) (*datapoint.Datapoint, error) {
var mt com_signalfx_metrics_protobuf.MetricType
if dp.GetValue() == nil {
return nil, errDatapointValueNotSet
}
if dp.MetricType != nil {
mt = dp.GetMetricType()
} else {
mt = mType
}
dims := make(map[string]string, len(dp.GetDimensions())+1)
if dp.GetSource() != "" {
dims["sf_source"] = dp.GetSource()
}
dpdims := dp.GetDimensions()
for _, dpdim := range dpdims {
dims[dpdim.GetKey()] = dpdim.GetValue()
}
dpToRet := datapoint.New(dp.GetMetric(), dims, NewDatumValue(dp.GetValue()), fromMT(mt), fromTs(dp.GetTimestamp()))
return dpToRet, nil
}
// PropertyAsRawType converts a protobuf property to a native Go type
func PropertyAsRawType(p *com_signalfx_metrics_protobuf.PropertyValue) interface{} {
if p == nil {
return nil
}
if p.BoolValue != nil {
return *p.BoolValue
}
if p.DoubleValue != nil {
return *p.DoubleValue
}
if p.StrValue != nil {
return *p.StrValue
}
if p.IntValue != nil {
return *p.IntValue
}
return nil
}
var errPropertyValueNotSet = errors.New("property value not set")
// NewProtobufEvent creates a new event from SignalFx's protobuf definition
func NewProtobufEvent(e *com_signalfx_metrics_protobuf.Event) (*event.Event, error) {
dims := make(map[string]string, len(e.GetDimensions())+1)
edims := e.GetDimensions()
for _, dpdim := range edims {
dims[dpdim.GetKey()] = dpdim.GetValue()
}
// sure wish protobuf has something eqiv of interface{} instead of only union structs...
// <sigh>
props := make(map[string]interface{}, len(e.GetDimensions())+1)
for _, dpdim := range e.GetProperties() {
pval := dpdim.GetValue()
pkey := dpdim.GetKey()
if pval.StrValue != nil {
props[pkey] = pval.GetStrValue()
} else if pval.BoolValue != nil {
props[pkey] = pval.GetBoolValue()
} else if pval.DoubleValue != nil {
props[pkey] = pval.GetDoubleValue()
} else if pval.IntValue != nil {
props[pkey] = pval.GetIntValue()
} else {
return nil, errPropertyValueNotSet
}
}
cat := event.ToProtoEC(e.GetCategory())
return event.NewWithProperties(e.GetEventType(), cat, dims, props, fromTs(e.GetTimestamp())), nil
}