graphite.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package metrics
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "net"
  7. "strconv"
  8. "strings"
  9. "time"
  10. )
  11. // GraphiteConfig provides a container with configuration parameters for
  12. // the Graphite exporter
  13. type GraphiteConfig struct {
  14. Addr *net.TCPAddr // Network address to connect to
  15. Registry Registry // Registry to be exported
  16. FlushInterval time.Duration // Flush interval
  17. DurationUnit time.Duration // Time conversion unit for durations
  18. Prefix string // Prefix to be prepended to metric names
  19. Percentiles []float64 // Percentiles to export from timers and histograms
  20. }
  21. // Graphite is a blocking exporter function which reports metrics in r
  22. // to a graphite server located at addr, flushing them every d duration
  23. // and prepending metric names with prefix.
  24. func Graphite(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) {
  25. GraphiteWithConfig(GraphiteConfig{
  26. Addr: addr,
  27. Registry: r,
  28. FlushInterval: d,
  29. DurationUnit: time.Nanosecond,
  30. Prefix: prefix,
  31. Percentiles: []float64{0.5, 0.75, 0.95, 0.99, 0.999},
  32. })
  33. }
  34. // GraphiteWithConfig is a blocking exporter function just like Graphite,
  35. // but it takes a GraphiteConfig instead.
  36. func GraphiteWithConfig(c GraphiteConfig) {
  37. for _ = range time.Tick(c.FlushInterval) {
  38. if err := graphite(&c); nil != err {
  39. log.Println(err)
  40. }
  41. }
  42. }
  43. func graphite(c *GraphiteConfig) error {
  44. now := time.Now().Unix()
  45. du := float64(c.DurationUnit)
  46. conn, err := net.DialTCP("tcp", nil, c.Addr)
  47. if nil != err {
  48. return err
  49. }
  50. defer conn.Close()
  51. w := bufio.NewWriter(conn)
  52. c.Registry.Each(func(name string, i interface{}) {
  53. switch metric := i.(type) {
  54. case Counter:
  55. fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now)
  56. case Gauge:
  57. fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now)
  58. case GaugeFloat64:
  59. fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now)
  60. case Histogram:
  61. h := metric.Snapshot()
  62. ps := h.Percentiles(c.Percentiles)
  63. fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now)
  64. fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now)
  65. fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now)
  66. fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now)
  67. fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now)
  68. for psIdx, psKey := range c.Percentiles {
  69. key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1)
  70. fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now)
  71. }
  72. case Meter:
  73. m := metric.Snapshot()
  74. fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now)
  75. fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now)
  76. fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now)
  77. fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now)
  78. fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now)
  79. case Timer:
  80. t := metric.Snapshot()
  81. ps := t.Percentiles(c.Percentiles)
  82. fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, t.Count(), now)
  83. fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, int64(du)*t.Min(), now)
  84. fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, int64(du)*t.Max(), now)
  85. fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, du*t.Mean(), now)
  86. fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, du*t.StdDev(), now)
  87. for psIdx, psKey := range c.Percentiles {
  88. key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1)
  89. fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now)
  90. }
  91. fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now)
  92. fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now)
  93. fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now)
  94. fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now)
  95. }
  96. w.Flush()
  97. })
  98. return nil
  99. }