graphite.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015")
  38. for _ = range time.Tick(c.FlushInterval) {
  39. if err := graphite(&c); nil != err {
  40. log.Println(err)
  41. }
  42. }
  43. }
  44. // GraphiteOnce performs a single submission to Graphite, returning a
  45. // non-nil error on failed connections. This can be used in a loop
  46. // similar to GraphiteWithConfig for custom error handling.
  47. func GraphiteOnce(c GraphiteConfig) error {
  48. log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015")
  49. return graphite(&c)
  50. }
  51. func graphite(c *GraphiteConfig) error {
  52. now := time.Now().Unix()
  53. du := float64(c.DurationUnit)
  54. conn, err := net.DialTCP("tcp", nil, c.Addr)
  55. if nil != err {
  56. return err
  57. }
  58. defer conn.Close()
  59. w := bufio.NewWriter(conn)
  60. c.Registry.Each(func(name string, i interface{}) {
  61. switch metric := i.(type) {
  62. case Counter:
  63. fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now)
  64. case Gauge:
  65. fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now)
  66. case GaugeFloat64:
  67. fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now)
  68. case Histogram:
  69. h := metric.Snapshot()
  70. ps := h.Percentiles(c.Percentiles)
  71. fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now)
  72. fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now)
  73. fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now)
  74. fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now)
  75. fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now)
  76. for psIdx, psKey := range c.Percentiles {
  77. key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1)
  78. fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now)
  79. }
  80. case Meter:
  81. m := metric.Snapshot()
  82. fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now)
  83. fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now)
  84. fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now)
  85. fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now)
  86. fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now)
  87. case Timer:
  88. t := metric.Snapshot()
  89. ps := t.Percentiles(c.Percentiles)
  90. fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, t.Count(), now)
  91. fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, t.Min()/int64(du), now)
  92. fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, t.Max()/int64(du), now)
  93. fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, t.Mean()/du, now)
  94. fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, t.StdDev()/du, now)
  95. for psIdx, psKey := range c.Percentiles {
  96. key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1)
  97. fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now)
  98. }
  99. fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now)
  100. fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now)
  101. fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now)
  102. fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now)
  103. }
  104. w.Flush()
  105. })
  106. return nil
  107. }