Depenancy upgrades and movign to dep. (#8630)
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
bf24f51c4e
Коммит
6e2cb00008
119
vendor/github.com/armon/go-metrics/circonus/circonus.go
сгенерированный
поставляемый
119
vendor/github.com/armon/go-metrics/circonus/circonus.go
сгенерированный
поставляемый
@@ -1,119 +0,0 @@
|
||||
// Circonus Metrics Sink
|
||||
|
||||
package circonus
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/armon/go-metrics"
|
||||
cgm "github.com/circonus-labs/circonus-gometrics"
|
||||
)
|
||||
|
||||
// CirconusSink provides an interface to forward metrics to Circonus with
|
||||
// automatic check creation and metric management
|
||||
type CirconusSink struct {
|
||||
metrics *cgm.CirconusMetrics
|
||||
}
|
||||
|
||||
// Config options for CirconusSink
|
||||
// See https://github.com/circonus-labs/circonus-gometrics for configuration options
|
||||
type Config cgm.Config
|
||||
|
||||
// NewCirconusSink - create new metric sink for circonus
|
||||
//
|
||||
// one of the following must be supplied:
|
||||
// - API Token - search for an existing check or create a new check
|
||||
// - API Token + Check Id - the check identified by check id will be used
|
||||
// - API Token + Check Submission URL - the check identified by the submission url will be used
|
||||
// - Check Submission URL - the check identified by the submission url will be used
|
||||
// metric management will be *disabled*
|
||||
//
|
||||
// Note: If submission url is supplied w/o an api token, the public circonus ca cert will be used
|
||||
// to verify the broker for metrics submission.
|
||||
func NewCirconusSink(cc *Config) (*CirconusSink, error) {
|
||||
cfg := cgm.Config{}
|
||||
if cc != nil {
|
||||
cfg = cgm.Config(*cc)
|
||||
}
|
||||
|
||||
metrics, err := cgm.NewCirconusMetrics(&cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &CirconusSink{
|
||||
metrics: metrics,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start submitting metrics to Circonus (flush every SubmitInterval)
|
||||
func (s *CirconusSink) Start() {
|
||||
s.metrics.Start()
|
||||
}
|
||||
|
||||
// Flush manually triggers metric submission to Circonus
|
||||
func (s *CirconusSink) Flush() {
|
||||
s.metrics.Flush()
|
||||
}
|
||||
|
||||
// SetGauge sets value for a gauge metric
|
||||
func (s *CirconusSink) SetGauge(key []string, val float32) {
|
||||
flatKey := s.flattenKey(key)
|
||||
s.metrics.SetGauge(flatKey, int64(val))
|
||||
}
|
||||
|
||||
// SetGaugeWithLabels sets value for a gauge metric with the given labels
|
||||
func (s *CirconusSink) SetGaugeWithLabels(key []string, val float32, labels []metrics.Label) {
|
||||
flatKey := s.flattenKeyLabels(key, labels)
|
||||
s.metrics.SetGauge(flatKey, int64(val))
|
||||
}
|
||||
|
||||
// EmitKey is not implemented in circonus
|
||||
func (s *CirconusSink) EmitKey(key []string, val float32) {
|
||||
// NOP
|
||||
}
|
||||
|
||||
// IncrCounter increments a counter metric
|
||||
func (s *CirconusSink) IncrCounter(key []string, val float32) {
|
||||
flatKey := s.flattenKey(key)
|
||||
s.metrics.IncrementByValue(flatKey, uint64(val))
|
||||
}
|
||||
|
||||
// IncrCounterWithLabels increments a counter metric with the given labels
|
||||
func (s *CirconusSink) IncrCounterWithLabels(key []string, val float32, labels []metrics.Label) {
|
||||
flatKey := s.flattenKeyLabels(key, labels)
|
||||
s.metrics.IncrementByValue(flatKey, uint64(val))
|
||||
}
|
||||
|
||||
// AddSample adds a sample to a histogram metric
|
||||
func (s *CirconusSink) AddSample(key []string, val float32) {
|
||||
flatKey := s.flattenKey(key)
|
||||
s.metrics.RecordValue(flatKey, float64(val))
|
||||
}
|
||||
|
||||
// AddSampleWithLabels adds a sample to a histogram metric with the given labels
|
||||
func (s *CirconusSink) AddSampleWithLabels(key []string, val float32, labels []metrics.Label) {
|
||||
flatKey := s.flattenKeyLabels(key, labels)
|
||||
s.metrics.RecordValue(flatKey, float64(val))
|
||||
}
|
||||
|
||||
// Flattens key to Circonus metric name
|
||||
func (s *CirconusSink) flattenKey(parts []string) string {
|
||||
joined := strings.Join(parts, "`")
|
||||
return strings.Map(func(r rune) rune {
|
||||
switch r {
|
||||
case ' ':
|
||||
return '_'
|
||||
default:
|
||||
return r
|
||||
}
|
||||
}, joined)
|
||||
}
|
||||
|
||||
// Flattens the key along with labels for formatting, removes spaces
|
||||
func (s *CirconusSink) flattenKeyLabels(parts []string, labels []metrics.Label) string {
|
||||
for _, label := range labels {
|
||||
parts = append(parts, label.Value)
|
||||
}
|
||||
return s.flattenKey(parts)
|
||||
}
|
||||
153
vendor/github.com/armon/go-metrics/circonus/circonus_test.go
сгенерированный
поставляемый
153
vendor/github.com/armon/go-metrics/circonus/circonus_test.go
сгенерированный
поставляемый
@@ -1,153 +0,0 @@
|
||||
package circonus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewCirconusSink(t *testing.T) {
|
||||
|
||||
// test with invalid config (nil)
|
||||
expectedError := errors.New("invalid check manager configuration (no API token AND no submission url)")
|
||||
_, err := NewCirconusSink(nil)
|
||||
if err == nil || err.Error() != expectedError.Error() {
|
||||
t.Errorf("Expected an '%#v' error, got '%#v'", expectedError, err)
|
||||
}
|
||||
|
||||
// test w/submission url and w/o token
|
||||
cfg := &Config{}
|
||||
cfg.CheckManager.Check.SubmissionURL = "http://127.0.0.1:43191/"
|
||||
_, err = NewCirconusSink(cfg)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got '%v'", err)
|
||||
}
|
||||
|
||||
// note: a test with a valid token is *not* done as it *will* create a
|
||||
// check resulting in testing the api more than the circonus sink
|
||||
// see circonus-gometrics/checkmgr/checkmgr_test.go for testing of api token
|
||||
}
|
||||
|
||||
func TestFlattenKey(t *testing.T) {
|
||||
var testKeys = []struct {
|
||||
input []string
|
||||
expected string
|
||||
}{
|
||||
{[]string{"a", "b", "c"}, "a`b`c"},
|
||||
{[]string{"a-a", "b_b", "c/c"}, "a-a`b_b`c/c"},
|
||||
{[]string{"spaces must", "flatten", "to", "underscores"}, "spaces_must`flatten`to`underscores"},
|
||||
}
|
||||
|
||||
c := &CirconusSink{}
|
||||
|
||||
for _, test := range testKeys {
|
||||
if actual := c.flattenKey(test.input); actual != test.expected {
|
||||
t.Fatalf("Flattening %v failed, expected '%s' got '%s'", test.input, test.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fakeBroker(q chan string) *httptest.Server {
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
defer r.Body.Close()
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
q <- err.Error()
|
||||
fmt.Fprintln(w, err.Error())
|
||||
} else {
|
||||
q <- string(body)
|
||||
fmt.Fprintln(w, `{"stats":1}`)
|
||||
}
|
||||
}
|
||||
|
||||
return httptest.NewServer(http.HandlerFunc(handler))
|
||||
}
|
||||
|
||||
func TestSetGauge(t *testing.T) {
|
||||
q := make(chan string)
|
||||
|
||||
server := fakeBroker(q)
|
||||
defer server.Close()
|
||||
|
||||
cfg := &Config{}
|
||||
cfg.CheckManager.Check.SubmissionURL = server.URL
|
||||
|
||||
cs, err := NewCirconusSink(cfg)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got '%v'", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
cs.SetGauge([]string{"foo", "bar"}, 1)
|
||||
cs.Flush()
|
||||
}()
|
||||
|
||||
expect := "{\"foo`bar\":{\"_type\":\"n\",\"_value\":\"1\"}}"
|
||||
actual := <-q
|
||||
|
||||
if actual != expect {
|
||||
t.Errorf("Expected '%s', got '%s'", expect, actual)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestIncrCounter(t *testing.T) {
|
||||
q := make(chan string)
|
||||
|
||||
server := fakeBroker(q)
|
||||
defer server.Close()
|
||||
|
||||
cfg := &Config{}
|
||||
cfg.CheckManager.Check.SubmissionURL = server.URL
|
||||
|
||||
cs, err := NewCirconusSink(cfg)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got '%v'", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
cs.IncrCounter([]string{"foo", "bar"}, 1)
|
||||
cs.Flush()
|
||||
}()
|
||||
|
||||
expect := "{\"foo`bar\":{\"_type\":\"n\",\"_value\":1}}"
|
||||
actual := <-q
|
||||
|
||||
if actual != expect {
|
||||
t.Errorf("Expected '%s', got '%s'", expect, actual)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddSample(t *testing.T) {
|
||||
q := make(chan string)
|
||||
|
||||
server := fakeBroker(q)
|
||||
defer server.Close()
|
||||
|
||||
cfg := &Config{}
|
||||
cfg.CheckManager.Check.SubmissionURL = server.URL
|
||||
|
||||
cs, err := NewCirconusSink(cfg)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got '%v'", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
cs.AddSample([]string{"foo", "bar"}, 1)
|
||||
cs.Flush()
|
||||
}()
|
||||
|
||||
expect := "{\"foo`bar\":{\"_type\":\"n\",\"_value\":[\"H[1.0e+00]=1\"]}}"
|
||||
actual := <-q
|
||||
|
||||
if actual != expect {
|
||||
t.Errorf("Expected '%s', got '%s'", expect, actual)
|
||||
|
||||
}
|
||||
}
|
||||
140
vendor/github.com/armon/go-metrics/datadog/dogstatsd.go
сгенерированный
поставляемый
140
vendor/github.com/armon/go-metrics/datadog/dogstatsd.go
сгенерированный
поставляемый
@@ -1,140 +0,0 @@
|
||||
package datadog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/DataDog/datadog-go/statsd"
|
||||
"github.com/armon/go-metrics"
|
||||
)
|
||||
|
||||
// DogStatsdSink provides a MetricSink that can be used
|
||||
// with a dogstatsd server. It utilizes the Dogstatsd client at github.com/DataDog/datadog-go/statsd
|
||||
type DogStatsdSink struct {
|
||||
client *statsd.Client
|
||||
hostName string
|
||||
propagateHostname bool
|
||||
}
|
||||
|
||||
// NewDogStatsdSink is used to create a new DogStatsdSink with sane defaults
|
||||
func NewDogStatsdSink(addr string, hostName string) (*DogStatsdSink, error) {
|
||||
client, err := statsd.New(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sink := &DogStatsdSink{
|
||||
client: client,
|
||||
hostName: hostName,
|
||||
propagateHostname: false,
|
||||
}
|
||||
return sink, nil
|
||||
}
|
||||
|
||||
// SetTags sets common tags on the Dogstatsd Client that will be sent
|
||||
// along with all dogstatsd packets.
|
||||
// Ref: http://docs.datadoghq.com/guides/dogstatsd/#tags
|
||||
func (s *DogStatsdSink) SetTags(tags []string) {
|
||||
s.client.Tags = tags
|
||||
}
|
||||
|
||||
// EnableHostnamePropagation forces a Dogstatsd `host` tag with the value specified by `s.HostName`
|
||||
// Since the go-metrics package has its own mechanism for attaching a hostname to metrics,
|
||||
// setting the `propagateHostname` flag ensures that `s.HostName` overrides the host tag naively set by the DogStatsd server
|
||||
func (s *DogStatsdSink) EnableHostNamePropagation() {
|
||||
s.propagateHostname = true
|
||||
}
|
||||
|
||||
func (s *DogStatsdSink) flattenKey(parts []string) string {
|
||||
joined := strings.Join(parts, ".")
|
||||
return strings.Map(sanitize, joined)
|
||||
}
|
||||
|
||||
func sanitize(r rune) rune {
|
||||
switch r {
|
||||
case ':':
|
||||
fallthrough
|
||||
case ' ':
|
||||
return '_'
|
||||
default:
|
||||
return r
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DogStatsdSink) parseKey(key []string) ([]string, []metrics.Label) {
|
||||
// Since DogStatsd supports dimensionality via tags on metric keys, this sink's approach is to splice the hostname out of the key in favor of a `host` tag
|
||||
// The `host` tag is either forced here, or set downstream by the DogStatsd server
|
||||
|
||||
var labels []metrics.Label
|
||||
hostName := s.hostName
|
||||
|
||||
// Splice the hostname out of the key
|
||||
for i, el := range key {
|
||||
if el == hostName {
|
||||
key = append(key[:i], key[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if s.propagateHostname {
|
||||
labels = append(labels, metrics.Label{"host", hostName})
|
||||
}
|
||||
return key, labels
|
||||
}
|
||||
|
||||
// Implementation of methods in the MetricSink interface
|
||||
|
||||
func (s *DogStatsdSink) SetGauge(key []string, val float32) {
|
||||
s.SetGaugeWithLabels(key, val, nil)
|
||||
}
|
||||
|
||||
func (s *DogStatsdSink) IncrCounter(key []string, val float32) {
|
||||
s.IncrCounterWithLabels(key, val, nil)
|
||||
}
|
||||
|
||||
// EmitKey is not implemented since DogStatsd does not provide a metric type that holds an
|
||||
// arbitrary number of values
|
||||
func (s *DogStatsdSink) EmitKey(key []string, val float32) {
|
||||
}
|
||||
|
||||
func (s *DogStatsdSink) AddSample(key []string, val float32) {
|
||||
s.AddSampleWithLabels(key, val, nil)
|
||||
}
|
||||
|
||||
// The following ...WithLabels methods correspond to Datadog's Tag extension to Statsd.
|
||||
// http://docs.datadoghq.com/guides/dogstatsd/#tags
|
||||
func (s *DogStatsdSink) SetGaugeWithLabels(key []string, val float32, labels []metrics.Label) {
|
||||
flatKey, tags := s.getFlatkeyAndCombinedLabels(key, labels)
|
||||
rate := 1.0
|
||||
s.client.Gauge(flatKey, float64(val), tags, rate)
|
||||
}
|
||||
|
||||
func (s *DogStatsdSink) IncrCounterWithLabels(key []string, val float32, labels []metrics.Label) {
|
||||
flatKey, tags := s.getFlatkeyAndCombinedLabels(key, labels)
|
||||
rate := 1.0
|
||||
s.client.Count(flatKey, int64(val), tags, rate)
|
||||
}
|
||||
|
||||
func (s *DogStatsdSink) AddSampleWithLabels(key []string, val float32, labels []metrics.Label) {
|
||||
flatKey, tags := s.getFlatkeyAndCombinedLabels(key, labels)
|
||||
rate := 1.0
|
||||
s.client.TimeInMilliseconds(flatKey, float64(val), tags, rate)
|
||||
}
|
||||
|
||||
func (s *DogStatsdSink) getFlatkeyAndCombinedLabels(key []string, labels []metrics.Label) (string, []string) {
|
||||
key, parsedLabels := s.parseKey(key)
|
||||
flatKey := s.flattenKey(key)
|
||||
labels = append(labels, parsedLabels...)
|
||||
|
||||
var tags []string
|
||||
for _, label := range labels {
|
||||
label.Name = strings.Map(sanitize, label.Name)
|
||||
label.Value = strings.Map(sanitize, label.Value)
|
||||
if label.Value != "" {
|
||||
tags = append(tags, fmt.Sprintf("%s:%s", label.Name, label.Value))
|
||||
} else {
|
||||
tags = append(tags, label.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return flatKey, tags
|
||||
}
|
||||
150
vendor/github.com/armon/go-metrics/datadog/dogstatsd_test.go
сгенерированный
поставляемый
150
vendor/github.com/armon/go-metrics/datadog/dogstatsd_test.go
сгенерированный
поставляемый
@@ -1,150 +0,0 @@
|
||||
package datadog
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/armon/go-metrics"
|
||||
)
|
||||
|
||||
var EmptyTags []metrics.Label
|
||||
|
||||
const (
|
||||
DogStatsdAddr = "127.0.0.1:7254"
|
||||
HostnameEnabled = true
|
||||
HostnameDisabled = false
|
||||
TestHostname = "test_hostname"
|
||||
)
|
||||
|
||||
func MockGetHostname() string {
|
||||
return TestHostname
|
||||
}
|
||||
|
||||
var ParseKeyTests = []struct {
|
||||
KeyToParse []string
|
||||
Tags []metrics.Label
|
||||
PropagateHostname bool
|
||||
ExpectedKey []string
|
||||
ExpectedTags []metrics.Label
|
||||
}{
|
||||
{[]string{"a", MockGetHostname(), "b", "c"}, EmptyTags, HostnameDisabled, []string{"a", "b", "c"}, EmptyTags},
|
||||
{[]string{"a", "b", "c"}, EmptyTags, HostnameDisabled, []string{"a", "b", "c"}, EmptyTags},
|
||||
{[]string{"a", "b", "c"}, EmptyTags, HostnameEnabled, []string{"a", "b", "c"}, []metrics.Label{{"host", MockGetHostname()}}},
|
||||
}
|
||||
|
||||
var FlattenKeyTests = []struct {
|
||||
KeyToFlatten []string
|
||||
Expected string
|
||||
}{
|
||||
{[]string{"a", "b", "c"}, "a.b.c"},
|
||||
{[]string{"spaces must", "flatten", "to", "underscores"}, "spaces_must.flatten.to.underscores"},
|
||||
}
|
||||
|
||||
var MetricSinkTests = []struct {
|
||||
Method string
|
||||
Metric []string
|
||||
Value interface{}
|
||||
Tags []metrics.Label
|
||||
PropagateHostname bool
|
||||
Expected string
|
||||
}{
|
||||
{"SetGauge", []string{"foo", "bar"}, float32(42), EmptyTags, HostnameDisabled, "foo.bar:42.000000|g"},
|
||||
{"SetGauge", []string{"foo", "bar", "baz"}, float32(42), EmptyTags, HostnameDisabled, "foo.bar.baz:42.000000|g"},
|
||||
{"AddSample", []string{"sample", "thing"}, float32(4), EmptyTags, HostnameDisabled, "sample.thing:4.000000|ms"},
|
||||
{"IncrCounter", []string{"count", "me"}, float32(3), EmptyTags, HostnameDisabled, "count.me:3|c"},
|
||||
|
||||
{"SetGauge", []string{"foo", "baz"}, float32(42), []metrics.Label{{"my_tag", ""}}, HostnameDisabled, "foo.baz:42.000000|g|#my_tag"},
|
||||
{"SetGauge", []string{"foo", "baz"}, float32(42), []metrics.Label{{"my tag", "my_value"}}, HostnameDisabled, "foo.baz:42.000000|g|#my_tag:my_value"},
|
||||
{"SetGauge", []string{"foo", "bar"}, float32(42), []metrics.Label{{"my_tag", "my_value"}, {"other_tag", "other_value"}}, HostnameDisabled, "foo.bar:42.000000|g|#my_tag:my_value,other_tag:other_value"},
|
||||
{"SetGauge", []string{"foo", "bar"}, float32(42), []metrics.Label{{"my_tag", "my_value"}, {"other_tag", "other_value"}}, HostnameEnabled, "foo.bar:42.000000|g|#my_tag:my_value,other_tag:other_value,host:test_hostname"},
|
||||
}
|
||||
|
||||
func mockNewDogStatsdSink(addr string, labels []metrics.Label, tagWithHostname bool) *DogStatsdSink {
|
||||
dog, _ := NewDogStatsdSink(addr, MockGetHostname())
|
||||
_, tags := dog.getFlatkeyAndCombinedLabels(nil, labels)
|
||||
dog.SetTags(tags)
|
||||
if tagWithHostname {
|
||||
dog.EnableHostNamePropagation()
|
||||
}
|
||||
|
||||
return dog
|
||||
}
|
||||
|
||||
func setupTestServerAndBuffer(t *testing.T) (*net.UDPConn, []byte) {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", DogStatsdAddr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
server, err := net.ListenUDP("udp", udpAddr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return server, make([]byte, 1024)
|
||||
}
|
||||
|
||||
func TestParseKey(t *testing.T) {
|
||||
for _, tt := range ParseKeyTests {
|
||||
dog := mockNewDogStatsdSink(DogStatsdAddr, tt.Tags, tt.PropagateHostname)
|
||||
key, tags := dog.parseKey(tt.KeyToParse)
|
||||
|
||||
if !reflect.DeepEqual(key, tt.ExpectedKey) {
|
||||
t.Fatalf("Key Parsing failed for %v", tt.KeyToParse)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tags, tt.ExpectedTags) {
|
||||
t.Fatalf("Tag Parsing Failed for %v, %v != %v", tt.KeyToParse, tags, tt.ExpectedTags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlattenKey(t *testing.T) {
|
||||
dog := mockNewDogStatsdSink(DogStatsdAddr, EmptyTags, HostnameDisabled)
|
||||
for _, tt := range FlattenKeyTests {
|
||||
if !reflect.DeepEqual(dog.flattenKey(tt.KeyToFlatten), tt.Expected) {
|
||||
t.Fatalf("Flattening %v failed", tt.KeyToFlatten)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricSink(t *testing.T) {
|
||||
server, buf := setupTestServerAndBuffer(t)
|
||||
defer server.Close()
|
||||
|
||||
for _, tt := range MetricSinkTests {
|
||||
dog := mockNewDogStatsdSink(DogStatsdAddr, tt.Tags, tt.PropagateHostname)
|
||||
method := reflect.ValueOf(dog).MethodByName(tt.Method)
|
||||
method.Call([]reflect.Value{
|
||||
reflect.ValueOf(tt.Metric),
|
||||
reflect.ValueOf(tt.Value)})
|
||||
assertServerMatchesExpected(t, server, buf, tt.Expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaggableMetrics(t *testing.T) {
|
||||
server, buf := setupTestServerAndBuffer(t)
|
||||
defer server.Close()
|
||||
|
||||
dog := mockNewDogStatsdSink(DogStatsdAddr, EmptyTags, HostnameDisabled)
|
||||
|
||||
dog.AddSampleWithLabels([]string{"sample", "thing"}, float32(4), []metrics.Label{{"tagkey", "tagvalue"}})
|
||||
assertServerMatchesExpected(t, server, buf, "sample.thing:4.000000|ms|#tagkey:tagvalue")
|
||||
|
||||
dog.SetGaugeWithLabels([]string{"sample", "thing"}, float32(4), []metrics.Label{{"tagkey", "tagvalue"}})
|
||||
assertServerMatchesExpected(t, server, buf, "sample.thing:4.000000|g|#tagkey:tagvalue")
|
||||
|
||||
dog.IncrCounterWithLabels([]string{"sample", "thing"}, float32(4), []metrics.Label{{"tagkey", "tagvalue"}})
|
||||
assertServerMatchesExpected(t, server, buf, "sample.thing:4|c|#tagkey:tagvalue")
|
||||
|
||||
dog = mockNewDogStatsdSink(DogStatsdAddr, []metrics.Label{{Name: "global"}}, HostnameEnabled) // with hostname, global tags
|
||||
dog.IncrCounterWithLabels([]string{"sample", "thing"}, float32(4), []metrics.Label{{"tagkey", "tagvalue"}})
|
||||
assertServerMatchesExpected(t, server, buf, "sample.thing:4|c|#global,tagkey:tagvalue,host:test_hostname")
|
||||
}
|
||||
|
||||
func assertServerMatchesExpected(t *testing.T, server *net.UDPConn, buf []byte, expected string) {
|
||||
n, _ := server.Read(buf)
|
||||
msg := buf[:n]
|
||||
if string(msg) != expected {
|
||||
t.Fatalf("Line %s does not match expected: %s", string(msg), expected)
|
||||
}
|
||||
}
|
||||
33
vendor/github.com/armon/go-metrics/inmem.go
сгенерированный
поставляемый
33
vendor/github.com/armon/go-metrics/inmem.go
сгенерированный
поставляемый
@@ -232,8 +232,37 @@ func (i *InmemSink) Data() []*IntervalMetrics {
|
||||
i.intervalLock.RLock()
|
||||
defer i.intervalLock.RUnlock()
|
||||
|
||||
intervals := make([]*IntervalMetrics, len(i.intervals))
|
||||
copy(intervals, i.intervals)
|
||||
n := len(i.intervals)
|
||||
intervals := make([]*IntervalMetrics, n)
|
||||
|
||||
copy(intervals[:n-1], i.intervals[:n-1])
|
||||
current := i.intervals[n-1]
|
||||
|
||||
// make its own copy for current interval
|
||||
intervals[n-1] = &IntervalMetrics{}
|
||||
copyCurrent := intervals[n-1]
|
||||
current.RLock()
|
||||
*copyCurrent = *current
|
||||
|
||||
copyCurrent.Gauges = make(map[string]GaugeValue, len(current.Gauges))
|
||||
for k, v := range current.Gauges {
|
||||
copyCurrent.Gauges[k] = v
|
||||
}
|
||||
// saved values will be not change, just copy its link
|
||||
copyCurrent.Points = make(map[string][]float32, len(current.Points))
|
||||
for k, v := range current.Points {
|
||||
copyCurrent.Points[k] = v
|
||||
}
|
||||
copyCurrent.Counters = make(map[string]SampledValue, len(current.Counters))
|
||||
for k, v := range current.Counters {
|
||||
copyCurrent.Counters[k] = v
|
||||
}
|
||||
copyCurrent.Samples = make(map[string]SampledValue, len(current.Samples))
|
||||
for k, v := range current.Samples {
|
||||
copyCurrent.Samples[k] = v
|
||||
}
|
||||
current.RUnlock()
|
||||
|
||||
return intervals
|
||||
}
|
||||
|
||||
|
||||
133
vendor/github.com/armon/go-metrics/inmem_endpoint_test.go
сгенерированный
поставляемый
133
vendor/github.com/armon/go-metrics/inmem_endpoint_test.go
сгенерированный
поставляемый
@@ -1,133 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pascaldekloe/goe/verify"
|
||||
)
|
||||
|
||||
func TestDisplayMetrics(t *testing.T) {
|
||||
interval := 10 * time.Millisecond
|
||||
inm := NewInmemSink(interval, 50*time.Millisecond)
|
||||
|
||||
// Add data points
|
||||
inm.SetGauge([]string{"foo", "bar"}, 42)
|
||||
inm.SetGaugeWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}})
|
||||
inm.EmitKey([]string{"foo", "bar"}, 42)
|
||||
inm.IncrCounter([]string{"foo", "bar"}, 20)
|
||||
inm.IncrCounter([]string{"foo", "bar"}, 22)
|
||||
inm.IncrCounterWithLabels([]string{"foo", "bar"}, 20, []Label{{"a", "b"}})
|
||||
inm.IncrCounterWithLabels([]string{"foo", "bar"}, 40, []Label{{"a", "b"}})
|
||||
inm.AddSample([]string{"foo", "bar"}, 20)
|
||||
inm.AddSample([]string{"foo", "bar"}, 24)
|
||||
inm.AddSampleWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}})
|
||||
inm.AddSampleWithLabels([]string{"foo", "bar"}, 33, []Label{{"a", "b"}})
|
||||
|
||||
data := inm.Data()
|
||||
if len(data) != 1 {
|
||||
t.Fatalf("bad: %v", data)
|
||||
}
|
||||
|
||||
expected := MetricsSummary{
|
||||
Timestamp: data[0].Interval.Round(time.Second).UTC().String(),
|
||||
Gauges: []GaugeValue{
|
||||
{
|
||||
Name: "foo.bar",
|
||||
Hash: "foo.bar",
|
||||
Value: float32(42),
|
||||
DisplayLabels: map[string]string{},
|
||||
},
|
||||
{
|
||||
Name: "foo.bar",
|
||||
Hash: "foo.bar;a=b",
|
||||
Value: float32(23),
|
||||
DisplayLabels: map[string]string{"a": "b"},
|
||||
},
|
||||
},
|
||||
Points: []PointValue{
|
||||
{
|
||||
Name: "foo.bar",
|
||||
Points: []float32{42},
|
||||
},
|
||||
},
|
||||
Counters: []SampledValue{
|
||||
{
|
||||
Name: "foo.bar",
|
||||
Hash: "foo.bar",
|
||||
AggregateSample: &AggregateSample{
|
||||
Count: 2,
|
||||
Min: 20,
|
||||
Max: 22,
|
||||
Sum: 42,
|
||||
SumSq: 884,
|
||||
Rate: 4200,
|
||||
},
|
||||
Mean: 21,
|
||||
Stddev: 1.4142135623730951,
|
||||
},
|
||||
{
|
||||
Name: "foo.bar",
|
||||
Hash: "foo.bar;a=b",
|
||||
AggregateSample: &AggregateSample{
|
||||
Count: 2,
|
||||
Min: 20,
|
||||
Max: 40,
|
||||
Sum: 60,
|
||||
SumSq: 2000,
|
||||
Rate: 6000,
|
||||
},
|
||||
Mean: 30,
|
||||
Stddev: 14.142135623730951,
|
||||
DisplayLabels: map[string]string{"a": "b"},
|
||||
},
|
||||
},
|
||||
Samples: []SampledValue{
|
||||
{
|
||||
Name: "foo.bar",
|
||||
Hash: "foo.bar",
|
||||
AggregateSample: &AggregateSample{
|
||||
Count: 2,
|
||||
Min: 20,
|
||||
Max: 24,
|
||||
Sum: 44,
|
||||
SumSq: 976,
|
||||
Rate: 4400,
|
||||
},
|
||||
Mean: 22,
|
||||
Stddev: 2.8284271247461903,
|
||||
},
|
||||
{
|
||||
Name: "foo.bar",
|
||||
Hash: "foo.bar;a=b",
|
||||
AggregateSample: &AggregateSample{
|
||||
Count: 2,
|
||||
Min: 23,
|
||||
Max: 33,
|
||||
Sum: 56,
|
||||
SumSq: 1618,
|
||||
Rate: 5600,
|
||||
},
|
||||
Mean: 28,
|
||||
Stddev: 7.0710678118654755,
|
||||
DisplayLabels: map[string]string{"a": "b"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
raw, err := inm.DisplayMetrics(nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
result := raw.(MetricsSummary)
|
||||
|
||||
// Ignore the LastUpdated field, we don't export that anyway
|
||||
for i, got := range result.Counters {
|
||||
expected.Counters[i].LastUpdated = got.LastUpdated
|
||||
}
|
||||
for i, got := range result.Samples {
|
||||
expected.Samples[i].LastUpdated = got.LastUpdated
|
||||
}
|
||||
|
||||
verify.Values(t, "all", result, expected)
|
||||
}
|
||||
58
vendor/github.com/armon/go-metrics/inmem_signal_test.go
сгенерированный
поставляемый
58
vendor/github.com/armon/go-metrics/inmem_signal_test.go
сгенерированный
поставляемый
@@ -1,58 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestInmemSignal(t *testing.T) {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
inm := NewInmemSink(10*time.Millisecond, 50*time.Millisecond)
|
||||
sig := NewInmemSignal(inm, syscall.SIGUSR1, buf)
|
||||
defer sig.Stop()
|
||||
|
||||
inm.SetGauge([]string{"foo"}, 42)
|
||||
inm.EmitKey([]string{"bar"}, 42)
|
||||
inm.IncrCounter([]string{"baz"}, 42)
|
||||
inm.AddSample([]string{"wow"}, 42)
|
||||
inm.SetGaugeWithLabels([]string{"asdf"}, 42, []Label{{"a", "b"}})
|
||||
inm.IncrCounterWithLabels([]string{"qwer"}, 42, []Label{{"a", "b"}})
|
||||
inm.AddSampleWithLabels([]string{"zxcv"}, 42, []Label{{"a", "b"}})
|
||||
|
||||
// Wait for period to end
|
||||
time.Sleep(15 * time.Millisecond)
|
||||
|
||||
// Send signal!
|
||||
syscall.Kill(os.Getpid(), syscall.SIGUSR1)
|
||||
|
||||
// Wait for flush
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// Check the output
|
||||
out := string(buf.Bytes())
|
||||
if !strings.Contains(out, "[G] 'foo': 42") {
|
||||
t.Fatalf("bad: %v", out)
|
||||
}
|
||||
if !strings.Contains(out, "[P] 'bar': 42") {
|
||||
t.Fatalf("bad: %v", out)
|
||||
}
|
||||
if !strings.Contains(out, "[C] 'baz': Count: 1 Sum: 42") {
|
||||
t.Fatalf("bad: %v", out)
|
||||
}
|
||||
if !strings.Contains(out, "[S] 'wow': Count: 1 Sum: 42") {
|
||||
t.Fatalf("bad: %v", out)
|
||||
}
|
||||
if !strings.Contains(out, "[G] 'asdf.b': 42") {
|
||||
t.Fatalf("bad: %v", out)
|
||||
}
|
||||
if !strings.Contains(out, "[C] 'qwer.b': Count: 1 Sum: 42") {
|
||||
t.Fatalf("bad: %v", out)
|
||||
}
|
||||
if !strings.Contains(out, "[S] 'zxcv.b': Count: 1 Sum: 42") {
|
||||
t.Fatalf("bad: %v", out)
|
||||
}
|
||||
}
|
||||
190
vendor/github.com/armon/go-metrics/inmem_test.go
сгенерированный
поставляемый
190
vendor/github.com/armon/go-metrics/inmem_test.go
сгенерированный
поставляемый
@@ -1,190 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"math"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestInmemSink(t *testing.T) {
|
||||
inm := NewInmemSink(10*time.Millisecond, 50*time.Millisecond)
|
||||
|
||||
data := inm.Data()
|
||||
if len(data) != 1 {
|
||||
t.Fatalf("bad: %v", data)
|
||||
}
|
||||
|
||||
// Add data points
|
||||
inm.SetGauge([]string{"foo", "bar"}, 42)
|
||||
inm.SetGaugeWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}})
|
||||
inm.EmitKey([]string{"foo", "bar"}, 42)
|
||||
inm.IncrCounter([]string{"foo", "bar"}, 20)
|
||||
inm.IncrCounter([]string{"foo", "bar"}, 22)
|
||||
inm.IncrCounterWithLabels([]string{"foo", "bar"}, 20, []Label{{"a", "b"}})
|
||||
inm.IncrCounterWithLabels([]string{"foo", "bar"}, 22, []Label{{"a", "b"}})
|
||||
inm.AddSample([]string{"foo", "bar"}, 20)
|
||||
inm.AddSample([]string{"foo", "bar"}, 22)
|
||||
inm.AddSampleWithLabels([]string{"foo", "bar"}, 23, []Label{{"a", "b"}})
|
||||
|
||||
data = inm.Data()
|
||||
if len(data) != 1 {
|
||||
t.Fatalf("bad: %v", data)
|
||||
}
|
||||
|
||||
intvM := data[0]
|
||||
intvM.RLock()
|
||||
|
||||
if time.Now().Sub(intvM.Interval) > 10*time.Millisecond {
|
||||
t.Fatalf("interval too old")
|
||||
}
|
||||
if intvM.Gauges["foo.bar"].Value != 42 {
|
||||
t.Fatalf("bad val: %v", intvM.Gauges)
|
||||
}
|
||||
if intvM.Gauges["foo.bar;a=b"].Value != 23 {
|
||||
t.Fatalf("bad val: %v", intvM.Gauges)
|
||||
}
|
||||
if intvM.Points["foo.bar"][0] != 42 {
|
||||
t.Fatalf("bad val: %v", intvM.Points)
|
||||
}
|
||||
|
||||
for _, agg := range []SampledValue{intvM.Counters["foo.bar"], intvM.Counters["foo.bar;a=b"]} {
|
||||
if agg.Count != 2 {
|
||||
t.Fatalf("bad val: %v", agg)
|
||||
}
|
||||
if agg.Rate != 4200 {
|
||||
t.Fatalf("bad val: %v", agg.Rate)
|
||||
}
|
||||
if agg.Sum != 42 {
|
||||
t.Fatalf("bad val: %v", agg)
|
||||
}
|
||||
if agg.SumSq != 884 {
|
||||
t.Fatalf("bad val: %v", agg)
|
||||
}
|
||||
if agg.Min != 20 {
|
||||
t.Fatalf("bad val: %v", agg)
|
||||
}
|
||||
if agg.Max != 22 {
|
||||
t.Fatalf("bad val: %v", agg)
|
||||
}
|
||||
if agg.AggregateSample.Mean() != 21 {
|
||||
t.Fatalf("bad val: %v", agg)
|
||||
}
|
||||
if agg.AggregateSample.Stddev() != math.Sqrt(2) {
|
||||
t.Fatalf("bad val: %v", agg)
|
||||
}
|
||||
|
||||
if agg.LastUpdated.IsZero() {
|
||||
t.Fatalf("agg.LastUpdated is not set: %v", agg)
|
||||
}
|
||||
|
||||
diff := time.Now().Sub(agg.LastUpdated).Seconds()
|
||||
if diff > 1 {
|
||||
t.Fatalf("time diff too great: %f", diff)
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := intvM.Samples["foo.bar"]; !ok {
|
||||
t.Fatalf("missing sample")
|
||||
}
|
||||
|
||||
if _, ok := intvM.Samples["foo.bar;a=b"]; !ok {
|
||||
t.Fatalf("missing sample")
|
||||
}
|
||||
|
||||
intvM.RUnlock()
|
||||
|
||||
for i := 1; i < 10; i++ {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
inm.SetGauge([]string{"foo", "bar"}, 42)
|
||||
data = inm.Data()
|
||||
if len(data) != min(i+1, 5) {
|
||||
t.Fatalf("bad: %v", data)
|
||||
}
|
||||
}
|
||||
|
||||
// Should not exceed 5 intervals!
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
inm.SetGauge([]string{"foo", "bar"}, 42)
|
||||
data = inm.Data()
|
||||
if len(data) != 5 {
|
||||
t.Fatalf("bad: %v", data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewInmemSinkFromURL(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
desc string
|
||||
input string
|
||||
expectErr string
|
||||
expectInterval time.Duration
|
||||
expectRetain time.Duration
|
||||
}{
|
||||
{
|
||||
desc: "interval and duration are set via query params",
|
||||
input: "inmem://?interval=11s&retain=22s",
|
||||
expectInterval: duration(t, "11s"),
|
||||
expectRetain: duration(t, "22s"),
|
||||
},
|
||||
{
|
||||
desc: "interval is required",
|
||||
input: "inmem://?retain=22s",
|
||||
expectErr: "Bad 'interval' param",
|
||||
},
|
||||
{
|
||||
desc: "interval must be a duration",
|
||||
input: "inmem://?retain=30s&interval=HIYA",
|
||||
expectErr: "Bad 'interval' param",
|
||||
},
|
||||
{
|
||||
desc: "retain is required",
|
||||
input: "inmem://?interval=30s",
|
||||
expectErr: "Bad 'retain' param",
|
||||
},
|
||||
{
|
||||
desc: "retain must be a valid duration",
|
||||
input: "inmem://?interval=30s&retain=HELLO",
|
||||
expectErr: "Bad 'retain' param",
|
||||
},
|
||||
} {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
u, err := url.Parse(tc.input)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing URL: %s", err)
|
||||
}
|
||||
ms, err := NewInmemSinkFromURL(u)
|
||||
if tc.expectErr != "" {
|
||||
if !strings.Contains(err.Error(), tc.expectErr) {
|
||||
t.Fatalf("expected err: %q, to contain: %q", err, tc.expectErr)
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %s", err)
|
||||
}
|
||||
is := ms.(*InmemSink)
|
||||
if is.interval != tc.expectInterval {
|
||||
t.Fatalf("expected interval %s, got: %s", tc.expectInterval, is.interval)
|
||||
}
|
||||
if is.retain != tc.expectRetain {
|
||||
t.Fatalf("expected retain %s, got: %s", tc.expectRetain, is.retain)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func duration(t *testing.T, s string) time.Duration {
|
||||
dur, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing duration: %s", err)
|
||||
}
|
||||
return dur
|
||||
}
|
||||
411
vendor/github.com/armon/go-metrics/metrics_test.go
сгенерированный
поставляемый
411
vendor/github.com/armon/go-metrics/metrics_test.go
сгенерированный
поставляемый
@@ -1,411 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mockMetric() (*MockSink, *Metrics) {
|
||||
m := &MockSink{}
|
||||
met := &Metrics{Config: Config{FilterDefault: true}, sink: m}
|
||||
return m, met
|
||||
}
|
||||
|
||||
func TestMetrics_SetGauge(t *testing.T) {
|
||||
m, met := mockMetric()
|
||||
met.SetGauge([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
labels := []Label{{"a", "b"}}
|
||||
met.SetGaugeWithLabels([]string{"key"}, float32(1), labels)
|
||||
if m.keys[0][0] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if !reflect.DeepEqual(m.labels[0], labels) {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.HostName = "test"
|
||||
met.EnableHostname = true
|
||||
met.SetGauge([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "test" || m.keys[0][1] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.EnableTypePrefix = true
|
||||
met.SetGauge([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "gauge" || m.keys[0][1] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.ServiceName = "service"
|
||||
met.SetGauge([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "service" || m.keys[0][1] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetrics_EmitKey(t *testing.T) {
|
||||
m, met := mockMetric()
|
||||
met.EmitKey([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.EnableTypePrefix = true
|
||||
met.EmitKey([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "kv" || m.keys[0][1] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.ServiceName = "service"
|
||||
met.EmitKey([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "service" || m.keys[0][1] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetrics_IncrCounter(t *testing.T) {
|
||||
m, met := mockMetric()
|
||||
met.IncrCounter([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
labels := []Label{{"a", "b"}}
|
||||
met.IncrCounterWithLabels([]string{"key"}, float32(1), labels)
|
||||
if m.keys[0][0] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if !reflect.DeepEqual(m.labels[0], labels) {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.EnableTypePrefix = true
|
||||
met.IncrCounter([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "counter" || m.keys[0][1] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.ServiceName = "service"
|
||||
met.IncrCounter([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "service" || m.keys[0][1] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetrics_AddSample(t *testing.T) {
|
||||
m, met := mockMetric()
|
||||
met.AddSample([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
labels := []Label{{"a", "b"}}
|
||||
met.AddSampleWithLabels([]string{"key"}, float32(1), labels)
|
||||
if m.keys[0][0] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if !reflect.DeepEqual(m.labels[0], labels) {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.EnableTypePrefix = true
|
||||
met.AddSample([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "sample" || m.keys[0][1] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.ServiceName = "service"
|
||||
met.AddSample([]string{"key"}, float32(1))
|
||||
if m.keys[0][0] != "service" || m.keys[0][1] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetrics_MeasureSince(t *testing.T) {
|
||||
m, met := mockMetric()
|
||||
met.TimerGranularity = time.Millisecond
|
||||
n := time.Now()
|
||||
met.MeasureSince([]string{"key"}, n)
|
||||
if m.keys[0][0] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] > 0.1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.TimerGranularity = time.Millisecond
|
||||
labels := []Label{{"a", "b"}}
|
||||
met.MeasureSinceWithLabels([]string{"key"}, n, labels)
|
||||
if m.keys[0][0] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] > 0.1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if !reflect.DeepEqual(m.labels[0], labels) {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.TimerGranularity = time.Millisecond
|
||||
met.EnableTypePrefix = true
|
||||
met.MeasureSince([]string{"key"}, n)
|
||||
if m.keys[0][0] != "timer" || m.keys[0][1] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] > 0.1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
|
||||
m, met = mockMetric()
|
||||
met.TimerGranularity = time.Millisecond
|
||||
met.ServiceName = "service"
|
||||
met.MeasureSince([]string{"key"}, n)
|
||||
if m.keys[0][0] != "service" || m.keys[0][1] != "key" {
|
||||
t.Fatalf("")
|
||||
}
|
||||
if m.vals[0] > 0.1 {
|
||||
t.Fatalf("")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetrics_EmitRuntimeStats(t *testing.T) {
|
||||
runtime.GC()
|
||||
m, met := mockMetric()
|
||||
met.emitRuntimeStats()
|
||||
|
||||
if m.keys[0][0] != "runtime" || m.keys[0][1] != "num_goroutines" {
|
||||
t.Fatalf("bad key %v", m.keys)
|
||||
}
|
||||
if m.vals[0] <= 1 {
|
||||
t.Fatalf("bad val: %v", m.vals)
|
||||
}
|
||||
|
||||
if m.keys[1][0] != "runtime" || m.keys[1][1] != "alloc_bytes" {
|
||||
t.Fatalf("bad key %v", m.keys)
|
||||
}
|
||||
if m.vals[1] <= 40000 {
|
||||
t.Fatalf("bad val: %v", m.vals)
|
||||
}
|
||||
|
||||
if m.keys[2][0] != "runtime" || m.keys[2][1] != "sys_bytes" {
|
||||
t.Fatalf("bad key %v", m.keys)
|
||||
}
|
||||
if m.vals[2] <= 100000 {
|
||||
t.Fatalf("bad val: %v", m.vals)
|
||||
}
|
||||
|
||||
if m.keys[3][0] != "runtime" || m.keys[3][1] != "malloc_count" {
|
||||
t.Fatalf("bad key %v", m.keys)
|
||||
}
|
||||
if m.vals[3] <= 100 {
|
||||
t.Fatalf("bad val: %v", m.vals)
|
||||
}
|
||||
|
||||
if m.keys[4][0] != "runtime" || m.keys[4][1] != "free_count" {
|
||||
t.Fatalf("bad key %v", m.keys)
|
||||
}
|
||||
if m.vals[4] <= 100 {
|
||||
t.Fatalf("bad val: %v", m.vals)
|
||||
}
|
||||
|
||||
if m.keys[5][0] != "runtime" || m.keys[5][1] != "heap_objects" {
|
||||
t.Fatalf("bad key %v", m.keys)
|
||||
}
|
||||
if m.vals[5] <= 100 {
|
||||
t.Fatalf("bad val: %v", m.vals)
|
||||
}
|
||||
|
||||
if m.keys[6][0] != "runtime" || m.keys[6][1] != "total_gc_pause_ns" {
|
||||
t.Fatalf("bad key %v", m.keys)
|
||||
}
|
||||
if m.vals[6] <= 100000 {
|
||||
t.Fatalf("bad val: %v", m.vals)
|
||||
}
|
||||
|
||||
if m.keys[7][0] != "runtime" || m.keys[7][1] != "total_gc_runs" {
|
||||
t.Fatalf("bad key %v", m.keys)
|
||||
}
|
||||
if m.vals[7] < 1 {
|
||||
t.Fatalf("bad val: %v", m.vals)
|
||||
}
|
||||
|
||||
if m.keys[8][0] != "runtime" || m.keys[8][1] != "gc_pause_ns" {
|
||||
t.Fatalf("bad key %v", m.keys)
|
||||
}
|
||||
if m.vals[8] <= 1000 {
|
||||
t.Fatalf("bad val: %v", m.vals)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsert(t *testing.T) {
|
||||
k := []string{"hi", "bob"}
|
||||
exp := []string{"hi", "there", "bob"}
|
||||
out := insert(1, "there", k)
|
||||
if !reflect.DeepEqual(exp, out) {
|
||||
t.Fatalf("bad insert %v %v", exp, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetrics_Filter_Blacklist(t *testing.T) {
|
||||
m := &MockSink{}
|
||||
conf := DefaultConfig("")
|
||||
conf.AllowedPrefixes = []string{"service", "debug.thing"}
|
||||
conf.BlockedPrefixes = []string{"debug"}
|
||||
conf.EnableHostname = false
|
||||
met, err := New(conf, m)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Allowed by default
|
||||
key := []string{"thing"}
|
||||
met.SetGauge(key, 1)
|
||||
if !reflect.DeepEqual(m.keys[0], key) {
|
||||
t.Fatalf("key doesn't exist %v, %v", m.keys[0], key)
|
||||
}
|
||||
if m.vals[0] != 1 {
|
||||
t.Fatalf("bad val: %v", m.vals[0])
|
||||
}
|
||||
|
||||
// Allowed by filter
|
||||
key = []string{"service", "thing"}
|
||||
met.SetGauge(key, 2)
|
||||
if !reflect.DeepEqual(m.keys[1], key) {
|
||||
t.Fatalf("key doesn't exist")
|
||||
}
|
||||
if m.vals[1] != 2 {
|
||||
t.Fatalf("bad val: %v", m.vals[1])
|
||||
}
|
||||
|
||||
// Allowed by filter, subtree of a blocked entry
|
||||
key = []string{"debug", "thing"}
|
||||
met.SetGauge(key, 3)
|
||||
if !reflect.DeepEqual(m.keys[2], key) {
|
||||
t.Fatalf("key doesn't exist")
|
||||
}
|
||||
if m.vals[2] != 3 {
|
||||
t.Fatalf("bad val: %v", m.vals[2])
|
||||
}
|
||||
|
||||
// Blocked by filter
|
||||
key = []string{"debug", "other-thing"}
|
||||
met.SetGauge(key, 4)
|
||||
if len(m.keys) != 3 {
|
||||
t.Fatalf("key shouldn't exist")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetrics_Filter_Whitelist(t *testing.T) {
|
||||
m := &MockSink{}
|
||||
conf := DefaultConfig("")
|
||||
conf.AllowedPrefixes = []string{"service", "debug.thing"}
|
||||
conf.BlockedPrefixes = []string{"debug"}
|
||||
conf.FilterDefault = false
|
||||
conf.EnableHostname = false
|
||||
met, err := New(conf, m)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Blocked by default
|
||||
key := []string{"thing"}
|
||||
met.SetGauge(key, 1)
|
||||
if len(m.keys) != 0 {
|
||||
t.Fatalf("key should not exist")
|
||||
}
|
||||
|
||||
// Allowed by filter
|
||||
key = []string{"service", "thing"}
|
||||
met.SetGauge(key, 2)
|
||||
if !reflect.DeepEqual(m.keys[0], key) {
|
||||
t.Fatalf("key doesn't exist")
|
||||
}
|
||||
if m.vals[0] != 2 {
|
||||
t.Fatalf("bad val: %v", m.vals[0])
|
||||
}
|
||||
|
||||
// Allowed by filter, subtree of a blocked entry
|
||||
key = []string{"debug", "thing"}
|
||||
met.SetGauge(key, 3)
|
||||
if !reflect.DeepEqual(m.keys[1], key) {
|
||||
t.Fatalf("key doesn't exist")
|
||||
}
|
||||
if m.vals[1] != 3 {
|
||||
t.Fatalf("bad val: %v", m.vals[1])
|
||||
}
|
||||
|
||||
// Blocked by filter
|
||||
key = []string{"debug", "other-thing"}
|
||||
met.SetGauge(key, 4)
|
||||
if len(m.keys) != 2 {
|
||||
t.Fatalf("key shouldn't exist")
|
||||
}
|
||||
}
|
||||
193
vendor/github.com/armon/go-metrics/prometheus/prometheus.go
сгенерированный
поставляемый
193
vendor/github.com/armon/go-metrics/prometheus/prometheus.go
сгенерированный
поставляемый
@@ -1,193 +0,0 @@
|
||||
// +build go1.3
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"regexp"
|
||||
|
||||
"github.com/armon/go-metrics"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultPrometheusOpts is the default set of options used when creating a
|
||||
// PrometheusSink.
|
||||
DefaultPrometheusOpts = PrometheusOpts{
|
||||
Expiration: 60 * time.Second,
|
||||
}
|
||||
)
|
||||
|
||||
// PrometheusOpts is used to configure the Prometheus Sink
|
||||
type PrometheusOpts struct {
|
||||
// Expiration is the duration a metric is valid for, after which it will be
|
||||
// untracked. If the value is zero, a metric is never expired.
|
||||
Expiration time.Duration
|
||||
}
|
||||
|
||||
type PrometheusSink struct {
|
||||
mu sync.Mutex
|
||||
gauges map[string]prometheus.Gauge
|
||||
summaries map[string]prometheus.Summary
|
||||
counters map[string]prometheus.Counter
|
||||
updates map[string]time.Time
|
||||
expiration time.Duration
|
||||
}
|
||||
|
||||
// NewPrometheusSink creates a new PrometheusSink using the default options.
|
||||
func NewPrometheusSink() (*PrometheusSink, error) {
|
||||
return NewPrometheusSinkFrom(DefaultPrometheusOpts)
|
||||
}
|
||||
|
||||
// NewPrometheusSinkFrom creates a new PrometheusSink using the passed options.
|
||||
func NewPrometheusSinkFrom(opts PrometheusOpts) (*PrometheusSink, error) {
|
||||
sink := &PrometheusSink{
|
||||
gauges: make(map[string]prometheus.Gauge),
|
||||
summaries: make(map[string]prometheus.Summary),
|
||||
counters: make(map[string]prometheus.Counter),
|
||||
updates: make(map[string]time.Time),
|
||||
expiration: opts.Expiration,
|
||||
}
|
||||
|
||||
return sink, prometheus.Register(sink)
|
||||
}
|
||||
|
||||
// Describe is needed to meet the Collector interface.
|
||||
func (p *PrometheusSink) Describe(c chan<- *prometheus.Desc) {
|
||||
// We must emit some description otherwise an error is returned. This
|
||||
// description isn't shown to the user!
|
||||
prometheus.NewGauge(prometheus.GaugeOpts{Name: "Dummy", Help: "Dummy"}).Describe(c)
|
||||
}
|
||||
|
||||
// Collect meets the collection interface and allows us to enforce our expiration
|
||||
// logic to clean up ephemeral metrics if their value haven't been set for a
|
||||
// duration exceeding our allowed expiration time.
|
||||
func (p *PrometheusSink) Collect(c chan<- prometheus.Metric) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
expire := p.expiration != 0
|
||||
now := time.Now()
|
||||
for k, v := range p.gauges {
|
||||
last := p.updates[k]
|
||||
if expire && last.Add(p.expiration).Before(now) {
|
||||
delete(p.updates, k)
|
||||
delete(p.gauges, k)
|
||||
} else {
|
||||
v.Collect(c)
|
||||
}
|
||||
}
|
||||
for k, v := range p.summaries {
|
||||
last := p.updates[k]
|
||||
if expire && last.Add(p.expiration).Before(now) {
|
||||
delete(p.updates, k)
|
||||
delete(p.summaries, k)
|
||||
} else {
|
||||
v.Collect(c)
|
||||
}
|
||||
}
|
||||
for k, v := range p.counters {
|
||||
last := p.updates[k]
|
||||
if expire && last.Add(p.expiration).Before(now) {
|
||||
delete(p.updates, k)
|
||||
delete(p.counters, k)
|
||||
} else {
|
||||
v.Collect(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var forbiddenChars = regexp.MustCompile("[ .=\\-]")
|
||||
|
||||
func (p *PrometheusSink) flattenKey(parts []string, labels []metrics.Label) (string, string) {
|
||||
key := strings.Join(parts, "_")
|
||||
key = forbiddenChars.ReplaceAllString(key, "_")
|
||||
|
||||
hash := key
|
||||
for _, label := range labels {
|
||||
hash += fmt.Sprintf(";%s=%s", label.Name, label.Value)
|
||||
}
|
||||
|
||||
return key, hash
|
||||
}
|
||||
|
||||
func prometheusLabels(labels []metrics.Label) prometheus.Labels {
|
||||
l := make(prometheus.Labels)
|
||||
for _, label := range labels {
|
||||
l[label.Name] = label.Value
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func (p *PrometheusSink) SetGauge(parts []string, val float32) {
|
||||
p.SetGaugeWithLabels(parts, val, nil)
|
||||
}
|
||||
|
||||
func (p *PrometheusSink) SetGaugeWithLabels(parts []string, val float32, labels []metrics.Label) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
key, hash := p.flattenKey(parts, labels)
|
||||
g, ok := p.gauges[hash]
|
||||
if !ok {
|
||||
g = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||
Name: key,
|
||||
Help: key,
|
||||
ConstLabels: prometheusLabels(labels),
|
||||
})
|
||||
p.gauges[hash] = g
|
||||
}
|
||||
g.Set(float64(val))
|
||||
p.updates[hash] = time.Now()
|
||||
}
|
||||
|
||||
func (p *PrometheusSink) AddSample(parts []string, val float32) {
|
||||
p.AddSampleWithLabels(parts, val, nil)
|
||||
}
|
||||
|
||||
func (p *PrometheusSink) AddSampleWithLabels(parts []string, val float32, labels []metrics.Label) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
key, hash := p.flattenKey(parts, labels)
|
||||
g, ok := p.summaries[hash]
|
||||
if !ok {
|
||||
g = prometheus.NewSummary(prometheus.SummaryOpts{
|
||||
Name: key,
|
||||
Help: key,
|
||||
MaxAge: 10 * time.Second,
|
||||
ConstLabels: prometheusLabels(labels),
|
||||
})
|
||||
p.summaries[hash] = g
|
||||
}
|
||||
g.Observe(float64(val))
|
||||
p.updates[hash] = time.Now()
|
||||
}
|
||||
|
||||
// EmitKey is not implemented. Prometheus doesn’t offer a type for which an
|
||||
// arbitrary number of values is retained, as Prometheus works with a pull
|
||||
// model, rather than a push model.
|
||||
func (p *PrometheusSink) EmitKey(key []string, val float32) {
|
||||
}
|
||||
|
||||
func (p *PrometheusSink) IncrCounter(parts []string, val float32) {
|
||||
p.IncrCounterWithLabels(parts, val, nil)
|
||||
}
|
||||
|
||||
func (p *PrometheusSink) IncrCounterWithLabels(parts []string, val float32, labels []metrics.Label) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
key, hash := p.flattenKey(parts, labels)
|
||||
g, ok := p.counters[hash]
|
||||
if !ok {
|
||||
g = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: key,
|
||||
Help: key,
|
||||
ConstLabels: prometheusLabels(labels),
|
||||
})
|
||||
p.counters[hash] = g
|
||||
}
|
||||
g.Add(float64(val))
|
||||
p.updates[hash] = time.Now()
|
||||
}
|
||||
272
vendor/github.com/armon/go-metrics/sink_test.go
сгенерированный
поставляемый
272
vendor/github.com/armon/go-metrics/sink_test.go
сгенерированный
поставляемый
@@ -1,272 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type MockSink struct {
|
||||
keys [][]string
|
||||
vals []float32
|
||||
labels [][]Label
|
||||
}
|
||||
|
||||
func (m *MockSink) SetGauge(key []string, val float32) {
|
||||
m.SetGaugeWithLabels(key, val, nil)
|
||||
}
|
||||
func (m *MockSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {
|
||||
m.keys = append(m.keys, key)
|
||||
m.vals = append(m.vals, val)
|
||||
m.labels = append(m.labels, labels)
|
||||
}
|
||||
func (m *MockSink) EmitKey(key []string, val float32) {
|
||||
m.keys = append(m.keys, key)
|
||||
m.vals = append(m.vals, val)
|
||||
m.labels = append(m.labels, nil)
|
||||
}
|
||||
func (m *MockSink) IncrCounter(key []string, val float32) {
|
||||
m.IncrCounterWithLabels(key, val, nil)
|
||||
}
|
||||
func (m *MockSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {
|
||||
m.keys = append(m.keys, key)
|
||||
m.vals = append(m.vals, val)
|
||||
m.labels = append(m.labels, labels)
|
||||
}
|
||||
func (m *MockSink) AddSample(key []string, val float32) {
|
||||
m.AddSampleWithLabels(key, val, nil)
|
||||
}
|
||||
func (m *MockSink) AddSampleWithLabels(key []string, val float32, labels []Label) {
|
||||
m.keys = append(m.keys, key)
|
||||
m.vals = append(m.vals, val)
|
||||
m.labels = append(m.labels, labels)
|
||||
}
|
||||
|
||||
func TestFanoutSink_Gauge(t *testing.T) {
|
||||
m1 := &MockSink{}
|
||||
m2 := &MockSink{}
|
||||
fh := &FanoutSink{m1, m2}
|
||||
|
||||
k := []string{"test"}
|
||||
v := float32(42.0)
|
||||
fh.SetGauge(k, v)
|
||||
|
||||
if !reflect.DeepEqual(m1.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m1.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFanoutSink_Gauge_Labels(t *testing.T) {
|
||||
m1 := &MockSink{}
|
||||
m2 := &MockSink{}
|
||||
fh := &FanoutSink{m1, m2}
|
||||
|
||||
k := []string{"test"}
|
||||
v := float32(42.0)
|
||||
l := []Label{{"a", "b"}}
|
||||
fh.SetGaugeWithLabels(k, v, l)
|
||||
|
||||
if !reflect.DeepEqual(m1.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m1.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m1.labels[0], l) {
|
||||
t.Fatalf("labels not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.labels[0], l) {
|
||||
t.Fatalf("labels not equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFanoutSink_Key(t *testing.T) {
|
||||
m1 := &MockSink{}
|
||||
m2 := &MockSink{}
|
||||
fh := &FanoutSink{m1, m2}
|
||||
|
||||
k := []string{"test"}
|
||||
v := float32(42.0)
|
||||
fh.EmitKey(k, v)
|
||||
|
||||
if !reflect.DeepEqual(m1.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m1.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFanoutSink_Counter(t *testing.T) {
|
||||
m1 := &MockSink{}
|
||||
m2 := &MockSink{}
|
||||
fh := &FanoutSink{m1, m2}
|
||||
|
||||
k := []string{"test"}
|
||||
v := float32(42.0)
|
||||
fh.IncrCounter(k, v)
|
||||
|
||||
if !reflect.DeepEqual(m1.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m1.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFanoutSink_Counter_Labels(t *testing.T) {
|
||||
m1 := &MockSink{}
|
||||
m2 := &MockSink{}
|
||||
fh := &FanoutSink{m1, m2}
|
||||
|
||||
k := []string{"test"}
|
||||
v := float32(42.0)
|
||||
l := []Label{{"a", "b"}}
|
||||
fh.IncrCounterWithLabels(k, v, l)
|
||||
|
||||
if !reflect.DeepEqual(m1.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m1.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m1.labels[0], l) {
|
||||
t.Fatalf("labels not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.labels[0], l) {
|
||||
t.Fatalf("labels not equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFanoutSink_Sample(t *testing.T) {
|
||||
m1 := &MockSink{}
|
||||
m2 := &MockSink{}
|
||||
fh := &FanoutSink{m1, m2}
|
||||
|
||||
k := []string{"test"}
|
||||
v := float32(42.0)
|
||||
fh.AddSample(k, v)
|
||||
|
||||
if !reflect.DeepEqual(m1.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m1.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFanoutSink_Sample_Labels(t *testing.T) {
|
||||
m1 := &MockSink{}
|
||||
m2 := &MockSink{}
|
||||
fh := &FanoutSink{m1, m2}
|
||||
|
||||
k := []string{"test"}
|
||||
v := float32(42.0)
|
||||
l := []Label{{"a", "b"}}
|
||||
fh.AddSampleWithLabels(k, v, l)
|
||||
|
||||
if !reflect.DeepEqual(m1.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m1.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.vals[0], v) {
|
||||
t.Fatalf("val not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m1.labels[0], l) {
|
||||
t.Fatalf("labels not equal")
|
||||
}
|
||||
if !reflect.DeepEqual(m2.labels[0], l) {
|
||||
t.Fatalf("labels not equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewMetricSinkFromURL(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
desc string
|
||||
input string
|
||||
expect reflect.Type
|
||||
expectErr string
|
||||
}{
|
||||
{
|
||||
desc: "statsd scheme yields a StatsdSink",
|
||||
input: "statsd://someserver:123",
|
||||
expect: reflect.TypeOf(&StatsdSink{}),
|
||||
},
|
||||
{
|
||||
desc: "statsite scheme yields a StatsiteSink",
|
||||
input: "statsite://someserver:123",
|
||||
expect: reflect.TypeOf(&StatsiteSink{}),
|
||||
},
|
||||
{
|
||||
desc: "inmem scheme yields an InmemSink",
|
||||
input: "inmem://?interval=30s&retain=30s",
|
||||
expect: reflect.TypeOf(&InmemSink{}),
|
||||
},
|
||||
{
|
||||
desc: "unknown scheme yields an error",
|
||||
input: "notasink://whatever",
|
||||
expectErr: "unrecognized sink name: \"notasink\"",
|
||||
},
|
||||
} {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
ms, err := NewMetricSinkFromURL(tc.input)
|
||||
if tc.expectErr != "" {
|
||||
if !strings.Contains(err.Error(), tc.expectErr) {
|
||||
t.Fatalf("expected err: %q to contain: %q", err, tc.expectErr)
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %s", err)
|
||||
}
|
||||
got := reflect.TypeOf(ms)
|
||||
if got != tc.expect {
|
||||
t.Fatalf("expected return type to be %v, got: %v", tc.expect, got)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
202
vendor/github.com/armon/go-metrics/start_test.go
сгенерированный
поставляемый
202
vendor/github.com/armon/go-metrics/start_test.go
сгенерированный
поставляемый
@@ -1,202 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDefaultConfig(t *testing.T) {
|
||||
conf := DefaultConfig("service")
|
||||
if conf.ServiceName != "service" {
|
||||
t.Fatalf("Bad name")
|
||||
}
|
||||
if conf.HostName == "" {
|
||||
t.Fatalf("missing hostname")
|
||||
}
|
||||
if !conf.EnableHostname || !conf.EnableRuntimeMetrics {
|
||||
t.Fatalf("expect true")
|
||||
}
|
||||
if conf.EnableTypePrefix {
|
||||
t.Fatalf("expect false")
|
||||
}
|
||||
if conf.TimerGranularity != time.Millisecond {
|
||||
t.Fatalf("bad granularity")
|
||||
}
|
||||
if conf.ProfileInterval != time.Second {
|
||||
t.Fatalf("bad interval")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GlobalMetrics(t *testing.T) {
|
||||
var tests = []struct {
|
||||
desc string
|
||||
key []string
|
||||
val float32
|
||||
fn func([]string, float32)
|
||||
}{
|
||||
{"SetGauge", []string{"test"}, 42, SetGauge},
|
||||
{"EmitKey", []string{"test"}, 42, EmitKey},
|
||||
{"IncrCounter", []string{"test"}, 42, IncrCounter},
|
||||
{"AddSample", []string{"test"}, 42, AddSample},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
s := &MockSink{}
|
||||
globalMetrics.Store(&Metrics{Config: Config{FilterDefault: true}, sink: s})
|
||||
tt.fn(tt.key, tt.val)
|
||||
if got, want := s.keys[0], tt.key; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got key %s want %s", got, want)
|
||||
}
|
||||
if got, want := s.vals[0], tt.val; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got val %s want %s", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GlobalMetrics_Labels(t *testing.T) {
|
||||
labels := []Label{{"a", "b"}}
|
||||
var tests = []struct {
|
||||
desc string
|
||||
key []string
|
||||
val float32
|
||||
fn func([]string, float32, []Label)
|
||||
labels []Label
|
||||
}{
|
||||
{"SetGaugeWithLabels", []string{"test"}, 42, SetGaugeWithLabels, labels},
|
||||
{"IncrCounterWithLabels", []string{"test"}, 42, IncrCounterWithLabels, labels},
|
||||
{"AddSampleWithLabels", []string{"test"}, 42, AddSampleWithLabels, labels},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
s := &MockSink{}
|
||||
globalMetrics.Store(&Metrics{Config: Config{FilterDefault: true}, sink: s})
|
||||
tt.fn(tt.key, tt.val, tt.labels)
|
||||
if got, want := s.keys[0], tt.key; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got key %s want %s", got, want)
|
||||
}
|
||||
if got, want := s.vals[0], tt.val; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got val %s want %s", got, want)
|
||||
}
|
||||
if got, want := s.labels[0], tt.labels; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got val %s want %s", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GlobalMetrics_DefaultLabels(t *testing.T) {
|
||||
config := Config{
|
||||
HostName: "host1",
|
||||
ServiceName: "redis",
|
||||
EnableHostnameLabel: true,
|
||||
EnableServiceLabel: true,
|
||||
FilterDefault: true,
|
||||
}
|
||||
labels := []Label{
|
||||
{"host", config.HostName},
|
||||
{"service", config.ServiceName},
|
||||
}
|
||||
var tests = []struct {
|
||||
desc string
|
||||
key []string
|
||||
val float32
|
||||
fn func([]string, float32, []Label)
|
||||
labels []Label
|
||||
}{
|
||||
{"SetGaugeWithLabels", []string{"test"}, 42, SetGaugeWithLabels, labels},
|
||||
{"IncrCounterWithLabels", []string{"test"}, 42, IncrCounterWithLabels, labels},
|
||||
{"AddSampleWithLabels", []string{"test"}, 42, AddSampleWithLabels, labels},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
s := &MockSink{}
|
||||
globalMetrics.Store(&Metrics{Config: config, sink: s})
|
||||
tt.fn(tt.key, tt.val, nil)
|
||||
if got, want := s.keys[0], tt.key; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got key %s want %s", got, want)
|
||||
}
|
||||
if got, want := s.vals[0], tt.val; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got val %s want %s", got, want)
|
||||
}
|
||||
if got, want := s.labels[0], tt.labels; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got val %s want %s", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GlobalMetrics_MeasureSince(t *testing.T) {
|
||||
s := &MockSink{}
|
||||
m := &Metrics{sink: s, Config: Config{TimerGranularity: time.Millisecond, FilterDefault: true}}
|
||||
globalMetrics.Store(m)
|
||||
|
||||
k := []string{"test"}
|
||||
now := time.Now()
|
||||
MeasureSince(k, now)
|
||||
|
||||
if !reflect.DeepEqual(s.keys[0], k) {
|
||||
t.Fatalf("key not equal")
|
||||
}
|
||||
if s.vals[0] > 0.1 {
|
||||
t.Fatalf("val too large %v", s.vals[0])
|
||||
}
|
||||
|
||||
labels := []Label{{"a", "b"}}
|
||||
MeasureSinceWithLabels(k, now, labels)
|
||||
if got, want := s.keys[1], k; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got key %s want %s", got, want)
|
||||
}
|
||||
if s.vals[1] > 0.1 {
|
||||
t.Fatalf("val too large %v", s.vals[0])
|
||||
}
|
||||
if got, want := s.labels[1], labels; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("got val %s want %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GlobalMetrics_UpdateFilter(t *testing.T) {
|
||||
globalMetrics.Store(&Metrics{Config: Config{
|
||||
AllowedPrefixes: []string{"a"},
|
||||
BlockedPrefixes: []string{"b"},
|
||||
}})
|
||||
UpdateFilter([]string{"c"}, []string{"d"})
|
||||
|
||||
m := globalMetrics.Load().(*Metrics)
|
||||
if m.AllowedPrefixes[0] != "c" {
|
||||
t.Fatalf("bad: %v", m.AllowedPrefixes)
|
||||
}
|
||||
if m.BlockedPrefixes[0] != "d" {
|
||||
t.Fatalf("bad: %v", m.BlockedPrefixes)
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmark_GlobalMetrics_Direct/direct-8 5000000 278 ns/op
|
||||
// Benchmark_GlobalMetrics_Direct/atomic.Value-8 5000000 235 ns/op
|
||||
func Benchmark_GlobalMetrics_Direct(b *testing.B) {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
s := &MockSink{}
|
||||
m := &Metrics{sink: s}
|
||||
var v atomic.Value
|
||||
v.Store(m)
|
||||
k := []string{"test"}
|
||||
b.Run("direct", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.IncrCounter(k, 1)
|
||||
}
|
||||
})
|
||||
b.Run("atomic.Value", func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
v.Load().(*Metrics).IncrCounter(k, 1)
|
||||
}
|
||||
})
|
||||
// do something with m so that the compiler does not optimize this away
|
||||
b.Logf("%d", m.lastNumGC)
|
||||
}
|
||||
175
vendor/github.com/armon/go-metrics/statsd_test.go
сгенерированный
поставляемый
175
vendor/github.com/armon/go-metrics/statsd_test.go
сгенерированный
поставляемый
@@ -1,175 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestStatsd_Flatten(t *testing.T) {
|
||||
s := &StatsdSink{}
|
||||
flat := s.flattenKey([]string{"a", "b", "c", "d"})
|
||||
if flat != "a.b.c.d" {
|
||||
t.Fatalf("Bad flat")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsd_PushFullQueue(t *testing.T) {
|
||||
q := make(chan string, 1)
|
||||
q <- "full"
|
||||
|
||||
s := &StatsdSink{metricQueue: q}
|
||||
s.pushMetric("omit")
|
||||
|
||||
out := <-q
|
||||
if out != "full" {
|
||||
t.Fatalf("bad val %v", out)
|
||||
}
|
||||
|
||||
select {
|
||||
case v := <-q:
|
||||
t.Fatalf("bad val %v", v)
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsd_Conn(t *testing.T) {
|
||||
addr := "127.0.0.1:7524"
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
list, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 7524})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer list.Close()
|
||||
buf := make([]byte, 1500)
|
||||
n, err := list.Read(buf)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
buf = buf[:n]
|
||||
reader := bufio.NewReader(bytes.NewReader(buf))
|
||||
|
||||
line, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "gauge.val:1.000000|g\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "gauge_labels.val.label:2.000000|g\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "key.other:3.000000|kv\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "counter.me:4.000000|c\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "counter_labels.me.label:5.000000|c\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "sample.slow_thingy:6.000000|ms\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "sample_labels.slow_thingy.label:7.000000|ms\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
done <- true
|
||||
}()
|
||||
s, err := NewStatsdSink(addr)
|
||||
if err != nil {
|
||||
t.Fatalf("bad error")
|
||||
}
|
||||
|
||||
s.SetGauge([]string{"gauge", "val"}, float32(1))
|
||||
s.SetGaugeWithLabels([]string{"gauge_labels", "val"}, float32(2), []Label{{"a", "label"}})
|
||||
s.EmitKey([]string{"key", "other"}, float32(3))
|
||||
s.IncrCounter([]string{"counter", "me"}, float32(4))
|
||||
s.IncrCounterWithLabels([]string{"counter_labels", "me"}, float32(5), []Label{{"a", "label"}})
|
||||
s.AddSample([]string{"sample", "slow thingy"}, float32(6))
|
||||
s.AddSampleWithLabels([]string{"sample_labels", "slow thingy"}, float32(7), []Label{{"a", "label"}})
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
s.Shutdown()
|
||||
case <-time.After(3 * time.Second):
|
||||
t.Fatalf("timeout")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewStatsdSinkFromURL(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
desc string
|
||||
input string
|
||||
expectErr string
|
||||
expectAddr string
|
||||
}{
|
||||
{
|
||||
desc: "address is populated",
|
||||
input: "statsd://statsd.service.consul",
|
||||
expectAddr: "statsd.service.consul",
|
||||
},
|
||||
{
|
||||
desc: "address includes port",
|
||||
input: "statsd://statsd.service.consul:1234",
|
||||
expectAddr: "statsd.service.consul:1234",
|
||||
},
|
||||
} {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
u, err := url.Parse(tc.input)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing URL: %s", err)
|
||||
}
|
||||
ms, err := NewStatsdSinkFromURL(u)
|
||||
if tc.expectErr != "" {
|
||||
if !strings.Contains(err.Error(), tc.expectErr) {
|
||||
t.Fatalf("expected err: %q, to contain: %q", err, tc.expectErr)
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %s", err)
|
||||
}
|
||||
is := ms.(*StatsdSink)
|
||||
if is.addr != tc.expectAddr {
|
||||
t.Fatalf("expected addr %s, got: %s", tc.expectAddr, is.addr)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
171
vendor/github.com/armon/go-metrics/statsite_test.go
сгенерированный
поставляемый
171
vendor/github.com/armon/go-metrics/statsite_test.go
сгенерированный
поставляемый
@@ -1,171 +0,0 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func acceptConn(addr string) net.Conn {
|
||||
ln, _ := net.Listen("tcp", addr)
|
||||
conn, _ := ln.Accept()
|
||||
return conn
|
||||
}
|
||||
|
||||
func TestStatsite_Flatten(t *testing.T) {
|
||||
s := &StatsiteSink{}
|
||||
flat := s.flattenKey([]string{"a", "b", "c", "d"})
|
||||
if flat != "a.b.c.d" {
|
||||
t.Fatalf("Bad flat")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsite_PushFullQueue(t *testing.T) {
|
||||
q := make(chan string, 1)
|
||||
q <- "full"
|
||||
|
||||
s := &StatsiteSink{metricQueue: q}
|
||||
s.pushMetric("omit")
|
||||
|
||||
out := <-q
|
||||
if out != "full" {
|
||||
t.Fatalf("bad val %v", out)
|
||||
}
|
||||
|
||||
select {
|
||||
case v := <-q:
|
||||
t.Fatalf("bad val %v", v)
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsite_Conn(t *testing.T) {
|
||||
addr := "localhost:7523"
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
conn := acceptConn(addr)
|
||||
reader := bufio.NewReader(conn)
|
||||
|
||||
line, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "gauge.val:1.000000|g\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "gauge_labels.val.label:2.000000|g\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "key.other:3.000000|kv\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "counter.me:4.000000|c\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "counter_labels.me.label:5.000000|c\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "sample.slow_thingy:6.000000|ms\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
line, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err %s", err)
|
||||
}
|
||||
if line != "sample_labels.slow_thingy.label:7.000000|ms\n" {
|
||||
t.Fatalf("bad line %s", line)
|
||||
}
|
||||
|
||||
conn.Close()
|
||||
done <- true
|
||||
}()
|
||||
s, err := NewStatsiteSink(addr)
|
||||
if err != nil {
|
||||
t.Fatalf("bad error")
|
||||
}
|
||||
|
||||
s.SetGauge([]string{"gauge", "val"}, float32(1))
|
||||
s.SetGaugeWithLabels([]string{"gauge_labels", "val"}, float32(2), []Label{{"a", "label"}})
|
||||
s.EmitKey([]string{"key", "other"}, float32(3))
|
||||
s.IncrCounter([]string{"counter", "me"}, float32(4))
|
||||
s.IncrCounterWithLabels([]string{"counter_labels", "me"}, float32(5), []Label{{"a", "label"}})
|
||||
s.AddSample([]string{"sample", "slow thingy"}, float32(6))
|
||||
s.AddSampleWithLabels([]string{"sample_labels", "slow thingy"}, float32(7), []Label{{"a", "label"}})
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
s.Shutdown()
|
||||
case <-time.After(3 * time.Second):
|
||||
t.Fatalf("timeout")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewStatsiteSinkFromURL(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
desc string
|
||||
input string
|
||||
expectErr string
|
||||
expectAddr string
|
||||
}{
|
||||
{
|
||||
desc: "address is populated",
|
||||
input: "statsd://statsd.service.consul",
|
||||
expectAddr: "statsd.service.consul",
|
||||
},
|
||||
{
|
||||
desc: "address includes port",
|
||||
input: "statsd://statsd.service.consul:1234",
|
||||
expectAddr: "statsd.service.consul:1234",
|
||||
},
|
||||
} {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
u, err := url.Parse(tc.input)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing URL: %s", err)
|
||||
}
|
||||
ms, err := NewStatsiteSinkFromURL(u)
|
||||
if tc.expectErr != "" {
|
||||
if !strings.Contains(err.Error(), tc.expectErr) {
|
||||
t.Fatalf("expected err: %q, to contain: %q", err, tc.expectErr)
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %s", err)
|
||||
}
|
||||
is := ms.(*StatsiteSink)
|
||||
if is.addr != tc.expectAddr {
|
||||
t.Fatalf("expected addr %s, got: %s", tc.expectAddr, is.addr)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Ссылка в новой задаче
Block a user