func TestLowerPercentile(t *testing.T) { d := []byte("time:0|ms\ntime:1|ms\ntime:2|ms\ntime:3|ms") packets := udp.ParseMessage(d, prefix_internal, output, udp.ParseLine) pct, _ := timers.NewPercentiles("-75") ti := timers.New("", *pct) for _, p := range packets { ti.Add(p) } var buf []byte var num int64 buf, n := ti.Process(buf, time.Now().Unix(), 10) num += n assert.Equal(t, num, int64(1)) exp := "time.upper_75 1 " got := string(buf) if strings.Contains(got, exp) { t.Fatalf("output %q contains %q", got, exp) } exp = "time.lower_75 1 " if !strings.Contains(got, exp) { t.Fatalf("output %q does not contain %q", got, exp) } }
func TestMetrics20Timer(t *testing.T) { d := []byte("foo=bar.target_type=gauge.unit=ms:5|ms\nfoo=bar.target_type=gauge.unit=ms:10|ms") packets := udp.ParseMessage(d, prefix_internal, output, udp.ParseLine) pct, _ := timers.NewPercentiles("75") ti := timers.New("", *pct) for _, p := range packets { ti.Add(p) } var buf []byte buf, num := ti.Process(buf, time.Now().Unix(), 10) assert.Equal(t, int(num), 1) dataForGraphite := string(buf) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=max_75 10")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=mean_75 7.5")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=sum_75 15")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=mean 7.5")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=median 7.5")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=std 2.5")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=sum 15")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=max 10")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=min 5")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=count.unit=Pckt.orig_unit=ms.pckt_type=sent.direction=in 2")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=rate.unit=Pcktps.orig_unit=ms.pckt_type=sent.direction=in 0.2")) }
func BenchmarkSameTimersAddAndProcess(b *testing.B) { metrics := getSameTimers(b.N) b.ResetTimer() pct, _ := timers.NewPercentiles("99") t := timers.New("bar", *pct) for i := 0; i < len(metrics); i++ { t.Add(&metrics[i]) } t.Process(make([]byte, 0), time.Now().Unix(), 10) }
func TestMean(t *testing.T) { // Some data with expected mean of 20 d := []byte("response_time:0|ms\nresponse_time:30|ms\nresponse_time:30|ms") packets := udp.ParseMessage(d, prefix_internal, output, udp.ParseLine) ti := timers.New("", timers.Percentiles{}) for _, p := range packets { ti.Add(p) } var buf []byte buf, num := ti.Process(buf, time.Now().Unix(), 60) assert.Equal(t, num, int64(1)) exp := "response_time.mean 20 " got := string(buf) if !strings.Contains(got, exp) { t.Fatalf("output %q does not contain %q", got, exp) } }
// metricsMonitor basically guards the metrics datastructures. // it typically receives metrics on the Metrics channel but also responds to // external signals and every flushInterval, computes and flushes the data func (s *StatsDaemon) metricsMonitor() { period := time.Duration(s.flushInterval) * time.Second tick := ticker.GetAlignedTicker(s.Clock, period) var c *counters.Counters var g *gauges.Gauges var t *timers.Timers oneCounter := &common.Metric{ Bucket: fmt.Sprintf("%sdirection_is_in.statsd_type_is_counter.target_type_is_count.unit_is_Metric", s.prefix), Value: 1, Sampling: 1, } oneGauge := &common.Metric{ Bucket: fmt.Sprintf("%sdirection_is_in.statsd_type_is_gauge.target_type_is_count.unit_is_Metric", s.prefix), Value: 1, Sampling: 1, } oneTimer := &common.Metric{ Bucket: fmt.Sprintf("%sdirection_is_in.statsd_type_is_timer.target_type_is_count.unit_is_Metric", s.prefix), Value: 1, Sampling: 1, } initializeCounters := func() { c = counters.New(s.prefix_rates, s.prefix_counters, s.legacy_namespace, s.flush_rates, s.flush_counts) g = gauges.New(s.prefix_gauges) t = timers.New(s.prefix_timers, s.pct) for _, name := range []string{"timer", "gauge", "counter"} { c.Add(&common.Metric{ Bucket: fmt.Sprintf("%sdirection_is_in.statsd_type_is_%s.target_type_is_count.unit_is_Metric", s.prefix, name), Sampling: 1, }) } } initializeCounters() for { select { case sig := <-s.signalchan: switch sig { case syscall.SIGTERM, syscall.SIGINT: fmt.Printf("!! Caught signal %s... shutting down\n", sig) s.submitFunc(c, g, t, s.Clock.Now().Add(period)) return default: fmt.Printf("unknown signal %s, ignoring\n", sig) } case <-tick.C: go func(c *counters.Counters, g *gauges.Gauges, t *timers.Timers) { s.submitFunc(c, g, t, s.Clock.Now().Add(period)) s.events.Broadcast <- "flush" }(c, g, t) initializeCounters() tick = ticker.GetAlignedTicker(s.Clock, period) case metrics := <-s.Metrics: for _, m := range metrics { if m.Modifier == "ms" { t.Add(m) c.Add(oneTimer) } else if m.Modifier == "g" { g.Add(m) c.Add(oneGauge) } else { c.Add(m) c.Add(oneCounter) } } } } }