statsd-instrument 3.5.12 → 3.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/statsd/instrument/client.rb +29 -21
- data/lib/statsd/instrument/datagram_builder.rb +43 -26
- data/lib/statsd/instrument/dogstatsd_datagram_builder.rb +20 -4
- data/lib/statsd/instrument/statsd_datagram_builder.rb +2 -4
- data/lib/statsd/instrument/version.rb +1 -1
- data/test/client_test.rb +1 -1
- data/test/datagram_builder_test.rb +13 -7
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5e3cda783c5f0c7de2c30175ab001cef492c3ad0e0923af3d3a4840df7d6005
|
4
|
+
data.tar.gz: b31685696c6e1ad8e5cd36a8115eca2363ed9a732a483534004b2163453b323a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 658663a99a273170ad72436eae0142d707e35a8cc2bbf5befd89a7cd225db5673c5ec676e8f96a168411f443fa7d3e6b73f60c6f081067082b2003920cef264b
|
7
|
+
data.tar.gz: bc8930e083ec158ca6a945186c2156a0890ebe74edb63080dc6ced9ca691498edc9d81ae746ec80477471c3b2f09d3abb95042002c0c8e7d72afeb9ab360526c
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,14 @@ section below.
|
|
6
6
|
|
7
7
|
## Unreleased changes
|
8
8
|
|
9
|
+
## Version 3.6.1
|
10
|
+
|
11
|
+
- Fix `ArgumentError` when passing an empty Hash as tags.
|
12
|
+
|
13
|
+
## Version 3.6.0
|
14
|
+
|
15
|
+
- Optimized datagram building.
|
16
|
+
|
9
17
|
## Version 3.5.12
|
10
18
|
|
11
19
|
- Update CONTRIBUTING docs about release process
|
@@ -140,13 +140,15 @@ module StatsD
|
|
140
140
|
# on their frequency, rather than changing the default sample rate.
|
141
141
|
#
|
142
142
|
# @return [Float] (default: 1.0) A value between 0.0 and 1.0.
|
143
|
-
|
143
|
+
def default_sample_rate
|
144
|
+
@default_sample_rate || 1.0
|
145
|
+
end
|
144
146
|
|
145
147
|
# Instantiates a new client.
|
146
148
|
# @see .from_env to instantiate a client using environment variables.
|
147
149
|
def initialize(
|
148
150
|
prefix: nil,
|
149
|
-
default_sample_rate:
|
151
|
+
default_sample_rate: nil,
|
150
152
|
default_tags: nil,
|
151
153
|
implementation: "datadog",
|
152
154
|
sink: StatsD::Instrument::NullSink.new,
|
@@ -199,9 +201,10 @@ module StatsD
|
|
199
201
|
# @return [void]
|
200
202
|
def increment(name, value = 1, sample_rate: nil, tags: nil, no_prefix: false)
|
201
203
|
sample_rate ||= @default_sample_rate
|
202
|
-
|
203
|
-
|
204
|
-
|
204
|
+
if sample_rate.nil? || sample?(sample_rate)
|
205
|
+
emit(datagram_builder(no_prefix: no_prefix).c(name, value, sample_rate, tags))
|
206
|
+
end
|
207
|
+
StatsD::Instrument::VOID
|
205
208
|
end
|
206
209
|
|
207
210
|
# Emits a timing metric.
|
@@ -217,9 +220,10 @@ module StatsD
|
|
217
220
|
end
|
218
221
|
|
219
222
|
sample_rate ||= @default_sample_rate
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
+
if sample_rate.nil? || sample?(sample_rate)
|
224
|
+
emit(datagram_builder(no_prefix: no_prefix).ms(name, value, sample_rate, tags))
|
225
|
+
end
|
226
|
+
StatsD::Instrument::VOID
|
223
227
|
end
|
224
228
|
|
225
229
|
# Emits a gauge metric.
|
@@ -237,9 +241,10 @@ module StatsD
|
|
237
241
|
# @return [void]
|
238
242
|
def gauge(name, value, sample_rate: nil, tags: nil, no_prefix: false)
|
239
243
|
sample_rate ||= @default_sample_rate
|
240
|
-
|
241
|
-
|
242
|
-
|
244
|
+
if sample_rate.nil? || sample?(sample_rate)
|
245
|
+
emit(datagram_builder(no_prefix: no_prefix).g(name, value, sample_rate, tags))
|
246
|
+
end
|
247
|
+
StatsD::Instrument::VOID
|
243
248
|
end
|
244
249
|
|
245
250
|
# Emits a set metric, which counts distinct values.
|
@@ -251,9 +256,10 @@ module StatsD
|
|
251
256
|
# @return [void]
|
252
257
|
def set(name, value, sample_rate: nil, tags: nil, no_prefix: false)
|
253
258
|
sample_rate ||= @default_sample_rate
|
254
|
-
|
255
|
-
|
256
|
-
|
259
|
+
if sample_rate.nil? || sample?(sample_rate)
|
260
|
+
emit(datagram_builder(no_prefix: no_prefix).s(name, value, sample_rate, tags))
|
261
|
+
end
|
262
|
+
StatsD::Instrument::VOID
|
257
263
|
end
|
258
264
|
|
259
265
|
# Emits a distribution metric, which builds a histogram of the reported
|
@@ -274,9 +280,10 @@ module StatsD
|
|
274
280
|
end
|
275
281
|
|
276
282
|
sample_rate ||= @default_sample_rate
|
277
|
-
|
278
|
-
|
279
|
-
|
283
|
+
if sample_rate.nil? || sample?(sample_rate)
|
284
|
+
emit(datagram_builder(no_prefix: no_prefix).d(name, value, sample_rate, tags))
|
285
|
+
end
|
286
|
+
StatsD::Instrument::VOID
|
280
287
|
end
|
281
288
|
|
282
289
|
# Emits a histogram metric, which builds a histogram of the reported values.
|
@@ -292,9 +299,10 @@ module StatsD
|
|
292
299
|
# @return [void]
|
293
300
|
def histogram(name, value, sample_rate: nil, tags: nil, no_prefix: false)
|
294
301
|
sample_rate ||= @default_sample_rate
|
295
|
-
|
296
|
-
|
297
|
-
|
302
|
+
if sample_rate.nil? || sample?(sample_rate)
|
303
|
+
emit(datagram_builder(no_prefix: no_prefix).h(name, value, sample_rate, tags))
|
304
|
+
end
|
305
|
+
StatsD::Instrument::VOID
|
298
306
|
end
|
299
307
|
|
300
308
|
# @!endgroup
|
@@ -317,7 +325,7 @@ module StatsD
|
|
317
325
|
stop = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
|
318
326
|
|
319
327
|
sample_rate ||= @default_sample_rate
|
320
|
-
if sample?(sample_rate)
|
328
|
+
if sample_rate.nil? || sample?(sample_rate)
|
321
329
|
metric_type ||= datagram_builder(no_prefix: no_prefix).latency_metric_type
|
322
330
|
latency_in_ms = stop - start
|
323
331
|
emit(datagram_builder(no_prefix: no_prefix).send(metric_type, name, latency_in_ms, sample_rate, tags))
|
@@ -20,8 +20,8 @@ module StatsD
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def initialize(prefix: nil, default_tags: nil)
|
23
|
-
@prefix = prefix.nil? ? "" : "#{
|
24
|
-
@default_tags =
|
23
|
+
@prefix = prefix.nil? ? "" : "#{prefix}.".tr(":|@", "_")
|
24
|
+
@default_tags = default_tags.nil? || default_tags.empty? ? nil : compile_tags(default_tags, "|#".b)
|
25
25
|
end
|
26
26
|
|
27
27
|
def c(name, value, sample_rate, tags)
|
@@ -58,26 +58,6 @@ module StatsD
|
|
58
58
|
|
59
59
|
protected
|
60
60
|
|
61
|
-
attr_reader :prefix, :default_tags
|
62
|
-
|
63
|
-
# Utility function to convert tags to the canonical form.
|
64
|
-
#
|
65
|
-
# - Tags specified as key value pairs will be converted into an array
|
66
|
-
# - Tags are normalized to remove unsupported characters
|
67
|
-
#
|
68
|
-
# @param tags [Array<String>, Hash<String, String>, nil] Tags specified in any form.
|
69
|
-
# @return [Array<String>, nil] the list of tags in canonical form.
|
70
|
-
def normalize_tags(tags)
|
71
|
-
return [] unless tags
|
72
|
-
|
73
|
-
tags = tags.map { |k, v| "#{k}:#{v}" } if tags.is_a?(Hash)
|
74
|
-
|
75
|
-
# Fast path when no string replacement is needed
|
76
|
-
return tags unless tags.any? { |tag| /[|,]/.match?(tag) }
|
77
|
-
|
78
|
-
tags.map { |tag| tag.tr("|,", "") }
|
79
|
-
end
|
80
|
-
|
81
61
|
# Utility function to remove invalid characters from a StatsD metric name
|
82
62
|
def normalize_name(name)
|
83
63
|
# Fast path when no normalization is needed to avoid copying the string
|
@@ -87,12 +67,49 @@ module StatsD
|
|
87
67
|
end
|
88
68
|
|
89
69
|
def generate_generic_datagram(name, value, type, sample_rate, tags)
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
70
|
+
datagram = "".b <<
|
71
|
+
@prefix <<
|
72
|
+
(/[:|@]/.match?(name) ? name.tr(":|@", "_") : name) <<
|
73
|
+
":" << value.to_s <<
|
74
|
+
"|" << type
|
75
|
+
|
76
|
+
datagram << "|@" << sample_rate.to_s if sample_rate && sample_rate < 1
|
77
|
+
|
78
|
+
unless @default_tags.nil?
|
79
|
+
datagram << @default_tags
|
80
|
+
end
|
81
|
+
|
82
|
+
unless tags.nil? || tags.empty?
|
83
|
+
datagram << (@default_tags.nil? ? "|#" : ",")
|
84
|
+
compile_tags(tags, datagram)
|
85
|
+
end
|
86
|
+
|
94
87
|
datagram
|
95
88
|
end
|
89
|
+
|
90
|
+
def compile_tags(tags, buffer = "".b)
|
91
|
+
if tags.is_a?(Hash)
|
92
|
+
first = true
|
93
|
+
tags.each do |key, value|
|
94
|
+
if first
|
95
|
+
first = false
|
96
|
+
else
|
97
|
+
buffer << ","
|
98
|
+
end
|
99
|
+
key = key.to_s
|
100
|
+
key = key.tr("|,", "") if /[|,]/.match?(key)
|
101
|
+
value = value.to_s
|
102
|
+
value = value.tr("|,", "") if /[|,]/.match?(value)
|
103
|
+
buffer << key << ":" << value
|
104
|
+
end
|
105
|
+
else
|
106
|
+
if tags.any? { |tag| /[|,]/.match?(tag) }
|
107
|
+
tags = tags.map { |tag| tag.tr("|,", "") }
|
108
|
+
end
|
109
|
+
buffer << tags.join(",")
|
110
|
+
end
|
111
|
+
buffer
|
112
|
+
end
|
96
113
|
end
|
97
114
|
end
|
98
115
|
end
|
@@ -36,7 +36,6 @@ module StatsD
|
|
36
36
|
|
37
37
|
escaped_title = "#{@prefix}#{title}".gsub("\n", '\n')
|
38
38
|
escaped_text = text.gsub("\n", '\n')
|
39
|
-
tags = normalize_tags(tags) + default_tags
|
40
39
|
|
41
40
|
datagram = +"_e{#{escaped_title.length},#{escaped_text.length}}:#{escaped_title}|#{escaped_text}"
|
42
41
|
datagram << "|h:#{hostname}" if hostname
|
@@ -45,7 +44,16 @@ module StatsD
|
|
45
44
|
datagram << "|p:#{priority}" if priority
|
46
45
|
datagram << "|s:#{source_type_name}" if source_type_name
|
47
46
|
datagram << "|t:#{alert_type}" if alert_type
|
48
|
-
|
47
|
+
|
48
|
+
unless @default_tags.nil?
|
49
|
+
datagram << @default_tags
|
50
|
+
end
|
51
|
+
|
52
|
+
unless tags.nil? || tags.empty?
|
53
|
+
datagram << (@default_tags.nil? ? "|#" : ",")
|
54
|
+
compile_tags(tags, datagram)
|
55
|
+
end
|
56
|
+
|
49
57
|
datagram
|
50
58
|
end
|
51
59
|
|
@@ -63,12 +71,20 @@ module StatsD
|
|
63
71
|
# @see https://docs.datadoghq.com/developers/dogstatsd/datagram_shell/#service-checks
|
64
72
|
def _sc(name, status, timestamp: nil, hostname: nil, tags: nil, message: nil)
|
65
73
|
status_number = status.is_a?(Integer) ? status : SERVICE_CHECK_STATUS_VALUES.fetch(status.to_sym)
|
66
|
-
tags = normalize_tags(tags) + default_tags
|
67
74
|
|
68
75
|
datagram = +"_sc|#{@prefix}#{normalize_name(name)}|#{status_number}"
|
69
76
|
datagram << "|h:#{hostname}" if hostname
|
70
77
|
datagram << "|d:#{timestamp.to_i}" if timestamp
|
71
|
-
|
78
|
+
|
79
|
+
unless @default_tags.nil?
|
80
|
+
datagram << @default_tags
|
81
|
+
end
|
82
|
+
|
83
|
+
unless tags.nil? || tags.empty?
|
84
|
+
datagram << (@default_tags.nil? ? "|#" : ",")
|
85
|
+
compile_tags(tags, datagram)
|
86
|
+
end
|
87
|
+
|
72
88
|
datagram << "|m:#{normalize_name(message)}" if message
|
73
89
|
datagram
|
74
90
|
end
|
@@ -9,10 +9,8 @@ module StatsD
|
|
9
9
|
|
10
10
|
protected
|
11
11
|
|
12
|
-
def
|
13
|
-
raise NotImplementedError, "#{self.class.name} does not support tags"
|
14
|
-
|
15
|
-
super
|
12
|
+
def compile_tags(*)
|
13
|
+
raise NotImplementedError, "#{self.class.name} does not support tags"
|
16
14
|
end
|
17
15
|
end
|
18
16
|
end
|
data/test/client_test.rb
CHANGED
@@ -206,7 +206,7 @@ class ClientTest < Minitest::Test
|
|
206
206
|
mock_sink.stubs(:sample?).returns(false, true, false, false, true)
|
207
207
|
mock_sink.expects(:<<).twice
|
208
208
|
|
209
|
-
client = StatsD::Instrument::Client.new(sink: mock_sink)
|
209
|
+
client = StatsD::Instrument::Client.new(sink: mock_sink, default_sample_rate: 0.5)
|
210
210
|
5.times { client.increment("metric") }
|
211
211
|
end
|
212
212
|
|
@@ -14,17 +14,17 @@ class DatagramBuilderTest < Minitest::Test
|
|
14
14
|
assert_equal("fo_o", @datagram_builder.send(:normalize_name, "fo:o"))
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
assert_equal(
|
17
|
+
def test_compile_unsupported_tag_names
|
18
|
+
assert_equal("ign#ored", @datagram_builder.send(:compile_tags, ["ign#o|re,d"]))
|
19
19
|
# NOTE: how this is interpreted by the backend is undefined.
|
20
20
|
# We rely on the user to not do stuff like this if they don't want to be surprised.
|
21
21
|
# We do not want to take the performance hit of normalizing this.
|
22
|
-
assert_equal(
|
22
|
+
assert_equal("lol::class:omg::lol", @datagram_builder.send(:compile_tags, { "lol::class" => "omg::lol" }))
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
26
|
-
assert_equal(
|
27
|
-
assert_equal(
|
25
|
+
def test_compile_tags_converts_hash_to_array
|
26
|
+
assert_equal("tag:value", @datagram_builder.send(:compile_tags, { tag: "value" }))
|
27
|
+
assert_equal("tag1:v1,tag2:v2", @datagram_builder.send(:compile_tags, { tag1: "v1", tag2: "v2" }))
|
28
28
|
end
|
29
29
|
|
30
30
|
def test_c
|
@@ -76,6 +76,12 @@ class DatagramBuilderTest < Minitest::Test
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def test_tags
|
79
|
+
datagram = @datagram_builder.d("foo", 10, nil, {})
|
80
|
+
assert_equal("foo:10|d", datagram)
|
81
|
+
|
82
|
+
datagram = @datagram_builder.d("foo", 10, nil, [])
|
83
|
+
assert_equal("foo:10|d", datagram)
|
84
|
+
|
79
85
|
datagram = @datagram_builder.d("foo", 10, nil, ["foo", "bar"])
|
80
86
|
assert_equal("foo:10|d|#foo,bar", datagram)
|
81
87
|
|
@@ -103,7 +109,7 @@ class DatagramBuilderTest < Minitest::Test
|
|
103
109
|
assert_equal("bar:1|c|#foo", datagram)
|
104
110
|
|
105
111
|
datagram = datagram_builder.c("bar", 1, nil, a: "b")
|
106
|
-
assert_equal("bar:1|c|#a:b
|
112
|
+
assert_equal("bar:1|c|#foo,a:b", datagram)
|
107
113
|
|
108
114
|
# We do not filter out duplicates, because detecting dupes is too time consuming.
|
109
115
|
# We let the server deal with the situation
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: statsd-instrument
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jesse Storimer
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-
|
13
|
+
date: 2023-11-06 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: A StatsD client for Ruby apps. Provides metaprogramming methods to inject
|
16
16
|
StatsD instrumentation into your code.
|
@@ -122,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
122
|
- !ruby/object:Gem::Version
|
123
123
|
version: '0'
|
124
124
|
requirements: []
|
125
|
-
rubygems_version: 3.4.
|
125
|
+
rubygems_version: 3.4.21
|
126
126
|
signing_key:
|
127
127
|
specification_version: 4
|
128
128
|
summary: A StatsD client for Ruby apps
|