Skip to content

Commit 5f0d083

Browse files
committed
Add statsd timer collection for http, get reputation, and redis commands
1 parent 15bf19a commit 5f0d083

File tree

5 files changed

+62
-0
lines changed

5 files changed

+62
-0
lines changed

http.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ func (v *ViolationRequest) Validate() error {
3232

3333
func mwHandler(h http.Handler) http.Handler {
3434
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
35+
s := time.Now()
36+
defer func() {
37+
sruntime.statsd.Timing("http.timing", time.Since(s))
38+
}()
3539
w.Header().Add("X-Frame-Options", "DENY")
3640
w.Header().Add("X-Content-Type-Options", "nosniff")
3741
w.Header().Add("Content-Security-Policy",
@@ -111,6 +115,10 @@ func httpGetAllReputation(w http.ResponseWriter, r *http.Request) {
111115
}
112116

113117
func httpGetReputation(w http.ResponseWriter, r *http.Request) {
118+
s := time.Now()
119+
defer func() {
120+
sruntime.statsd.Timing("http.get_reputation.timing", time.Since(s))
121+
}()
114122
ipstr := mux.Vars(r)["ip"]
115123
if net.ParseIP(ipstr) == nil {
116124
w.WriteHeader(http.StatusBadRequest)

iprepd.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type serverRuntime struct {
1515
redis redisLink
1616
versionResponse []byte
1717
exceptionsLoaded chan bool
18+
statsd *statsdClient
1819
}
1920

2021
type serverCfg struct {
@@ -41,6 +42,9 @@ type serverCfg struct {
4142
AWS bool
4243
}
4344
VersionResponse string
45+
Statsd struct {
46+
Addr string
47+
}
4448
}
4549

4650
func (cfg *serverCfg) validate() error {
@@ -97,6 +101,10 @@ func StartDaemon(confpath string) {
97101
if err != nil {
98102
log.Fatalf(err.Error())
99103
}
104+
sruntime.statsd, err = newStatsdClient(sruntime.cfg)
105+
if err != nil {
106+
log.Fatalf(err.Error())
107+
}
100108
sruntime.redis, err = newRedisLink(sruntime.cfg)
101109
if err != nil {
102110
log.Fatalf(err.Error())

iprepd.yaml.sample

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,6 @@ exceptions:
7070
# request to the /__version__ endpoint. If the file isn't found a warning will be printed
7171
# in the log and the daemon will not return any data at this endpoint.
7272
versionresponse: ./version.json
73+
# statsd address for metrics. To disable metrics collection, simply delete the below section.
74+
statsd:
75+
addr: "127.0.0.1:8125"

redis.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package iprepd
22

33
import (
4+
"fmt"
45
"math/rand"
56
"time"
67

@@ -47,6 +48,15 @@ func (r *redisLink) set(k string, v interface{}, e time.Duration) *redis.StatusC
4748
return r.master.Set(k, v, e)
4849
}
4950

51+
func instrumentRedisCmd(old func(cmd redis.Cmder) error) func(cmd redis.Cmder) error {
52+
return func(cmd redis.Cmder) error {
53+
s := time.Now()
54+
err := old(cmd)
55+
sruntime.statsd.Timing(fmt.Sprintf("redis.%s.timing", cmd.Name()), time.Since(s))
56+
return err
57+
}
58+
}
59+
5060
func newRedisLink(cfg serverCfg) (ret redisLink, err error) {
5161
ret.master = redis.NewClient(&redis.Options{
5262
Addr: cfg.Redis.Addr,
@@ -55,6 +65,7 @@ func newRedisLink(cfg serverCfg) (ret redisLink, err error) {
5565
WriteTimeout: time.Millisecond * time.Duration(cfg.Redis.WriteTimeout),
5666
DialTimeout: time.Millisecond * time.Duration(cfg.Redis.DialTimeout),
5767
})
68+
ret.master.WrapProcess(instrumentRedisCmd)
5869
_, err = ret.ping().Result()
5970
if err != nil {
6071
return
@@ -72,6 +83,7 @@ func newRedisLink(cfg serverCfg) (ret redisLink, err error) {
7283
ReadTimeout: time.Millisecond * time.Duration(cfg.Redis.ReadTimeout),
7384
DialTimeout: time.Millisecond * time.Duration(cfg.Redis.DialTimeout),
7485
})
86+
y.WrapProcess(instrumentRedisCmd)
7587
ret.readClients = append(ret.readClients, y)
7688
}
7789
// Also use the master for reads

statsd.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package iprepd
2+
3+
import (
4+
"time"
5+
6+
"github.com/DataDog/datadog-go/statsd"
7+
)
8+
9+
type statsdClient struct {
10+
client *statsd.Client
11+
}
12+
13+
func newStatsdClient(cfg serverCfg) (*statsdClient, error) {
14+
if cfg.Statsd.Addr == "" {
15+
return &statsdClient{client: nil}, nil
16+
}
17+
c, err := statsd.New(cfg.Statsd.Addr)
18+
if err != nil {
19+
return nil, err
20+
}
21+
c.Namespace = "iprepd_server."
22+
23+
return &statsdClient{client: c}, nil
24+
}
25+
26+
func (sc statsdClient) Timing(name string, value time.Duration) error {
27+
if sc.client == nil {
28+
return nil
29+
}
30+
return sc.client.Timing(name, value, []string{}, 1)
31+
}

0 commit comments

Comments
 (0)