statsd-instrument 3.9.0 → 3.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +12 -1
- data/lib/statsd/instrument/aggregator.rb +13 -3
- data/lib/statsd/instrument/client.rb +41 -13
- data/lib/statsd/instrument/environment.rb +7 -0
- data/lib/statsd/instrument/version.rb +1 -1
- data/test/client_test.rb +12 -0
- 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: a0d94832ea51c0d6253bc8e1d0255b3d17dc2fa46d900c8159c86855a30ed333
|
4
|
+
data.tar.gz: ce59be3645a74e337c9484834cd40f1d37ed5ee16a1ebaabd88ef6b299697e4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72350208478d416e44bb8f939d398c3359c7d45daae1c41fc39bae490fd16ea97932a107075c993cdb46ca7285cac00242acf13e0d68c21d392bc879a133b7f8
|
7
|
+
data.tar.gz: 9401843bc9a07b36028d11749a0c813a43d5f307a650ce62823d7d8e953129a148fbdbcb9cf57aec8556973a752cb3a87daf2a874244cf0bc73e62e6bfba61e0
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.3.
|
1
|
+
3.3.3
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,17 @@ section below.
|
|
6
6
|
|
7
7
|
## Unreleased changes
|
8
8
|
|
9
|
+
## Version 3.9.2
|
10
|
+
|
11
|
+
- [#381](https://github.com/Shopify/statsd-instrument/pull/381) - Reduce log level of some messages inside new Aggregator
|
12
|
+
to avoid contention and verbosity.
|
13
|
+
|
14
|
+
## Version 3.9.1
|
15
|
+
|
16
|
+
- [#378](https://github.com/Shopify/statsd-instrument/pull/378) - Respect sampling rate when aggregation is enabled, just for timing metrics.
|
17
|
+
Not respecting sampling rate, incurs in a performance penalty, as we will send more metrics than expected.
|
18
|
+
Moreover, it overloads the StatsD server, which has to send out and process more metrics than expected.
|
19
|
+
|
9
20
|
## Version 3.9.0
|
10
21
|
|
11
22
|
- Introduced an experimental aggregation feature to improve the efficiency of metrics reporting by aggregating
|
@@ -15,7 +26,7 @@ decrease the overhead associated with high-frequency metric reporting. To enable
|
|
15
26
|
- Added support for sending StatsD via Unix domain sockets. This feature is enabled by
|
16
27
|
setting the `STATSD_SOCKET` environment variable to the path of the Unix domain socket.
|
17
28
|
- :warning: **Possible breaking change**: We removed/renamed some classes and now Sinks are generic, so the classes `UDPSink` and `UDPBatchedSink` are now called
|
18
|
-
`StatsD::Instrument::Sink` and `StatsD::Instrument::
|
29
|
+
`StatsD::Instrument::Sink` and `StatsD::Instrument::BatchedSink` respectively.
|
19
30
|
If you used those internal classes, you will need to update your code to use the new classes.
|
20
31
|
|
21
32
|
## Version 3.8.0
|
@@ -24,12 +24,15 @@ module StatsD
|
|
24
24
|
end
|
25
25
|
|
26
26
|
class Aggregator
|
27
|
+
DEFAULT_MAX_CONTEXT_SIZE = 250
|
28
|
+
|
27
29
|
CONST_SAMPLE_RATE = 1.0
|
28
30
|
COUNT = :c
|
29
31
|
DISTRIBUTION = :d
|
30
32
|
MEASURE = :ms
|
31
33
|
HISTOGRAM = :h
|
32
34
|
GAUGE = :g
|
35
|
+
private_constant :COUNT, :DISTRIBUTION, :MEASURE, :HISTOGRAM, :GAUGE, :CONST_SAMPLE_RATE
|
33
36
|
|
34
37
|
class << self
|
35
38
|
def finalize(aggregation_state, sink, datagram_builders, datagram_builder_class, default_tags)
|
@@ -78,7 +81,14 @@ module StatsD
|
|
78
81
|
# @param default_tags [Array<String>] The tags to add to all metrics.
|
79
82
|
# @param flush_interval [Float] The interval at which to flush the aggregated metrics.
|
80
83
|
# @param max_values [Integer] The maximum number of values to aggregate before flushing.
|
81
|
-
def initialize(
|
84
|
+
def initialize(
|
85
|
+
sink,
|
86
|
+
datagram_builder_class,
|
87
|
+
prefix,
|
88
|
+
default_tags,
|
89
|
+
flush_interval: 5.0,
|
90
|
+
max_values: DEFAULT_MAX_CONTEXT_SIZE
|
91
|
+
)
|
82
92
|
@sink = sink
|
83
93
|
@datagram_builder_class = datagram_builder_class
|
84
94
|
@metric_prefix = prefix
|
@@ -236,11 +246,11 @@ module StatsD
|
|
236
246
|
return false unless Thread.main.alive?
|
237
247
|
|
238
248
|
if @pid != Process.pid
|
239
|
-
StatsD.logger.
|
249
|
+
StatsD.logger.debug { "[#{self.class.name}] Restarting the flush thread after fork" }
|
240
250
|
@pid = Process.pid
|
241
251
|
@aggregation_state.clear
|
242
252
|
else
|
243
|
-
StatsD.logger.
|
253
|
+
StatsD.logger.debug { "[#{self.class.name}] Restarting the flush thread" }
|
244
254
|
end
|
245
255
|
@flush_thread = Thread.new do
|
246
256
|
Thread.current.abort_on_exception = true
|
@@ -156,7 +156,8 @@ module StatsD
|
|
156
156
|
sink: StatsD::Instrument::NullSink.new,
|
157
157
|
datagram_builder_class: self.class.datagram_builder_class_for_implementation(implementation),
|
158
158
|
enable_aggregation: false,
|
159
|
-
aggregation_flush_interval: 2.0
|
159
|
+
aggregation_flush_interval: 2.0,
|
160
|
+
aggregation_max_context_size: StatsD::Instrument::Aggregator::DEFAULT_MAX_CONTEXT_SIZE
|
160
161
|
)
|
161
162
|
@sink = sink
|
162
163
|
@datagram_builder_class = datagram_builder_class
|
@@ -176,6 +177,7 @@ module StatsD
|
|
176
177
|
prefix,
|
177
178
|
default_tags,
|
178
179
|
flush_interval: @aggregation_flush_interval,
|
180
|
+
max_values: aggregation_max_context_size,
|
179
181
|
)
|
180
182
|
end
|
181
183
|
end
|
@@ -237,6 +239,19 @@ module StatsD
|
|
237
239
|
# @param tags (see #increment)
|
238
240
|
# @return [void]
|
239
241
|
def measure(name, value = nil, sample_rate: nil, tags: nil, no_prefix: false, &block)
|
242
|
+
sample_rate ||= @default_sample_rate
|
243
|
+
if sample_rate && !sample?(sample_rate)
|
244
|
+
# For all timing metrics, we have to use the sampling logic.
|
245
|
+
# Not doing so would impact performance and CPU usage.
|
246
|
+
# See Datadog's documentation for more details: https://github.com/DataDog/datadog-go/blob/20af2dbfabbbe6bd0347780cd57ed931f903f223/statsd/aggregator.go#L281-L283
|
247
|
+
|
248
|
+
if block_given?
|
249
|
+
return yield
|
250
|
+
end
|
251
|
+
|
252
|
+
return StatsD::Instrument::VOID
|
253
|
+
end
|
254
|
+
|
240
255
|
if block_given?
|
241
256
|
return latency(name, sample_rate: sample_rate, tags: tags, metric_type: :ms, no_prefix: no_prefix, &block)
|
242
257
|
end
|
@@ -245,10 +260,7 @@ module StatsD
|
|
245
260
|
@aggregator.aggregate_timing(name, value, tags: tags, no_prefix: no_prefix, type: :ms)
|
246
261
|
return StatsD::Instrument::VOID
|
247
262
|
end
|
248
|
-
sample_rate
|
249
|
-
if sample_rate.nil? || sample?(sample_rate)
|
250
|
-
emit(datagram_builder(no_prefix: no_prefix).ms(name, value, sample_rate, tags))
|
251
|
-
end
|
263
|
+
emit(datagram_builder(no_prefix: no_prefix).ms(name, value, sample_rate, tags))
|
252
264
|
StatsD::Instrument::VOID
|
253
265
|
end
|
254
266
|
|
@@ -306,6 +318,19 @@ module StatsD
|
|
306
318
|
# @param tags (see #increment)
|
307
319
|
# @return [void]
|
308
320
|
def distribution(name, value = nil, sample_rate: nil, tags: nil, no_prefix: false, &block)
|
321
|
+
sample_rate ||= @default_sample_rate
|
322
|
+
if sample_rate && !sample?(sample_rate)
|
323
|
+
# For all timing metrics, we have to use the sampling logic.
|
324
|
+
# Not doing so would impact performance and CPU usage.
|
325
|
+
# See Datadog's documentation for more details: https://github.com/DataDog/datadog-go/blob/20af2dbfabbbe6bd0347780cd57ed931f903f223/statsd/aggregator.go#L281-L283
|
326
|
+
|
327
|
+
if block_given?
|
328
|
+
return yield
|
329
|
+
end
|
330
|
+
|
331
|
+
return StatsD::Instrument::VOID
|
332
|
+
end
|
333
|
+
|
309
334
|
if block_given?
|
310
335
|
return latency(name, sample_rate: sample_rate, tags: tags, metric_type: :d, no_prefix: no_prefix, &block)
|
311
336
|
end
|
@@ -315,10 +340,7 @@ module StatsD
|
|
315
340
|
return StatsD::Instrument::VOID
|
316
341
|
end
|
317
342
|
|
318
|
-
sample_rate
|
319
|
-
if sample_rate.nil? || sample?(sample_rate)
|
320
|
-
emit(datagram_builder(no_prefix: no_prefix).d(name, value, sample_rate, tags))
|
321
|
-
end
|
343
|
+
emit(datagram_builder(no_prefix: no_prefix).d(name, value, sample_rate, tags))
|
322
344
|
StatsD::Instrument::VOID
|
323
345
|
end
|
324
346
|
|
@@ -334,14 +356,20 @@ module StatsD
|
|
334
356
|
# @param tags (see #increment)
|
335
357
|
# @return [void]
|
336
358
|
def histogram(name, value, sample_rate: nil, tags: nil, no_prefix: false)
|
359
|
+
sample_rate ||= @default_sample_rate
|
360
|
+
if sample_rate && !sample?(sample_rate)
|
361
|
+
# For all timing metrics, we have to use the sampling logic.
|
362
|
+
# Not doing so would impact performance and CPU usage.
|
363
|
+
# See Datadog's documentation for more details: https://github.com/DataDog/datadog-go/blob/20af2dbfabbbe6bd0347780cd57ed931f903f223/statsd/aggregator.go#L281-L283
|
364
|
+
return StatsD::Instrument::VOID
|
365
|
+
end
|
366
|
+
|
337
367
|
if @enable_aggregation
|
338
368
|
@aggregator.aggregate_timing(name, value, tags: tags, no_prefix: no_prefix, type: :h)
|
369
|
+
return StatsD::Instrument::VOID
|
339
370
|
end
|
340
371
|
|
341
|
-
sample_rate
|
342
|
-
if sample_rate.nil? || sample?(sample_rate)
|
343
|
-
emit(datagram_builder(no_prefix: no_prefix).h(name, value, sample_rate, tags))
|
344
|
-
end
|
372
|
+
emit(datagram_builder(no_prefix: no_prefix).h(name, value, sample_rate, tags))
|
345
373
|
StatsD::Instrument::VOID
|
346
374
|
end
|
347
375
|
|
@@ -125,6 +125,13 @@ module StatsD
|
|
125
125
|
Float(env.fetch("STATSD_AGGREGATION_INTERVAL", 2.0))
|
126
126
|
end
|
127
127
|
|
128
|
+
def aggregation_max_context_size
|
129
|
+
Integer(env.fetch(
|
130
|
+
"STATSD_AGGREGATION_MAX_CONTEXT_SIZE",
|
131
|
+
StatsD::Instrument::Aggregator::DEFAULT_MAX_CONTEXT_SIZE,
|
132
|
+
))
|
133
|
+
end
|
134
|
+
|
128
135
|
def client
|
129
136
|
StatsD::Instrument::Client.from_env(self)
|
130
137
|
end
|
data/test/client_test.rb
CHANGED
@@ -245,6 +245,18 @@ class ClientTest < Minitest::Test
|
|
245
245
|
5.times { client.increment("metric") }
|
246
246
|
end
|
247
247
|
|
248
|
+
def test_sampling_with_aggregation
|
249
|
+
mock_sink = mock("sink")
|
250
|
+
mock_sink.stubs(:sample?).returns(false, true, false, false, true)
|
251
|
+
# Since we are aggregating, we only expect a single datagram.
|
252
|
+
mock_sink.expects(:<<).with("metric:60:60|d").once
|
253
|
+
mock_sink.expects(:flush).once
|
254
|
+
|
255
|
+
client = StatsD::Instrument::Client.new(sink: mock_sink, default_sample_rate: 0.5, enable_aggregation: true)
|
256
|
+
5.times { client.distribution("metric", 60) }
|
257
|
+
client.force_flush
|
258
|
+
end
|
259
|
+
|
248
260
|
def test_clone_with_prefix_option
|
249
261
|
# Both clients will use the same sink.
|
250
262
|
mock_sink = mock("sink")
|
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.9.
|
4
|
+
version: 3.9.2
|
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: 2024-
|
13
|
+
date: 2024-10-09 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.
|
@@ -130,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '0'
|
132
132
|
requirements: []
|
133
|
-
rubygems_version: 3.5.
|
133
|
+
rubygems_version: 3.5.21
|
134
134
|
signing_key:
|
135
135
|
specification_version: 4
|
136
136
|
summary: A StatsD client for Ruby apps
|