Example #1
0
func TestHistogram(t *testing.T) {
	// The histogram test is actually like 4 gauge tests.
	prefix, name := "statsd.", "histogram_test"
	label, value := "abc", "def" // ignored for Graphite
	re50 := regexp.MustCompile(prefix + name + `.p50 ([0-9\.]+) [0-9]+`)
	re90 := regexp.MustCompile(prefix + name + `.p90 ([0-9\.]+) [0-9]+`)
	re95 := regexp.MustCompile(prefix + name + `.p95 ([0-9\.]+) [0-9]+`)
	re99 := regexp.MustCompile(prefix + name + `.p99 ([0-9\.]+) [0-9]+`)
	g := New(prefix, log.NewNopLogger())
	histogram := g.NewHistogram(name, 50).With(label, value)
	quantiles := func() (float64, float64, float64, float64) {
		var buf bytes.Buffer
		g.WriteTo(&buf)
		match50 := re50.FindStringSubmatch(buf.String())
		p50, _ := strconv.ParseFloat(match50[1], 64)
		match90 := re90.FindStringSubmatch(buf.String())
		p90, _ := strconv.ParseFloat(match90[1], 64)
		match95 := re95.FindStringSubmatch(buf.String())
		p95, _ := strconv.ParseFloat(match95[1], 64)
		match99 := re99.FindStringSubmatch(buf.String())
		p99, _ := strconv.ParseFloat(match99[1], 64)
		return p50, p90, p95, p99
	}
	if err := teststat.TestHistogram(histogram, quantiles, 0.01); err != nil {
		t.Fatal(err)
	}
}
Example #2
0
func TestTimingSampled(t *testing.T) {
	prefix, name := "statsd.", "sampled_timing_test"
	label, value := "foo", "bar" // ignored
	regex := `^` + prefix + name + `:([0-9\.]+)\|ms\|@0\.01[0]*$`
	s := New(prefix, log.NewNopLogger())
	timing := s.NewTiming(name, 0.01).With(label, value)
	quantiles := teststat.Quantiles(s, regex, 50)
	if err := teststat.TestHistogram(timing, quantiles, 0.02); err != nil {
		t.Fatal(err)
	}
}
Example #3
0
func TestTiming(t *testing.T) {
	prefix, name := "statsd.", "timing_test"
	label, value := "abc", "def" // ignored
	regex := `^` + prefix + name + `:([0-9\.]+)\|ms$`
	s := New(prefix, log.NewNopLogger())
	timing := s.NewTiming(name, 1.0).With(label, value)
	quantiles := teststat.Quantiles(s, regex, 50) // no |@0.X
	if err := teststat.TestHistogram(timing, quantiles, 0.01); err != nil {
		t.Fatal(err)
	}
}
Example #4
0
func TestHistogram(t *testing.T) {
	in := New(map[string]string{"foo": "alpha"}, influxdb.BatchPointsConfig{}, log.NewNopLogger())
	re := regexp.MustCompile(`influx_histogram,foo=alpha bar="beta",value=([0-9\.]+) [0-9]+`)
	histogram := in.NewHistogram("influx_histogram").With("bar", "beta")
	quantiles := func() (float64, float64, float64, float64) {
		w := &bufWriter{}
		in.WriteTo(w)
		h := generic.NewHistogram("h", 50)
		matches := re.FindAllStringSubmatch(w.buf.String(), -1)
		for _, match := range matches {
			f, _ := strconv.ParseFloat(match[1], 64)
			h.Observe(f)
		}
		return h.Quantile(0.50), h.Quantile(0.90), h.Quantile(0.95), h.Quantile(0.99)
	}
	if err := teststat.TestHistogram(histogram, quantiles, 0.01); err != nil {
		t.Fatal(err)
	}
}
Example #5
0
func TestHistogram(t *testing.T) {
	const name = "ghi"

	// Circonus just emits bucketed counts. We'll dump them into a generic
	// histogram (losing some precision) and take statistics from there. Note
	// this does assume that the generic histogram computes statistics properly,
	// but we have another test for that :)
	re := regexp.MustCompile(`^H\[([0-9\.e\+]+)\]=([0-9]+)$`) // H[1.2e+03]=456

	var p50, p90, p95, p99 float64
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var res map[string]struct {
			Values []string `json:"_value"` // reverse-engineered :\
		}
		json.NewDecoder(r.Body).Decode(&res)

		h := generic.NewHistogram("dummy", len(res[name].Values)) // match tbe bucket counts
		for _, v := range res[name].Values {
			match := re.FindStringSubmatch(v)
			f, _ := strconv.ParseFloat(match[1], 64)
			n, _ := strconv.ParseInt(match[2], 10, 64)
			for i := int64(0); i < n; i++ {
				h.Observe(f)
			}
		}

		p50 = h.Quantile(0.50)
		p90 = h.Quantile(0.90)
		p95 = h.Quantile(0.95)
		p99 = h.Quantile(0.99)
	}))
	defer s.Close()

	m := newCirconusMetrics(s.URL)
	histogram := New(m).NewHistogram(name).With("label values", "not supported")
	quantiles := func() (float64, float64, float64, float64) { m.Flush(); return p50, p90, p95, p99 }

	// Circonus metrics, because they do their own bucketing, are less precise
	// than other systems. So, we bump the tolerance to 5 percent.
	if err := teststat.TestHistogram(histogram, quantiles, 0.05); err != nil {
		t.Fatal(err)
	}
}
Example #6
0
func TestSummary(t *testing.T) {
	s := httptest.NewServer(stdprometheus.UninstrumentedHandler())
	defer s.Close()

	scrape := func() string {
		resp, _ := http.Get(s.URL)
		buf, _ := ioutil.ReadAll(resp.Body)
		return string(buf)
	}

	namespace, subsystem, name := "test", "prometheus", "summary"
	re50 := regexp.MustCompile(namespace + `_` + subsystem + `_` + name + `{a="a",b="b",quantile="0.5"} ([0-9\.]+)`)
	re90 := regexp.MustCompile(namespace + `_` + subsystem + `_` + name + `{a="a",b="b",quantile="0.9"} ([0-9\.]+)`)
	re99 := regexp.MustCompile(namespace + `_` + subsystem + `_` + name + `{a="a",b="b",quantile="0.99"} ([0-9\.]+)`)

	summary := NewSummaryFrom(stdprometheus.SummaryOpts{
		Namespace: namespace,
		Subsystem: subsystem,
		Name:      name,
		Help:      "This is the help string for the summary.",
	}, []string{"a", "b"}).With("b", "b").With("a", "a")

	quantiles := func() (float64, float64, float64, float64) {
		buf := scrape()
		match50 := re50.FindStringSubmatch(buf)
		p50, _ := strconv.ParseFloat(match50[1], 64)
		match90 := re90.FindStringSubmatch(buf)
		p90, _ := strconv.ParseFloat(match90[1], 64)
		match99 := re99.FindStringSubmatch(buf)
		p99, _ := strconv.ParseFloat(match99[1], 64)
		p95 := p90 + ((p99 - p90) / 2) // Prometheus, y u no p95??? :< #yolo
		return p50, p90, p95, p99
	}

	if err := teststat.TestHistogram(summary, quantiles, 0.01); err != nil {
		t.Fatal(err)
	}
}