Ejemplo n.º 1
0
func graphite(c *GraphiteConfig) error {
	now := time.Now().Unix()
	du := float64(c.DurationUnit)
	conn, err := net.DialTCP("tcp", nil, c.Addr)
	if nil != err {
		return err
	}
	defer conn.Close()
	w := bufio.NewWriter(conn)
	c.Registry.Each(func(name string, i interface{}) {
		k := c.Prefix + name
		switch metric := i.(type) {
		case Counter:
			fmt.Fprintf(w, "%s %d %d\n", m2.Counter(k, ""), metric.Count(), now)
		case Gauge:
			fmt.Fprintf(w, "%s %d %d\n", m2.Gauge(k, ""), metric.Value(), now)
		case GaugeFloat64:
			fmt.Fprintf(w, "%s %f %d\n", m2.Gauge(k, ""), metric.Value(), now)
		case Histogram:
			h := metric.Snapshot()
			ps := h.Percentiles(c.Percentiles)
			fmt.Fprintf(w, "%s %d %d\n", m2.CountMetric(k, ""), h.Count(), now)
			fmt.Fprintf(w, "%s %d %d\n", m2.Min(k, "", "", ""), h.Min(), now)
			fmt.Fprintf(w, "%s %d %d\n", m2.Max(k, "", "", ""), h.Max(), now)
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Mean(k, "", "", ""), h.Mean(), now)
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Std(k, "", "", ""), h.StdDev(), now)
			for psIdx, psKey := range c.Percentiles {
				pct := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1)
				fmt.Fprintf(w, "%s %.2f %d\n", m2.Max(k, "", pct, ""), ps[psIdx], now)
			}
		case Meter:
			m := metric.Snapshot()
			fmt.Fprintf(w, "%s %d %d\n", m2.CountMetric(k, ""), m.Count(), now)
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Mean(k, "1m", "", "60"), m.Rate1(), now)
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Mean(k, "5m", "", "300"), m.Rate5(), now)
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Mean(k, "15m", "", "900"), m.Rate15(), now)
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Mean(k, "start", "", "start"), m.RateMean(), now)
		case Timer:
			t := metric.Snapshot()
			ps := t.Percentiles(c.Percentiles)
			fmt.Fprintf(w, "%s %d %d\n", m2.CountMetric(k, ""), t.Count(), now)
			fmt.Fprintf(w, "%s %d %d\n", m2.Min(k, "", "", ""), t.Min()/int64(du), now)
			fmt.Fprintf(w, "%s %d %d\n", m2.Max(k, "", "", ""), t.Max()/int64(du), now)
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Mean(k, "", "", ""), t.Mean()/du, now)
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Std(k, "", "", ""), t.StdDev()/du, now)
			for psIdx, psKey := range c.Percentiles {
				pct := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1)
				fmt.Fprintf(w, "%s %.2f %d\n", m2.Max(k, "", pct, ""), ps[psIdx], now)
			}
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Mean(k, "1m", "", "60"), t.Rate1(), now)
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Mean(k, "5m", "", "300"), t.Rate5(), now)
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Mean(k, "15m", "", "900"), t.Rate15(), now)
			fmt.Fprintf(w, "%s %.2f %d\n", m2.Mean(k, "start", "", "start"), t.RateMean(), now)
		}
		w.Flush()
	})
	return nil
}
Ejemplo n.º 2
0
// Process computes the outbound metrics for timers and puts them in the buffer
func (timers *Timers) Process(buf []byte, now int64, interval int) ([]byte, int64) {
	// these are the metrics that get exposed:
	// count estimate of original amount of metrics sent, by dividing received by samplerate
	// count_ps  same but per second
	// lower
	// mean  // arithmetic mean
	// mean_<pct> // arithmetic mean of values below <pct> percentile
	// median
	// std  standard deviation
	// sum
	// sum_90
	// upper
	// upper_90 / lower_90

	var num int64
	for u, t := range timers.Values {
		if len(t.Points) > 0 {
			seen := len(t.Points)
			count := t.Amount_submitted
			count_ps := float64(count) / float64(interval)
			num++

			sort.Sort(t.Points)
			min := t.Points[0]
			max := t.Points[seen-1]

			sum := float64(0)
			for _, value := range t.Points {
				sum += value
			}
			mean := float64(sum) / float64(seen)
			sumOfDiffs := float64(0)
			for _, value := range t.Points {
				sumOfDiffs += math.Pow((float64(value) - mean), 2)
			}
			stddev := math.Sqrt(sumOfDiffs / float64(seen))
			mid := seen / 2
			var median float64
			if seen%2 == 1 {
				median = t.Points[mid]
			} else {
				median = (t.Points[mid-1] + t.Points[mid]) / 2
			}
			var cumulativeValues Float64Slice
			cumulativeValues = make(Float64Slice, seen, seen)
			cumulativeValues[0] = t.Points[0]
			for i := 1; i < seen; i++ {
				cumulativeValues[i] = t.Points[i] + cumulativeValues[i-1]
			}

			maxAtThreshold := max
			sum_pct := sum
			mean_pct := mean

			for _, pct := range timers.pctls {

				if seen > 1 {
					var abs float64
					if pct.float >= 0 {
						abs = pct.float
					} else {
						abs = 100 + pct.float
					}
					// poor man's math.Round(x):
					// math.Floor(x + 0.5)
					indexOfPerc := int(math.Floor(((abs / 100.0) * float64(seen)) + 0.5))
					if pct.float >= 0 {
						sum_pct = cumulativeValues[indexOfPerc-1]
						maxAtThreshold = t.Points[indexOfPerc-1]
					} else {
						maxAtThreshold = t.Points[indexOfPerc]
						sum_pct = cumulativeValues[seen-1] - cumulativeValues[seen-indexOfPerc-1]
					}
					mean_pct = float64(sum_pct) / float64(indexOfPerc)
				}

				var pctstr string
				var fn func(metric_in, prefix, percentile, timespec string) string
				if pct.float >= 0 {
					pctstr = pct.str
					fn = m20.Max
				} else {
					pctstr = pct.str[1:]
					fn = m20.Min
				}
				buf = common.WriteFloat64(buf, []byte(fn(u, timers.prefix, pctstr, "")), maxAtThreshold, now)
				buf = common.WriteFloat64(buf, []byte(m20.Mean(u, timers.prefix, pctstr, "")), mean_pct, now)
				buf = common.WriteFloat64(buf, []byte(m20.Sum(u, timers.prefix, pctstr, "")), sum_pct, now)
			}

			buf = common.WriteFloat64(buf, []byte(m20.Mean(u, timers.prefix, "", "")), mean, now)
			buf = common.WriteFloat64(buf, []byte(m20.Median(u, timers.prefix, "", "")), median, now)
			buf = common.WriteFloat64(buf, []byte(m20.Std(u, timers.prefix, "", "")), stddev, now)
			buf = common.WriteFloat64(buf, []byte(m20.Sum(u, timers.prefix, "", "")), sum, now)
			buf = common.WriteFloat64(buf, []byte(m20.Max(u, timers.prefix, "", "")), max, now)
			buf = common.WriteFloat64(buf, []byte(m20.Min(u, timers.prefix, "", "")), min, now)
			buf = common.WriteInt64(buf, []byte(m20.CountPckt(u, timers.prefix)), count, now)
			buf = common.WriteFloat64(buf, []byte(m20.RatePckt(u, timers.prefix)), count_ps, now)
		}
	}
	return buf, num
}