-
Notifications
You must be signed in to change notification settings - Fork 137
/
exchanger.go
80 lines (70 loc) · 2.2 KB
/
exchanger.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
package exchanger
import (
"log"
"time"
"github.com/mesosphere/mesos-dns/logging"
"github.com/miekg/dns"
)
// Exchanger is an interface capturing a dns.Client Exchange method.
type Exchanger interface {
// Exchange performs an synchronous query. It sends the message m to the address
// contained in addr (host:port) and waits for a reply.
Exchange(m *dns.Msg, addr string) (r *dns.Msg, rtt time.Duration, err error)
}
// Func is a function type that implements the Exchanger interface.
type Func func(*dns.Msg, string) (*dns.Msg, time.Duration, error)
// Exchange implements the Exchanger interface.
func (f Func) Exchange(m *dns.Msg, addr string) (*dns.Msg, time.Duration, error) {
return f(m, addr)
}
// A Decorator adds a layer of behaviour to a given Exchanger.
type Decorator func(Exchanger) Exchanger
// IgnoreErrTruncated is a Decorator which causes dns.ErrTruncated to be ignored
var IgnoreErrTruncated Decorator = func(ex Exchanger) Exchanger {
return Func(func(m *dns.Msg, a string) (r *dns.Msg, rtt time.Duration, err error) {
r, rtt, err = ex.Exchange(m, a)
if err == dns.ErrTruncated {
// Ignore
err = nil
}
return
})
}
// Decorate decorates an Exchanger with the given Decorators.
func Decorate(ex Exchanger, ds ...Decorator) Exchanger {
decorated := ex
for _, decorate := range ds {
decorated = decorate(decorated)
}
return decorated
}
// ErrorLogging returns a Decorator which logs an Exchanger's errors to the given
// logger.
func ErrorLogging(l *log.Logger) Decorator {
return func(ex Exchanger) Exchanger {
return Func(func(m *dns.Msg, a string) (r *dns.Msg, rtt time.Duration, err error) {
defer func() {
if err != nil {
l.Printf("%v: exchanging %#v with %q", err, m, a)
}
}()
return ex.Exchange(m, a)
})
}
}
// Instrumentation returns a Decorator which instruments an Exchanger with the given
// counters.
func Instrumentation(total, success, failure logging.Counter) Decorator {
return func(ex Exchanger) Exchanger {
return Func(func(m *dns.Msg, a string) (r *dns.Msg, rtt time.Duration, err error) {
defer func() {
if total.Inc(); err != nil {
failure.Inc()
} else {
success.Inc()
}
}()
return ex.Exchange(m, a)
})
}
}