graphite.go 2.7 KB

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