statsd-instrument 3.9.0 → 3.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|