func TestLowerPercentile(t *testing.T) { // Some data with expected mean of 20 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 buff bytes.Buffer var num int64 num += ti.Process(&buff, time.Now().Unix(), 10) assert.Equal(t, num, int64(1)) dataForGraphite := buff.String() meanRegexp := regexp.MustCompile(`time\.upper_75 1\.`) matched := meanRegexp.MatchString(dataForGraphite) assert.Equal(t, matched, false) meanRegexp = regexp.MustCompile(`time\.lower_75 1\.`) matched = meanRegexp.MatchString(dataForGraphite) assert.Equal(t, matched, true) }
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 buff bytes.Buffer num := ti.Process(&buff, time.Now().Unix(), 10) assert.Equal(t, int(num), 1) dataForGraphite := buff.String() assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=max_75 10.000000")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=mean_75 7.500000")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=sum_75 15.000000")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=mean 7.500000")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=median 7.500000")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=std 2.500000")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=sum 15.000000")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=max 10.000000")) assert.T(t, strings.Contains(dataForGraphite, "foo=bar.target_type=gauge.unit=ms.stat=min 5.000000")) 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.200000")) }
func BenchmarkMillionSameTimersAddAndProcess(b *testing.B) { metrics := getSameTimers(1000000) b.ResetTimer() pct, _ := timers.NewPercentiles("99") t := timers.New("bar", *pct) for i := 0; i < len(metrics); i++ { for n := 0; n < b.N; n++ { t.Add(&metrics[i]) } } t.Process(&bytes.Buffer{}, 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 buff bytes.Buffer num := ti.Process(&buff, time.Now().Unix(), 60) assert.Equal(t, num, int64(1)) dataForGraphite := buff.String() pattern := `response_time\.mean 20\.[0-9]+ ` meanRegexp := regexp.MustCompile(pattern) matched := meanRegexp.MatchString(dataForGraphite) assert.Equal(t, matched, true) }
// 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(period) var c *counters.Counters var g *gauges.Gauges var t *timers.Timers initializeCounters := func() { c = counters.New(s.prefix_rates) 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) if err := s.submit(c, g, t, time.Now().Add(period)); err != nil { log.Printf("ERROR: %s", err) } return default: fmt.Printf("unknown signal %s, ignoring\n", sig) } case <-tick.C: go func(c *counters.Counters, g *gauges.Gauges, t *timers.Timers) { if err := s.submit(c, g, t, time.Now().Add(period)); err != nil { log.Printf("ERROR: %s", err) } s.events.Broadcast <- "flush" }(c, g, t) initializeCounters() tick = ticker.GetAlignedTicker(period) case m := <-s.Metrics: var name string if m.Modifier == "ms" { t.Add(m) name = "timer" } else if m.Modifier == "g" { if m.IsDelta { log.Fatal("delta gauge:", m) } g.Add(m) name = "gauge" } else if m.Modifier == "c" { c.Add(m) name = "counter" } else { name = "unknown" } c.Add(&common.Metric{ Bucket: fmt.Sprintf("%sdirection_is_in.statsd_type_is_%s.target_type_is_count.unit_is_Metric", s.prefix, name), Value: 1, Sampling: 1, }) } } }