statsd-instrument 3.9.0 → 3.9.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9776ac7b9f3dc12364a1ba286d7b77330c52b0aa8560c29c0ff47c8033c066df
4
- data.tar.gz: ecfc23f01f345eabc82d1c696c2fb280cc3185f2d30b47e8e5c75326077f10bd
3
+ metadata.gz: 436100176f41a4557dfad3169208a34581a4a51ed03532857ce0192ef0586f95
4
+ data.tar.gz: 888b9d6dcab8741aede0db4044f9a4d5ce0eb146ce016037b5ee278296f1f2a1
5
5
  SHA512:
6
- metadata.gz: e831388ae5824bd7d1e53b9eefc399dd639210648976adeafd48fabd9d4a37705af2d5814868e75922cc27840cba42d5066054751a8120e4ea8d055efdaea379
7
- data.tar.gz: 91f63290ef5d9dcc032e0fcdad8e34acdc5448d563e1eedd71b23a68330060ba58af3999ace24b4a82567f2e5c96182996c3f8dda940684a1df93fe9acee02ef
6
+ metadata.gz: 181b505253e000ae9f4b457716e4715227dbdc81d85357bedc335296af681d2975e4da0062abd4028b87d37462cd3ae5280f1033886a1b96a9bf566c32cf7930
7
+ data.tar.gz: cbc3e3cb9ed41abfda94075eeb4e25e29445f42447af826616cc3545419be2e4ceeab273183bbb56af3e166066ef5bb02ed19ac09b4467782c0184e5251e454f
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.3.1
1
+ 3.3.3
data/CHANGELOG.md CHANGED
@@ -6,6 +6,12 @@ section below.
6
6
 
7
7
  ## Unreleased changes
8
8
 
9
+ ## Version 3.9.1
10
+
11
+ - [#378](https://github.com/Shopify/statsd-instrument/pull/378) - Respect sampling rate when aggregation is enabled, just for timing metrics.
12
+ Not respecting sampling rate, incurs in a performance penalty, as we will send more metrics than expected.
13
+ Moreover, it overloads the StatsD server, which has to send out and process more metrics than expected.
14
+
9
15
  ## Version 3.9.0
10
16
 
11
17
  - Introduced an experimental aggregation feature to improve the efficiency of metrics reporting by aggregating
@@ -15,7 +21,7 @@ decrease the overhead associated with high-frequency metric reporting. To enable
15
21
  - Added support for sending StatsD via Unix domain sockets. This feature is enabled by
16
22
  setting the `STATSD_SOCKET` environment variable to the path of the Unix domain socket.
17
23
  - :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::Sink` respectively.
24
+ `StatsD::Instrument::Sink` and `StatsD::Instrument::BatchedSink` respectively.
19
25
  If you used those internal classes, you will need to update your code to use the new classes.
20
26
 
21
27
  ## 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(sink, datagram_builder_class, prefix, default_tags, flush_interval: 5.0, max_values: 100)
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
@@ -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 ||= @default_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 ||= @default_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 ||= @default_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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module StatsD
4
4
  module Instrument
5
- VERSION = "3.9.0"
5
+ VERSION = "3.9.1"
6
6
  end
7
7
  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.0
4
+ version: 3.9.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: 2024-08-19 00:00:00.000000000 Z
13
+ date: 2024-09-16 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.17
133
+ rubygems_version: 3.5.18
134
134
  signing_key:
135
135
  specification_version: 4
136
136
  summary: A StatsD client for Ruby apps