Skip to content

Commit daf7f42

Browse files
Merge pull request #14 from istreamlabs/optimize-tags
Optimize tag handling
2 parents af57a97 + c02370b commit daf7f42

File tree

13 files changed

+209
-26
lines changed

13 files changed

+209
-26
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77
## [Unreleased]
88
- Put unreleased items here.
99

10+
## [2.0.0] - 2020-05-28
11+
12+
- Go module support
13+
- Go 1.12-1.14 support
14+
- Upgrade to datadog-go 3.x
15+
- Adds support for DataDog Distributions: https://docs.datadoghq.com/metrics/distributions/
16+
- Adds Close() to Client interface to support intentional flushes when applications are shutting down
17+
- Optimize tag handling
18+
1019
## [1.4.0] - 2019-08-26
1120

1221
- Updated `datadog-go` to version `2.2.0`

Gopkg.lock

Lines changed: 56 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Gopkg.toml example
2+
#
3+
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
4+
# for detailed Gopkg.toml documentation.
5+
#
6+
# required = ["github.com/user/thing/cmd/thing"]
7+
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
8+
#
9+
# [[constraint]]
10+
# name = "github.com/user/project"
11+
# version = "1.0.0"
12+
#
13+
# [[constraint]]
14+
# name = "github.com/user/project2"
15+
# branch = "dev"
16+
# source = "github.com/myfork/project2"
17+
#
18+
# [[override]]
19+
# name = "github.com/x/y"
20+
# version = "2.4.0"
21+
#
22+
# [prune]
23+
# non-go = false
24+
# go-tests = true
25+
# unused-packages = true
26+
27+
28+
[[constraint]]
29+
name = "github.com/DataDog/datadog-go"
30+
version = "3.7.1"
31+
32+
[[constraint]]
33+
name = "github.com/mattn/go-isatty"
34+
version = "0.0.12"
35+
36+
[[constraint]]
37+
branch = "master"
38+
name = "github.com/mgutz/ansi"
39+
40+
[prune]
41+
go-tests = true
42+
unused-packages = true

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ if os.Getenv("env") == "prod" {
3737
// Log to standard out instead of sending production metrics.
3838
client = metrics.NewLoggerClient(nil)
3939
}
40+
defer client.Close()
4041

4142
// Simple incrementing counter
4243
client.Incr("requests.count")

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ module github.com/istreamlabs/go-metrics
33
go 1.12
44

55
require (
6-
github.com/DataDog/datadog-go v3.4.1+incompatible
6+
github.com/DataDog/datadog-go v3.7.1+incompatible
77
github.com/mattn/go-colorable v0.1.6 // indirect
88
github.com/mattn/go-isatty v0.0.12
99
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
1010
github.com/stretchr/testify v1.5.1 // indirect
1111
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect
12+
gopkg.in/go-playground/assert.v1 v1.2.1
1213
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
github.com/DataDog/datadog-go v3.4.1+incompatible h1:hRUopimy+td4Lc3QDvP/hsbQKI3n5xsmGJTRghwaA7U=
22
github.com/DataDog/datadog-go v3.4.1+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
3+
github.com/DataDog/datadog-go v3.7.1+incompatible h1:HmA9qHVrHIAqpSvoCYJ+c6qst0lgqEhNW6/KwfkHbS8=
4+
github.com/DataDog/datadog-go v3.7.1+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
35
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
46
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
57
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
@@ -20,5 +22,7 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0
2022
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
2123
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
2224
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
25+
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
26+
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
2327
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
2428
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

metrics/datadog.go

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
type DataDogClient struct {
1212
client *statsd.Client
1313
rate float64
14-
tagMap map[string]string
14+
tags []string
1515
}
1616

1717
// NewDataDogClient creates a new dogstatsd client pointing to `address` with
@@ -39,7 +39,7 @@ func (c *DataDogClient) WithRate(rate float64) Client {
3939
return &DataDogClient{
4040
client: c.client,
4141
rate: rate,
42-
tagMap: combine(c.tagMap, map[string]string{}),
42+
tags: c.tags, // clone isn't necessary since original slice is immutable
4343
}
4444
}
4545

@@ -49,22 +49,18 @@ func (c *DataDogClient) WithTags(tags map[string]string) Client {
4949
return &DataDogClient{
5050
client: c.client,
5151
rate: c.rate,
52-
tagMap: combine(c.tagMap, tags),
52+
tags: cloneTagsWithMap(c.tags, tags),
5353
}
5454
}
5555

56-
func (c *DataDogClient) tagsList() []string {
57-
return mapToStrings(c.tagMap)
58-
}
59-
6056
// Close closes all client connections and flushes any buffered data.
6157
func (c *DataDogClient) Close() error {
6258
return c.client.Close()
6359
}
6460

6561
// Count adds some integer value to a metric.
6662
func (c *DataDogClient) Count(name string, value int64) {
67-
c.client.Count(name, value, c.tagsList(), c.rate)
63+
c.client.Count(name, value, c.tags, c.rate)
6864
}
6965

7066
// Incr adds one to a metric.
@@ -79,29 +75,29 @@ func (c *DataDogClient) Decr(name string) {
7975

8076
// Gauge sets a numeric value.
8177
func (c *DataDogClient) Gauge(name string, value float64) {
82-
c.client.Gauge(name, value, c.tagsList(), c.rate)
78+
c.client.Gauge(name, value, c.tags, c.rate)
8379
}
8480

8581
// Event tracks an event that may be relevant to other metrics.
8682
func (c *DataDogClient) Event(e *statsd.Event) {
87-
if len(c.tagMap) > 0 {
88-
e.Tags = append(e.Tags, c.tagsList()...)
83+
if len(c.tags) > 0 {
84+
e.Tags = append(e.Tags, c.tags...)
8985
}
9086

9187
c.client.Event(e)
9288
}
9389

9490
// Timing tracks a duration.
9591
func (c *DataDogClient) Timing(name string, value time.Duration) {
96-
c.client.Timing(name, value, c.tagsList(), c.rate)
92+
c.client.Timing(name, value, c.tags, c.rate)
9793
}
9894

9995
// Histogram sets a numeric value while tracking min/max/avg/p95/etc.
10096
func (c *DataDogClient) Histogram(name string, value float64) {
101-
c.client.Histogram(name, value, c.tagsList(), c.rate)
97+
c.client.Histogram(name, value, c.tags, c.rate)
10298
}
10399

104100
// Distribution tracks the statistical distribution of a set of values.
105101
func (c *DataDogClient) Distribution(name string, value float64) {
106-
c.client.Distribution(name, value, c.tagsList(), c.rate)
102+
c.client.Distribution(name, value, c.tags, c.rate)
107103
}

metrics/datadog_test.go

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package metrics_test
22

33
import (
4+
"fmt"
45
"reflect"
56
"testing"
67
"time"
@@ -51,15 +52,18 @@ func TestDataDogClient(t *testing.T) {
5152
// Test that tag overrides work.
5253
override := datadog.WithTags(map[string]string{
5354
"tag1": "value1",
55+
"tag2": "value2",
5456
}).WithTags(map[string]string{
5557
"tag1": "override",
56-
"tag2": "value2",
58+
"tag3": "value3",
5759
})
5860

59-
actual := override.(*metrics.DataDogClient).TagMap()
60-
expected := map[string]string{
61-
"tag1": "override",
62-
"tag2": "value2",
61+
actual := override.(*metrics.DataDogClient).Tags()
62+
expected := []string{
63+
"tag1:override",
64+
"tag1:value1",
65+
"tag2:value2",
66+
"tag3:value3",
6367
}
6468
if !reflect.DeepEqual(actual, expected) {
6569
t.Fatalf("Expected %v to equal %v", actual, expected)
@@ -80,3 +84,55 @@ func TestDataDogClient(t *testing.T) {
8084

8185
datadog.Close()
8286
}
87+
88+
func Benchmark_0Tags_100Emits(b *testing.B) {
89+
benchmarkClient(b, 0, 100, false)
90+
}
91+
92+
func BenchmarkTags_5Tags_100Emits(b *testing.B) {
93+
benchmarkClient(b, 5, 100, false)
94+
}
95+
96+
func BenchmarkTags_5Tags_100Emits_WithInline(b *testing.B) {
97+
benchmarkClient(b, 5, 100, true)
98+
}
99+
100+
func BenchmarkTags_10Tags_1000Emits(b *testing.B) {
101+
benchmarkClient(b, 10, 1000, false)
102+
}
103+
104+
func BenchmarkTags_10Tags_1000Emits_WithInline(b *testing.B) {
105+
benchmarkClient(b, 10, 1000, true)
106+
}
107+
108+
func BenchmarkTags_15Tags_100Emits(b *testing.B) {
109+
benchmarkClient(b, 15, 100, false)
110+
}
111+
112+
func BenchmarkTags_15Tags_100Emits_WithInline(b *testing.B) {
113+
benchmarkClient(b, 15, 100, true)
114+
}
115+
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")
119+
defer datadog.Close()
120+
121+
tags := map[string]string{}
122+
for i := 0; i < numTags; i++ {
123+
tags[fmt.Sprintf("tag-%v", i)] = fmt.Sprintf("value-%v", i)
124+
}
125+
126+
b.ResetTimer()
127+
b.ReportAllocs()
128+
for i := 0; i < b.N; i++ {
129+
cli := datadog.WithTags(tags)
130+
for m := 0; m < numMetrics; m++ {
131+
if inlineTags {
132+
cli.WithTags(map[string]string{"a": "b"}).Histogram("histo", 123)
133+
} else {
134+
cli.Histogram("histo", 123)
135+
}
136+
}
137+
}
138+
}

metrics/export_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package metrics
22

3-
// TagMap returns the internal tag map from a DataDog client instance.
4-
func (c *DataDogClient) TagMap() map[string]string {
5-
return c.tagMap
3+
import "sort"
4+
5+
// Tags returns the internal tag list from a DataDog client instance.
6+
func (c *DataDogClient) Tags() []string {
7+
sort.Strings(c.tags)
8+
return c.tags
69
}

metrics/logger.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func (c *LoggerClient) Colorized() *LoggerClient {
7272
logger: c.logger,
7373
rate: c.rate,
7474
colors: true,
75-
tagMap: combine(map[string]string{}, c.tagMap),
75+
tagMap: c.tagMap,
7676
}
7777
}
7878

@@ -94,7 +94,7 @@ func (c *LoggerClient) WithRate(rate float64) Client {
9494
logger: c.logger,
9595
rate: rate,
9696
colors: c.colors,
97-
tagMap: combine(map[string]string{}, c.tagMap),
97+
tagMap: c.tagMap,
9898
}
9999
}
100100

0 commit comments

Comments
 (0)