forked from exaring/hystrix-go
/
graphite_aggregator.go
109 lines (98 loc) · 4.2 KB
/
graphite_aggregator.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
108
109
// Plugins allows users to operate on statistics recorded for each circuit operation.
// Plugins should be careful to be lightweight as they will be called frequently.
package plugins
import (
"net"
"strings"
"time"
"github.com/rcrowley/go-metrics"
"github.com/vetmik/hystrix-go/hystrix/metric_collector"
)
var makeTimerFunc = func() interface{} { return metrics.NewTimer() }
var makeCounterFunc = func() interface{} { return metrics.NewCounter() }
// GraphiteCollector fulfills the metricCollector interface allowing users to ship circuit
// stats to a graphite backend. To use users must call InitializeGraphiteCollector before
// circuits are started. Then register NewGraphiteCollector with metricCollector.Registry.Register(NewGraphiteCollector).
//
// This Collector uses github.com/rcrowley/go-metrics for aggregation. See that repo for more details
// on how metrics are aggregated and expressed in graphite.
type GraphiteCollector struct {
attemptsPrefix string
errorsPrefix string
successesPrefix string
failuresPrefix string
rejectsPrefix string
shortCircuitsPrefix string
timeoutsPrefix string
fallbackSuccessesPrefix string
fallbackFailuresPrefix string
totalDurationPrefix string
runDurationPrefix string
}
// GraphiteCollectorConfig provides configuration that the graphite client will need.
type GraphiteCollectorConfig struct {
// GraphiteAddr is the tcp address of the graphite server
GraphiteAddr *net.TCPAddr
// Prefix is the prefix that will be prepended to all metrics sent from this collector.
Prefix string
// TickInterval spcifies the period that this collector will send metrics to the server.
TickInterval time.Duration
}
// InitializeGraphiteCollector creates the connection to the graphite server
// and should be called before any metrics are recorded.
func InitializeGraphiteCollector(config *GraphiteCollectorConfig) {
go metrics.Graphite(metrics.DefaultRegistry, config.TickInterval, config.Prefix, config.GraphiteAddr)
}
// NewGraphiteCollector creates a collector for a specific circuit. The
// prefix given to this circuit will be {config.Prefix}.{circuit_name}.{metric}.
// Circuits with "/" in their names will have them replaced with ".".
func NewGraphiteCollector(name string) metricCollector.MetricCollector {
name = strings.Replace(name, "/", "-", -1)
name = strings.Replace(name, ":", "-", -1)
name = strings.Replace(name, ".", "-", -1)
return &GraphiteCollector{
attemptsPrefix: name + ".attempts",
errorsPrefix: name + ".errors",
successesPrefix: name + ".successes",
failuresPrefix: name + ".failures",
rejectsPrefix: name + ".rejects",
shortCircuitsPrefix: name + ".shortCircuits",
timeoutsPrefix: name + ".timeouts",
fallbackSuccessesPrefix: name + ".fallbackSuccesses",
fallbackFailuresPrefix: name + ".fallbackFailures",
totalDurationPrefix: name + ".totalDuration",
runDurationPrefix: name + ".runDuration",
}
}
func (g *GraphiteCollector) incrementCounterMetric(prefix string, i float64) {
if i == 0 {
return
}
c, ok := metrics.GetOrRegister(prefix, makeCounterFunc).(metrics.Counter)
if !ok {
return
}
c.Inc(int64(i))
}
func (g *GraphiteCollector) updateTimerMetric(prefix string, dur time.Duration) {
c, ok := metrics.GetOrRegister(prefix, makeTimerFunc).(metrics.Timer)
if !ok {
return
}
c.Update(dur)
}
func (g *GraphiteCollector) Update(r metricCollector.MetricResult) {
g.incrementCounterMetric(g.attemptsPrefix, r.Attempts)
g.incrementCounterMetric(g.errorsPrefix, r.Errors)
g.incrementCounterMetric(g.successesPrefix, r.Successes)
g.incrementCounterMetric(g.failuresPrefix, r.Failures)
g.incrementCounterMetric(g.rejectsPrefix, r.Rejects)
g.incrementCounterMetric(g.shortCircuitsPrefix, r.ShortCircuits)
g.incrementCounterMetric(g.timeoutsPrefix, r.Timeouts)
g.incrementCounterMetric(g.fallbackSuccessesPrefix, r.FallbackSuccesses)
g.incrementCounterMetric(g.fallbackFailuresPrefix, r.FallbackFailures)
g.updateTimerMetric(g.totalDurationPrefix, r.TotalDuration)
g.updateTimerMetric(g.runDurationPrefix, r.RunDuration)
}
// Reset is a noop operation in this collector.
func (g *GraphiteCollector) Reset() {}