graphite.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package metrics
  2. import (
  3. "bytes"
  4. "fmt"
  5. "net"
  6. "strings"
  7. "time"
  8. "github.com/grafana/grafana/pkg/log"
  9. "github.com/grafana/grafana/pkg/setting"
  10. )
  11. type GraphitePublisher struct {
  12. address string
  13. protocol string
  14. prefix string
  15. prevCounts map[string]int64
  16. }
  17. func CreateGraphitePublisher() (*GraphitePublisher, error) {
  18. graphiteSection, err := setting.Cfg.GetSection("metrics.graphite")
  19. if err != nil {
  20. return nil, nil
  21. }
  22. address := graphiteSection.Key("address").String()
  23. if address == "" {
  24. return nil, nil
  25. }
  26. publisher := &GraphitePublisher{}
  27. publisher.prevCounts = make(map[string]int64)
  28. publisher.protocol = "tcp"
  29. publisher.prefix = graphiteSection.Key("prefix").MustString("prod.grafana.%(instance_name)s")
  30. publisher.address = address
  31. safeInstanceName := strings.Replace(setting.InstanceName, ".", "_", -1)
  32. prefix := graphiteSection.Key("prefix").Value()
  33. if prefix == "" {
  34. prefix = "prod.grafana.%(instance_name)s."
  35. }
  36. publisher.prefix = strings.Replace(prefix, "%(instance_name)s", safeInstanceName, -1)
  37. return publisher, nil
  38. }
  39. func (this *GraphitePublisher) Publish(metrics []Metric) {
  40. conn, err := net.DialTimeout(this.protocol, this.address, time.Second*5)
  41. if err != nil {
  42. log.Error(3, "Metrics: GraphitePublisher: Failed to connect to %s!", err)
  43. return
  44. }
  45. buf := bytes.NewBufferString("")
  46. now := time.Now().Unix()
  47. for _, m := range metrics {
  48. metricName := this.prefix + m.Name() + m.StringifyTags()
  49. switch metric := m.(type) {
  50. case Counter:
  51. this.addCount(buf, metricName+".count", metric.Count(), now)
  52. case Timer:
  53. percentiles := metric.Percentiles([]float64{0.25, 0.75, 0.90, 0.99})
  54. this.addCount(buf, metricName+".count", metric.Count(), now)
  55. this.addInt(buf, metricName+".max", metric.Max(), now)
  56. this.addInt(buf, metricName+".min", metric.Min(), now)
  57. this.addFloat(buf, metricName+".mean", metric.Mean(), now)
  58. this.addFloat(buf, metricName+".std", metric.StdDev(), now)
  59. this.addFloat(buf, metricName+".p25", percentiles[0], now)
  60. this.addFloat(buf, metricName+".p75", percentiles[1], now)
  61. this.addFloat(buf, metricName+".p90", percentiles[2], now)
  62. this.addFloat(buf, metricName+".p99", percentiles[3], now)
  63. }
  64. }
  65. log.Trace("Metrics: GraphitePublisher.Publish() \n%s", buf)
  66. _, err = conn.Write(buf.Bytes())
  67. if err != nil {
  68. log.Error(3, "Metrics: GraphitePublisher: Failed to send metrics! %s", err)
  69. }
  70. }
  71. func (this *GraphitePublisher) addInt(buf *bytes.Buffer, metric string, value int64, now int64) {
  72. buf.WriteString(fmt.Sprintf("%s %d %d\n", metric, value, now))
  73. }
  74. func (this *GraphitePublisher) addFloat(buf *bytes.Buffer, metric string, value float64, now int64) {
  75. buf.WriteString(fmt.Sprintf("%s %f %d\n", metric, value, now))
  76. }
  77. func (this *GraphitePublisher) addCount(buf *bytes.Buffer, metric string, value int64, now int64) {
  78. delta := value
  79. if last, ok := this.prevCounts[metric]; ok {
  80. delta = calculateDelta(last, value)
  81. }
  82. this.prevCounts[metric] = value
  83. buf.WriteString(fmt.Sprintf("%s %d %d\n", metric, delta, now))
  84. }