Skip to content

Commit e8a91e3

Browse files
Merge pull request #30 from istreamlabs/custom-statsd
feat: add option for custom configured statsd client
2 parents b643fa2 + 04bdfd4 commit e8a91e3

File tree

2 files changed

+83
-19
lines changed

2 files changed

+83
-19
lines changed

metrics/datadog.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,30 @@ type DataDogClient struct {
1717
// Options contains the configuration options for a client.
1818
type Options struct {
1919
WithoutTelemetry bool
20+
Statsd *statsd.Client
2021
}
2122

2223
// Option is a client option. Can return an error if validation fails.
2324
type Option func(*Options) error
2425

25-
// WithoutTelemetry turns off senting DataDog telemetry metrics.
26+
// WithoutTelemetry turns off sending DataDog telemetry metrics.
2627
func WithoutTelemetry() Option {
2728
return func(o *Options) error {
2829
o.WithoutTelemetry = true
2930
return nil
3031
}
3132
}
3233

34+
// WithStatsd sets a custom configured statsd client. This lets you set any
35+
// options that aren't directly supported by the metrics package. When used,
36+
// this ignores the address and namespace arguments to NewDataDogClient.
37+
func WithStatsd(s *statsd.Client) Option {
38+
return func(o *Options) error {
39+
o.Statsd = s
40+
return nil
41+
}
42+
}
43+
3344
func resolveOptions(options []Option) (*Options, error) {
3445
o := &Options{
3546
WithoutTelemetry: false,
@@ -62,9 +73,14 @@ func NewDataDogClient(address string, namespace string, options ...Option) *Data
6273
opts = append(opts, statsd.WithNamespace(namespace))
6374
}
6475

65-
c, err := statsd.New(address, opts...)
66-
if err != nil {
67-
log.Panic(err)
76+
var c *statsd.Client
77+
if o.Statsd != nil {
78+
c = o.Statsd
79+
} else {
80+
c, err = statsd.New(address, opts...)
81+
if err != nil {
82+
log.Panic(err)
83+
}
6884
}
6985

7086
return &DataDogClient{

metrics/datadog_test.go

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,29 @@ type withRater interface {
1515
}
1616

1717
func ExampleDataDogClient() {
18+
// Create a new DataDog metrics client.
1819
datadog := metrics.NewDataDogClient("127.0.0.1:8125", "myprefix")
1920
datadog.WithTags(map[string]string{
2021
"tag": "value",
2122
}).Incr("requests.count")
23+
24+
// Create a DataDog metrics client with a custom configured statsd.
25+
client, err := statsd.New("127.0.0.1:8125", statsd.WithNamespace("myprefix"))
26+
if err != nil {
27+
panic(err)
28+
}
29+
custom := metrics.NewDataDogClient("", "", metrics.WithStatsd(client))
30+
custom.WithTags(map[string]string{
31+
"tag": "value",
32+
}).Incr("requests.count")
2233
}
2334

2435
func TestDataDogClient(t *testing.T) {
2536
// This connects to an address that's probably not running anything. The
2637
// stats essentially go into `/dev/null`. Right now the only thing this
2738
// ensures is that the functions can be called without crashing.
2839
// TODO: In the future, we should use a statsd mock here.
29-
var datadog metrics.Client
30-
datadog = metrics.NewDataDogClient("127.0.0.1:8126", "testing", metrics.WithoutTelemetry())
40+
var datadog metrics.Client = metrics.NewDataDogClient("127.0.0.1:8126", "testing", metrics.WithoutTelemetry())
3141

3242
datadog.Incr("one")
3343
datadog.Event(statsd.NewEvent("title", "desc"))
@@ -85,37 +95,67 @@ func TestDataDogClient(t *testing.T) {
8595
datadog.Close()
8696
}
8797

98+
func TestDataDogCustom(t *testing.T) {
99+
client, err := statsd.New("127.0.0.1:8125", statsd.WithNamespace("myprefix"))
100+
if err != nil {
101+
panic(err)
102+
}
103+
// This should pass without error even though no address is passed in because
104+
// the client we created above does have an address.
105+
custom := metrics.NewDataDogClient("", "", metrics.WithStatsd(client))
106+
custom.WithTags(map[string]string{
107+
"tag": "value",
108+
}).Incr("requests.count")
109+
custom.Close()
110+
}
111+
88112
func Benchmark_0Tags_100Emits(b *testing.B) {
89-
benchmarkClient(b, 0, 100, false)
113+
benchmarkClient(b, 0, 100, true, false, nil)
90114
}
91115

92116
func BenchmarkTags_5Tags_100Emits(b *testing.B) {
93-
benchmarkClient(b, 5, 100, false)
117+
benchmarkClient(b, 5, 100, true, false, nil)
94118
}
95119

96120
func BenchmarkTags_5Tags_100Emits_WithInline(b *testing.B) {
97-
benchmarkClient(b, 5, 100, true)
121+
benchmarkClient(b, 5, 100, true, true, nil)
98122
}
99123

100124
func BenchmarkTags_10Tags_1000Emits(b *testing.B) {
101-
benchmarkClient(b, 10, 1000, false)
125+
benchmarkClient(b, 10, 1000, true, false, nil)
102126
}
103127

104128
func BenchmarkTags_10Tags_1000Emits_WithInline(b *testing.B) {
105-
benchmarkClient(b, 10, 1000, true)
129+
benchmarkClient(b, 10, 1000, true, true, nil)
106130
}
107131

108132
func BenchmarkTags_15Tags_100Emits(b *testing.B) {
109-
benchmarkClient(b, 15, 100, false)
133+
benchmarkClient(b, 15, 100, true, false, nil)
110134
}
111135

112136
func BenchmarkTags_15Tags_100Emits_WithInline(b *testing.B) {
113-
benchmarkClient(b, 15, 100, true)
137+
benchmarkClient(b, 15, 100, true, true, nil)
138+
}
139+
140+
func BenchmarkTags_15Tags_1000Emits_Incr(b *testing.B) {
141+
benchmarkClient(b, 15, 1000, false, false, nil)
142+
}
143+
144+
func BenchmarkTags_15Tags_1000Emits_Incr_WithInline(b *testing.B) {
145+
benchmarkClient(b, 15, 1000, false, true, nil)
146+
}
147+
148+
func BenchmarkTags_15Tags_1000Emits_Incr_NoAggr(b *testing.B) {
149+
client, _ := statsd.New("127.0.0.1:8126", statsd.WithoutClientSideAggregation())
150+
benchmarkClient(b, 15, 1000, false, false, client)
114151
}
115152

116-
func benchmarkClient(b *testing.B, numTags, numMetrics int, inlineTags bool) {
117-
var datadog metrics.Client
118-
datadog = metrics.NewDataDogClient("127.0.0.1:8126", "testing")
153+
func benchmarkClient(b *testing.B, numTags, numMetrics int, histo bool, inlineTags bool, client *statsd.Client) {
154+
options := []metrics.Option{}
155+
if client != nil {
156+
options = append(options, metrics.WithStatsd(client))
157+
}
158+
var datadog metrics.Client = metrics.NewDataDogClient("127.0.0.1:8126", "testing", options...)
119159
defer datadog.Close()
120160

121161
tags := map[string]string{}
@@ -128,10 +168,18 @@ func benchmarkClient(b *testing.B, numTags, numMetrics int, inlineTags bool) {
128168
for i := 0; i < b.N; i++ {
129169
cli := datadog.WithTags(tags)
130170
for m := 0; m < numMetrics; m++ {
131-
if inlineTags {
132-
cli.WithTags(map[string]string{"a": "b"}).Histogram("histo", 123)
171+
if histo {
172+
if inlineTags {
173+
cli.WithTags(map[string]string{"a": "b"}).Histogram("histo", 123)
174+
} else {
175+
cli.Histogram("histo", 123)
176+
}
133177
} else {
134-
cli.Histogram("histo", 123)
178+
if inlineTags {
179+
cli.WithTags(map[string]string{"a": "b"}).Incr("incr")
180+
} else {
181+
cli.Incr("incr")
182+
}
135183
}
136184
}
137185
}

0 commit comments

Comments
 (0)