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