| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- package graphitebridge
- import (
- "bufio"
- "bytes"
- "io"
- "net"
- "regexp"
- "testing"
- "time"
- "github.com/prometheus/client_golang/prometheus"
- dto "github.com/prometheus/client_model/go"
- "github.com/prometheus/common/model"
- )
- func TestCountersAsDelta(t *testing.T) {
- b, _ := NewBridge(&Config{
- URL: "localhost:12345",
- CountersAsDelta: true,
- })
- ty := dto.MetricType(0)
- mf := &dto.MetricFamily{
- Type: &ty,
- Metric: []*dto.Metric{},
- }
- m := model.Metric{}
- var want float64
- var got float64
- want = float64(1)
- got = b.replaceCounterWithDelta(mf, m, model.SampleValue(1))
- if got != want {
- t.Fatalf("want %v got %v", want, got)
- }
- got = b.replaceCounterWithDelta(mf, m, model.SampleValue(2))
- if got != want {
- t.Fatalf("want %v got %v", want, got)
- }
- }
- func TestCountersAsDeltaDisabled(t *testing.T) {
- b, _ := NewBridge(&Config{
- URL: "localhost:12345",
- CountersAsDelta: false,
- })
- ty := dto.MetricType(0)
- mf := &dto.MetricFamily{
- Type: &ty,
- Metric: []*dto.Metric{},
- }
- m := model.Metric{}
- var want float64
- var got float64
- want = float64(1)
- got = b.replaceCounterWithDelta(mf, m, model.SampleValue(1))
- if got != want {
- t.Fatalf("want %v got %v", want, got)
- }
- want = float64(2)
- got = b.replaceCounterWithDelta(mf, m, model.SampleValue(2))
- if got != want {
- t.Fatalf("want %v got %v", want, got)
- }
- }
- func TestSanitize(t *testing.T) {
- testCases := []struct {
- in, out string
- }{
- {in: "hello", out: "hello"},
- {in: "hE/l1o", out: "hE_l1o"},
- {in: "he,*ll(.o", out: "he_ll_o"},
- {in: "hello_there%^&", out: "hello_there_"},
- }
- var buf bytes.Buffer
- w := bufio.NewWriter(&buf)
- for i, tc := range testCases {
- if err := writeSanitized(w, tc.in); err != nil {
- t.Fatalf("write failed: %v", err)
- }
- if err := w.Flush(); err != nil {
- t.Fatalf("flush failed: %v", err)
- }
- if want, got := tc.out, buf.String(); want != got {
- t.Fatalf("test case index %d: got sanitized string %s, want %s", i, got, want)
- }
- buf.Reset()
- }
- }
- func TestSanitizePrefix(t *testing.T) {
- testCases := []struct {
- in, out string
- }{
- {in: "service.prod.", out: "service.prod."},
- {in: "service.prod", out: "service.prod"},
- }
- var buf bytes.Buffer
- w := bufio.NewWriter(&buf)
- for i, tc := range testCases {
- if err := writePrefix(w, tc.in); err != nil {
- t.Fatalf("write failed: %v", err)
- }
- if err := w.Flush(); err != nil {
- t.Fatalf("flush failed: %v", err)
- }
- if want, got := tc.out, buf.String(); want != got {
- t.Fatalf("test case index %d: got sanitized string %s, want %s", i, got, want)
- }
- buf.Reset()
- }
- }
- func TestWriteSummary(t *testing.T) {
- sumVec := prometheus.NewSummaryVec(
- prometheus.SummaryOpts{
- Name: "name",
- Help: "docstring",
- ConstLabels: prometheus.Labels{"constname": "constvalue"},
- Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
- },
- []string{"labelname"},
- )
- reg := prometheus.NewRegistry()
- reg.MustRegister(sumVec)
- b, err := NewBridge(&Config{
- URL: "localhost:8080",
- Gatherer: reg,
- CountersAsDelta: true,
- })
- if err != nil {
- t.Fatalf("cannot create bridge. err: %v", err)
- }
- sumVec.WithLabelValues("val1").Observe(float64(10))
- sumVec.WithLabelValues("val1").Observe(float64(20))
- sumVec.WithLabelValues("val1").Observe(float64(30))
- sumVec.WithLabelValues("val2").Observe(float64(20))
- sumVec.WithLabelValues("val2").Observe(float64(30))
- sumVec.WithLabelValues("val2").Observe(float64(40))
- mfs, err := reg.Gather()
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- now := model.Time(1477043083)
- var buf bytes.Buffer
- err = b.writeMetrics(&buf, mfs, "prefix.", now)
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- want := `prefix.name.constname.constvalue.labelname.val1.quantile.0_5 20 1477043
- prefix.name.constname.constvalue.labelname.val1.quantile.0_9 30 1477043
- prefix.name.constname.constvalue.labelname.val1.quantile.0_99 30 1477043
- prefix.name_sum.constname.constvalue.labelname.val1 60 1477043
- prefix.name_count.constname.constvalue.labelname.val1.count 3 1477043
- prefix.name.constname.constvalue.labelname.val2.quantile.0_5 30 1477043
- prefix.name.constname.constvalue.labelname.val2.quantile.0_9 40 1477043
- prefix.name.constname.constvalue.labelname.val2.quantile.0_99 40 1477043
- prefix.name_sum.constname.constvalue.labelname.val2 90 1477043
- prefix.name_count.constname.constvalue.labelname.val2.count 3 1477043
- `
- if got := buf.String(); want != got {
- t.Fatalf("wanted \n%s\n, got \n%s\n", want, got)
- }
- }
- func TestWriteHistogram(t *testing.T) {
- histVec := prometheus.NewHistogramVec(
- prometheus.HistogramOpts{
- Name: "name",
- Help: "docstring",
- ConstLabels: prometheus.Labels{"constname": "constvalue"},
- Buckets: []float64{0.01, 0.02, 0.05, 0.1},
- },
- []string{"labelname"},
- )
- reg := prometheus.NewRegistry()
- reg.MustRegister(histVec)
- b, err := NewBridge(&Config{
- URL: "localhost:8080",
- Gatherer: reg,
- CountersAsDelta: true,
- })
- if err != nil {
- t.Fatalf("error creating bridge: %v", err)
- }
- histVec.WithLabelValues("val1").Observe(float64(10))
- histVec.WithLabelValues("val1").Observe(float64(20))
- histVec.WithLabelValues("val1").Observe(float64(30))
- histVec.WithLabelValues("val2").Observe(float64(20))
- histVec.WithLabelValues("val2").Observe(float64(30))
- histVec.WithLabelValues("val2").Observe(float64(40))
- mfs, err := reg.Gather()
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- now := model.Time(1477043083)
- var buf bytes.Buffer
- err = b.writeMetrics(&buf, mfs, "prefix.", now)
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- want := `prefix.name_bucket.constname.constvalue.labelname.val1.le.0_01 0 1477043
- prefix.name_bucket.constname.constvalue.labelname.val1.le.0_02 0 1477043
- prefix.name_bucket.constname.constvalue.labelname.val1.le.0_05 0 1477043
- prefix.name_bucket.constname.constvalue.labelname.val1.le.0_1 0 1477043
- prefix.name_sum.constname.constvalue.labelname.val1.sum 60 1477043
- prefix.name_count.constname.constvalue.labelname.val1.count 3 1477043
- prefix.name_bucket.constname.constvalue.labelname.val1.le._Inf 3 1477043
- prefix.name_bucket.constname.constvalue.labelname.val2.le.0_01 0 1477043
- prefix.name_bucket.constname.constvalue.labelname.val2.le.0_02 0 1477043
- prefix.name_bucket.constname.constvalue.labelname.val2.le.0_05 0 1477043
- prefix.name_bucket.constname.constvalue.labelname.val2.le.0_1 0 1477043
- prefix.name_sum.constname.constvalue.labelname.val2.sum 90 1477043
- prefix.name_count.constname.constvalue.labelname.val2.count 3 1477043
- prefix.name_bucket.constname.constvalue.labelname.val2.le._Inf 3 1477043
- `
- if got := buf.String(); want != got {
- t.Fatalf("wanted \n%s\n, got \n%s\n", want, got)
- }
- }
- func TestCounterVec(t *testing.T) {
- cntVec := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "page_response",
- Help: "docstring",
- ConstLabels: prometheus.Labels{"constname": "constvalue"},
- },
- []string{"labelname"},
- )
- reg := prometheus.NewRegistry()
- reg.MustRegister(cntVec)
- cntVec.WithLabelValues("val1").Inc()
- cntVec.WithLabelValues("val2").Inc()
- b, err := NewBridge(&Config{
- URL: "localhost:8080",
- Gatherer: reg,
- CountersAsDelta: true,
- })
- if err != nil {
- t.Fatalf("error creating bridge: %v", err)
- }
- // first collect
- mfs, err := reg.Gather()
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- var buf bytes.Buffer
- err = b.writeMetrics(&buf, mfs, "prefix.", model.Time(1477043083))
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- want := `prefix.page.response.constname.constvalue.labelname.val1.count 1 1477043
- prefix.page.response.constname.constvalue.labelname.val2.count 1 1477043
- `
- if got := buf.String(); want != got {
- t.Fatalf("wanted \n%s\n, got \n%s\n", want, got)
- }
- //next collect
- cntVec.WithLabelValues("val1").Inc()
- cntVec.WithLabelValues("val2").Inc()
- mfs, err = reg.Gather()
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- buf = bytes.Buffer{}
- err = b.writeMetrics(&buf, mfs, "prefix.", model.Time(1477053083))
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- want2 := `prefix.page.response.constname.constvalue.labelname.val1.count 1 1477053
- prefix.page.response.constname.constvalue.labelname.val2.count 1 1477053
- `
- if got := buf.String(); want2 != got {
- t.Fatalf("wanted \n%s\n, got \n%s\n", want2, got)
- }
- }
- func TestCounter(t *testing.T) {
- cntVec := prometheus.NewCounter(
- prometheus.CounterOpts{
- Name: "page_response",
- Help: "docstring",
- ConstLabels: prometheus.Labels{"constname": "constvalue"},
- })
- reg := prometheus.NewRegistry()
- reg.MustRegister(cntVec)
- cntVec.Inc()
- b, err := NewBridge(&Config{
- URL: "localhost:8080",
- Gatherer: reg,
- CountersAsDelta: true,
- })
- if err != nil {
- t.Fatalf("error creating bridge: %v", err)
- }
- // first collect
- mfs, err := reg.Gather()
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- var buf bytes.Buffer
- err = b.writeMetrics(&buf, mfs, "prefix.", model.Time(1477043083))
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- want := "prefix.page.response.constname.constvalue.count 1 1477043\n"
- if got := buf.String(); want != got {
- t.Fatalf("wanted \n%s\n, got \n%s\n", want, got)
- }
- //next collect
- cntVec.Inc()
- mfs, err = reg.Gather()
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- buf = bytes.Buffer{}
- err = b.writeMetrics(&buf, mfs, "prefix.", model.Time(1477053083))
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- want2 := "prefix.page.response.constname.constvalue.count 1 1477053\n"
- if got := buf.String(); want2 != got {
- t.Fatalf("wanted \n%s\n, got \n%s\n", want2, got)
- }
- }
- func TestTrimGrafanaNamespace(t *testing.T) {
- cntVec := prometheus.NewCounter(
- prometheus.CounterOpts{
- Name: "grafana_http_request_total",
- Help: "docstring",
- ConstLabels: prometheus.Labels{"constname": "constvalue"},
- })
- reg := prometheus.NewRegistry()
- reg.MustRegister(cntVec)
- cntVec.Inc()
- b, err := NewBridge(&Config{
- URL: "localhost:8080",
- Gatherer: reg,
- CountersAsDelta: true,
- })
- if err != nil {
- t.Fatalf("error creating bridge: %v", err)
- }
- // first collect
- mfs, err := reg.Gather()
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- var buf bytes.Buffer
- err = b.writeMetrics(&buf, mfs, "prefix.", model.Time(1477043083))
- if err != nil {
- t.Fatalf("error: %v", err)
- }
- want := "prefix.http_request_total.constname.constvalue.count 1 1477043\n"
- if got := buf.String(); want != got {
- t.Fatalf("wanted \n%s\n, got \n%s\n", want, got)
- }
- }
- func TestPush(t *testing.T) {
- reg := prometheus.NewRegistry()
- cntVec := prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "name",
- Help: "docstring",
- ConstLabels: prometheus.Labels{"constname": "constvalue"},
- },
- []string{"labelname"},
- )
- cntVec.WithLabelValues("val1").Inc()
- cntVec.WithLabelValues("val2").Inc()
- reg.MustRegister(cntVec)
- host := "localhost"
- port := ":56789"
- b, err := NewBridge(&Config{
- URL: host + port,
- Gatherer: reg,
- Prefix: "prefix.",
- })
- if err != nil {
- t.Fatalf("error creating bridge: %v", err)
- }
- nmg, err := newMockGraphite(port)
- if err != nil {
- t.Fatalf("error creating mock graphite: %v", err)
- }
- defer nmg.Close()
- err = b.Push()
- if err != nil {
- t.Fatalf("error pushing: %v", err)
- }
- wants := []string{
- "prefix.name.constname.constvalue.labelname.val1.count 1",
- "prefix.name.constname.constvalue.labelname.val2.count 1",
- }
- select {
- case got := <-nmg.readc:
- for _, want := range wants {
- matched, err := regexp.MatchString(want, got)
- if err != nil {
- t.Fatalf("error pushing: %v", err)
- }
- if !matched {
- t.Fatalf("missing metric:\nno match for %s received by server:\n%s", want, got)
- }
- }
- return
- case err := <-nmg.errc:
- t.Fatalf("error reading push: %v", err)
- case <-time.After(50 * time.Millisecond):
- t.Fatalf("no result from graphite server")
- }
- }
- func newMockGraphite(port string) (*mockGraphite, error) {
- readc := make(chan string)
- errc := make(chan error)
- ln, err := net.Listen("tcp", port)
- if err != nil {
- return nil, err
- }
- go func() {
- conn, err := ln.Accept()
- if err != nil {
- errc <- err
- }
- var b bytes.Buffer
- io.Copy(&b, conn)
- readc <- b.String()
- }()
- return &mockGraphite{
- readc: readc,
- errc: errc,
- Listener: ln,
- }, nil
- }
- type mockGraphite struct {
- readc chan string
- errc chan error
- net.Listener
- }
|