* Source improvement for librato output Build the source from the list of tag instead of a configuration specified single tag Graphite Serializer: * make buildTags public * make sure not to use empty tags Librato output: * Improve Error handling for librato API base on error or debug flag * Send Metric per Batch (max 300) * use Graphite BuildTag function to generate source The change is made that it should be retro compatible Metric sample: server=127.0.0.1 port=80 state=leader env=test measurement.metric_name value service_n.metric_x Metric before with source tags set as "server": source=127.0.0.1 test.80.127_0_0_1.leader.measurement.metric_name test.80.127_0_0_1.leader.service_n.metric_x Metric now: source=test.80.127.0.0.1.leader measurement.metric_name service_n.metric_x As you can see the source in the "new" version is much more precise That way when filter (only from source) you can filter by env or any other tags * Using template to specify which tagsusing for source, default concat all tags * revert change in graphite serializer * better documentation, change default for template * fmt * test passing with new host as default tags * use host tag in api integration test * Limit 80 char per line, change resolution to be a int in the sample * fmt * remove resolution, doc for template * fmt
283 lines
5.8 KiB
Go
283 lines
5.8 KiB
Go
package librato
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/influxdata/telegraf"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var (
|
|
fakeURL = "http://test.librato.com"
|
|
fakeUser = "telegraf@influxdb.com"
|
|
fakeToken = "123456"
|
|
)
|
|
|
|
func fakeLibrato() *Librato {
|
|
l := NewLibrato(fakeURL)
|
|
l.APIUser = fakeUser
|
|
l.APIToken = fakeToken
|
|
return l
|
|
}
|
|
|
|
func TestUriOverride(t *testing.T) {
|
|
ts := httptest.NewServer(
|
|
http.HandlerFunc(
|
|
func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
defer ts.Close()
|
|
|
|
l := NewLibrato(ts.URL)
|
|
l.APIUser = "telegraf@influxdb.com"
|
|
l.APIToken = "123456"
|
|
err := l.Connect()
|
|
require.NoError(t, err)
|
|
err = l.Write([]telegraf.Metric{newHostMetric(int32(0), "name", "host")})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestBadStatusCode(t *testing.T) {
|
|
ts := httptest.NewServer(
|
|
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusServiceUnavailable)
|
|
}))
|
|
defer ts.Close()
|
|
|
|
l := NewLibrato(ts.URL)
|
|
l.APIUser = "telegraf@influxdb.com"
|
|
l.APIToken = "123456"
|
|
err := l.Connect()
|
|
require.NoError(t, err)
|
|
err = l.Write([]telegraf.Metric{newHostMetric(int32(0), "name", "host")})
|
|
if err == nil {
|
|
t.Errorf("error expected but none returned")
|
|
} else {
|
|
require.EqualError(
|
|
t,
|
|
fmt.Errorf("received bad status code, 503\n "), err.Error())
|
|
}
|
|
}
|
|
|
|
func TestBuildGauge(t *testing.T) {
|
|
|
|
mtime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC).Unix()
|
|
var gaugeTests = []struct {
|
|
ptIn telegraf.Metric
|
|
outGauge *Gauge
|
|
err error
|
|
}{
|
|
{
|
|
newHostMetric(0.0, "test1", "host1"),
|
|
&Gauge{
|
|
Name: "test1",
|
|
MeasureTime: mtime,
|
|
Value: 0.0,
|
|
Source: "host1",
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
newHostMetric(1.0, "test2", "host2"),
|
|
&Gauge{
|
|
Name: "test2",
|
|
MeasureTime: mtime,
|
|
Value: 1.0,
|
|
Source: "host2",
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
newHostMetric(10, "test3", "host3"),
|
|
&Gauge{
|
|
Name: "test3",
|
|
MeasureTime: mtime,
|
|
Value: 10.0,
|
|
Source: "host3",
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
newHostMetric(int32(112345), "test4", "host4"),
|
|
&Gauge{
|
|
Name: "test4",
|
|
MeasureTime: mtime,
|
|
Value: 112345.0,
|
|
Source: "host4",
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
newHostMetric(int64(112345), "test5", "host5"),
|
|
&Gauge{
|
|
Name: "test5",
|
|
MeasureTime: mtime,
|
|
Value: 112345.0,
|
|
Source: "host5",
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
newHostMetric(float32(11234.5), "test6", "host6"),
|
|
&Gauge{
|
|
Name: "test6",
|
|
MeasureTime: mtime,
|
|
Value: 11234.5,
|
|
Source: "host6",
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
newHostMetric("11234.5", "test7", "host7"),
|
|
nil,
|
|
nil,
|
|
},
|
|
}
|
|
|
|
l := NewLibrato(fakeURL)
|
|
for _, gt := range gaugeTests {
|
|
gauges, err := l.buildGauges(gt.ptIn)
|
|
if err != nil && gt.err == nil {
|
|
t.Errorf("%s: unexpected error, %+v\n", gt.ptIn.Name(), err)
|
|
}
|
|
if gt.err != nil && err == nil {
|
|
t.Errorf("%s: expected an error (%s) but none returned",
|
|
gt.ptIn.Name(), gt.err.Error())
|
|
}
|
|
if len(gauges) != 0 && gt.outGauge == nil {
|
|
t.Errorf("%s: unexpected gauge, %+v\n", gt.ptIn.Name(), gt.outGauge)
|
|
}
|
|
if len(gauges) == 0 {
|
|
continue
|
|
}
|
|
if gt.err == nil && !reflect.DeepEqual(gauges[0], gt.outGauge) {
|
|
t.Errorf("%s: \nexpected %+v\ngot %+v\n",
|
|
gt.ptIn.Name(), gt.outGauge, gauges[0])
|
|
}
|
|
}
|
|
}
|
|
|
|
func newHostMetric(value interface{}, name, host string) (metric telegraf.Metric) {
|
|
metric, _ = telegraf.NewMetric(
|
|
name,
|
|
map[string]string{"host": host},
|
|
map[string]interface{}{"value": value},
|
|
time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC),
|
|
)
|
|
return
|
|
}
|
|
|
|
func TestBuildGaugeWithSource(t *testing.T) {
|
|
mtime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
|
|
pt1, _ := telegraf.NewMetric(
|
|
"test1",
|
|
map[string]string{"hostname": "192.168.0.1", "tag1": "value1"},
|
|
map[string]interface{}{"value": 0.0},
|
|
mtime,
|
|
)
|
|
pt2, _ := telegraf.NewMetric(
|
|
"test2",
|
|
map[string]string{"hostnam": "192.168.0.1", "tag1": "value1"},
|
|
map[string]interface{}{"value": 1.0},
|
|
mtime,
|
|
)
|
|
pt3, _ := telegraf.NewMetric(
|
|
"test3",
|
|
map[string]string{
|
|
"hostname": "192.168.0.1",
|
|
"tag2": "value2",
|
|
"tag1": "value1"},
|
|
map[string]interface{}{"value": 1.0},
|
|
mtime,
|
|
)
|
|
pt4, _ := telegraf.NewMetric(
|
|
"test4",
|
|
map[string]string{
|
|
"hostname": "192.168.0.1",
|
|
"tag2": "value2",
|
|
"tag1": "value1"},
|
|
map[string]interface{}{"value": 1.0},
|
|
mtime,
|
|
)
|
|
var gaugeTests = []struct {
|
|
ptIn telegraf.Metric
|
|
template string
|
|
outGauge *Gauge
|
|
err error
|
|
}{
|
|
|
|
{
|
|
pt1,
|
|
"hostname",
|
|
&Gauge{
|
|
Name: "test1",
|
|
MeasureTime: mtime.Unix(),
|
|
Value: 0.0,
|
|
Source: "192_168_0_1",
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
pt2,
|
|
"hostname",
|
|
&Gauge{
|
|
Name: "test2",
|
|
MeasureTime: mtime.Unix(),
|
|
Value: 1.0,
|
|
},
|
|
fmt.Errorf("undeterminable Source type from Field, hostname"),
|
|
},
|
|
{
|
|
pt3,
|
|
"tags",
|
|
&Gauge{
|
|
Name: "test3",
|
|
MeasureTime: mtime.Unix(),
|
|
Value: 1.0,
|
|
Source: "192_168_0_1.value1.value2",
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
pt4,
|
|
"hostname.tag2",
|
|
&Gauge{
|
|
Name: "test4",
|
|
MeasureTime: mtime.Unix(),
|
|
Value: 1.0,
|
|
Source: "192_168_0_1.value2",
|
|
},
|
|
nil,
|
|
},
|
|
}
|
|
|
|
l := NewLibrato(fakeURL)
|
|
for _, gt := range gaugeTests {
|
|
l.Template = gt.template
|
|
gauges, err := l.buildGauges(gt.ptIn)
|
|
if err != nil && gt.err == nil {
|
|
t.Errorf("%s: unexpected error, %+v\n", gt.ptIn.Name(), err)
|
|
}
|
|
if gt.err != nil && err == nil {
|
|
t.Errorf(
|
|
"%s: expected an error (%s) but none returned",
|
|
gt.ptIn.Name(),
|
|
gt.err.Error())
|
|
}
|
|
if len(gauges) == 0 {
|
|
continue
|
|
}
|
|
if gt.err == nil && !reflect.DeepEqual(gauges[0], gt.outGauge) {
|
|
t.Errorf(
|
|
"%s: \nexpected %+v\ngot %+v\n",
|
|
gt.ptIn.Name(),
|
|
gt.outGauge, gauges[0])
|
|
}
|
|
}
|
|
}
|