-
Notifications
You must be signed in to change notification settings - Fork 32
/
handler.go
100 lines (80 loc) · 2.5 KB
/
handler.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
package stats
import "time"
// The Handler interface is implemented by types that produce measures to
// various metric collection backends.
type Handler interface {
// HandleMeasures is called by the Engine on which the handler was set
// whenever new measures are produced by the program. The first argument
// is the time at which the measures were taken.
//
// The method must treat the list of measures as read-only values, and
// must not retain pointers to any of the measures or their sub-fields
// after returning.
HandleMeasures(time time.Time, measures ...Measure)
}
// Flusher is an interface implemented by measure handlers in order to flush
// any buffered data.
type Flusher interface {
Flush()
}
func flush(h Handler) {
if f, ok := h.(Flusher); ok {
f.Flush()
}
}
// HandlerFunc is a type alias making it possible to use simple functions as
// measure handlers.
type HandlerFunc func(time.Time, ...Measure)
// HandleMeasures calls f, satisfies the Handler interface.
func (f HandlerFunc) HandleMeasures(time time.Time, measures ...Measure) {
f(time, measures...)
}
// MultiHandler constructs a handler which dispatches measures to all given
// handlers.
func MultiHandler(handlers ...Handler) Handler {
multi := make([]Handler, 0, len(handlers))
for _, h := range handlers {
if h != nil {
if m, ok := h.(*multiHandler); ok {
multi = append(multi, m.handlers...) // flatten multi handlers
} else {
multi = append(multi, h)
}
}
}
if len(multi) == 1 {
return multi[0]
}
return &multiHandler{handlers: multi}
}
type multiHandler struct {
handlers []Handler
}
func (m *multiHandler) HandleMeasures(time time.Time, measures ...Measure) {
for _, h := range m.handlers {
h.HandleMeasures(time, measures...)
}
}
func (m *multiHandler) Flush() {
for _, h := range m.handlers {
flush(h)
}
}
// FilteredHandler constructs a Handler that processes Measures with `filter` before forwarding to `h`.
func FilteredHandler(h Handler, filter func([]Measure) []Measure) Handler {
return &filteredHandler{handler: h, filter: filter}
}
type filteredHandler struct {
handler Handler
filter func([]Measure) []Measure
}
func (h *filteredHandler) HandleMeasures(time time.Time, measures ...Measure) {
h.handler.HandleMeasures(time, h.filter(measures)...)
}
func (h *filteredHandler) Flush() {
flush(h.handler)
}
// Discard is a handler that doesn't do anything with the measures it receives.
var Discard = &discard{}
type discard struct{}
func (*discard) HandleMeasures(time.Time, ...Measure) {}