summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/armon/go-metrics/circonus
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2017-05-17 16:51:25 -0400
committerGitHub <noreply@github.com>2017-05-17 16:51:25 -0400
commitd103ed6ca97ca5a2669f6cf5fe4b3d2a9c945f26 (patch)
treedbde13123c6add150448f7b75753ac022d862475 /vendor/github.com/armon/go-metrics/circonus
parentcd23b8139a9463b67e3096744321f6f4eb0ca40a (diff)
downloadchat-d103ed6ca97ca5a2669f6cf5fe4b3d2a9c945f26.tar.gz
chat-d103ed6ca97ca5a2669f6cf5fe4b3d2a9c945f26.tar.bz2
chat-d103ed6ca97ca5a2669f6cf5fe4b3d2a9c945f26.zip
Upgrading server dependancies (#6431)
Diffstat (limited to 'vendor/github.com/armon/go-metrics/circonus')
-rw-r--r--vendor/github.com/armon/go-metrics/circonus/circonus.go92
-rw-r--r--vendor/github.com/armon/go-metrics/circonus/circonus_test.go153
2 files changed, 245 insertions, 0 deletions
diff --git a/vendor/github.com/armon/go-metrics/circonus/circonus.go b/vendor/github.com/armon/go-metrics/circonus/circonus.go
new file mode 100644
index 000000000..c6e3974b5
--- /dev/null
+++ b/vendor/github.com/armon/go-metrics/circonus/circonus.go
@@ -0,0 +1,92 @@
+// Circonus Metrics Sink
+
+package circonus
+
+import (
+ "strings"
+
+ 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))
+}
+
+// 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))
+}
+
+// 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))
+}
+
+// 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)
+}
diff --git a/vendor/github.com/armon/go-metrics/circonus/circonus_test.go b/vendor/github.com/armon/go-metrics/circonus/circonus_test.go
new file mode 100644
index 000000000..234a3cb89
--- /dev/null
+++ b/vendor/github.com/armon/go-metrics/circonus/circonus_test.go
@@ -0,0 +1,153 @@
+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)
+
+ }
+}