statsd-instrument 3.9.5 → 3.9.6

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: 90a8111f77847ab11ea592d7b4a15c91a1d52b1f706b9296f29afa0c943658e8
4
- data.tar.gz: 444ef926b623f13fa9cb453b4179969a3655071a20c39b0f429dee3f22272662
3
+ metadata.gz: 62a2601a6b425e15a8f3b616fcb182d48548179d95bc5b9bbdef74f5cdabcc1d
4
+ data.tar.gz: 64a4fd724bcee0e6fe8cac4001439c6a9e0b4b9e5234cd5b654b3df4045171cf
5
5
  SHA512:
6
- metadata.gz: ead57ab89be89a51dabe4eb08c93fdd73cb5a439d5605f38305268b81e079a62c18555e1cf462ce1aa231b1928301dfe62376fa31f073c419408e478dd5cfef3
7
- data.tar.gz: 372737145878f6b8eda3c1e2d498fd40dbb7f5aa38acf13e94b93b2ace670e2bf787162dcf54b1489fb9d057ea76511b07a83b03a3bbcc740edf1c64081b403f
6
+ metadata.gz: d74d19d5e29895763d423dd0daf67bedfeeb3e05ebff891f87eda90d4482648f5cd8bb3b163c000f2fe70473ece32f9f4febf36530bcfd16ab2d9d699cf1d49d
7
+ data.tar.gz: 18d287d1d24792d9e63d7d2f2db3bee74fd929d7e4fd5ea1dccb50447a7278de7cfe8f088184064298809e70ef82b3d719dc27c5d6dc07edbc01b5747dff7246
data/CHANGELOG.md CHANGED
@@ -6,6 +6,11 @@ section below.
6
6
 
7
7
  ## Unreleased changes
8
8
 
9
+ ## Version 3.9.6
10
+
11
+ - [#388](https://github.com/Shopify/statsd-instrument/pull/388) - Properly fixing the bug when using aggregation and sending sampled
12
+ histograms, now the client will respect the sampling rate when sending the metrics and pass it down to the aggregator.
13
+
9
14
  ## Version 3.9.5
10
15
 
11
16
  - [#387](https://github.com/Shopify/statsd-instrument/pull/387) - Fixing bug when using aggregation and sending sampled
@@ -138,7 +138,7 @@ module StatsD
138
138
  def aggregate_timing(name, value, tags: [], no_prefix: false, type: DISTRIBUTION, sample_rate: CONST_SAMPLE_RATE)
139
139
  unless thread_healthcheck
140
140
  @sink << datagram_builder(no_prefix: no_prefix).timing_value_packed(
141
- name, type.to_s, [value], CONST_SAMPLE_RATE, tags
141
+ name, type.to_s, [value], sample_rate, tags
142
142
  )
143
143
  return
144
144
  end
@@ -318,25 +318,27 @@ module StatsD
318
318
  # @param tags (see #increment)
319
319
  # @return [void]
320
320
  def distribution(name, value = nil, sample_rate: nil, tags: nil, no_prefix: false, &block)
321
+ if block_given?
322
+ return latency(name, sample_rate: sample_rate, tags: tags, metric_type: :d, no_prefix: no_prefix, &block)
323
+ end
324
+
325
+ # For all timing metrics, we have to use the sampling logic.
326
+ # Not doing so would impact performance and CPU usage.
327
+ # See Datadog's documentation for more details: https://github.com/DataDog/datadog-go/blob/20af2dbfabbbe6bd0347780cd57ed931f903f223/statsd/aggregator.go#L281-L283
321
328
  sample_rate ||= @default_sample_rate
322
329
  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
330
  return StatsD::Instrument::VOID
332
331
  end
333
332
 
334
- if block_given?
335
- return latency(name, sample_rate: sample_rate, tags: tags, metric_type: :d, no_prefix: no_prefix, &block)
336
- end
337
-
338
333
  if @enable_aggregation
339
- @aggregator.aggregate_timing(name, value, tags: tags, no_prefix: no_prefix, type: :d)
334
+ @aggregator.aggregate_timing(
335
+ name,
336
+ value,
337
+ tags: tags,
338
+ no_prefix: no_prefix,
339
+ type: :d,
340
+ sample_rate: sample_rate,
341
+ )
340
342
  return StatsD::Instrument::VOID
341
343
  end
342
344
 
@@ -392,13 +394,26 @@ module StatsD
392
394
  ensure
393
395
  stop = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
394
396
 
395
- metric_type ||= datagram_builder(no_prefix: no_prefix).latency_metric_type
396
- latency_in_ms = stop - start
397
- if @enable_aggregation
398
- @aggregator.aggregate_timing(name, latency_in_ms, tags: tags, no_prefix: no_prefix, type: metric_type)
399
- else
400
- sample_rate ||= @default_sample_rate
401
- if sample_rate.nil? || sample?(sample_rate)
397
+ # For all timing metrics, we have to use the sampling logic.
398
+ # Not doing so would impact performance and CPU usage.
399
+ # See Datadog's documentation for more details:
400
+ # https://github.com/DataDog/datadog-go/blob/20af2dbfabbbe6bd0347780cd57ed931f903f223/statsd/aggregator.go#L281-L283
401
+ sample_rate ||= @default_sample_rate
402
+ if sample_rate.nil? || sample?(sample_rate)
403
+
404
+ metric_type ||= datagram_builder(no_prefix: no_prefix).latency_metric_type
405
+ latency_in_ms = stop - start
406
+
407
+ if @enable_aggregation
408
+ @aggregator.aggregate_timing(
409
+ name,
410
+ latency_in_ms,
411
+ tags: tags,
412
+ no_prefix: no_prefix,
413
+ type: metric_type,
414
+ sample_rate: sample_rate,
415
+ )
416
+ else
402
417
  emit(datagram_builder(no_prefix: no_prefix).send(metric_type, name, latency_in_ms, sample_rate, tags))
403
418
  end
404
419
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module StatsD
4
4
  module Instrument
5
- VERSION = "3.9.5"
5
+ VERSION = "3.9.6"
6
6
  end
7
7
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "test_helper"
4
- require "ostruct"
5
4
 
6
5
  class AggregatorTest < Minitest::Test
7
6
  class CaptureLogger
@@ -70,6 +69,7 @@ class AggregatorTest < Minitest::Test
70
69
  sampled_datagram = @sink.datagrams.find { |d| d.name == "timing.sampled" }
71
70
  assert_equal([60.0, 80.0], sampled_datagram.value)
72
71
  assert_equal(0.01, sampled_datagram.sample_rate)
72
+ assert_equal("timing.sampled:60.0:80.0|d|@0.01", sampled_datagram.source)
73
73
 
74
74
  unsampled_datagram = @sink.datagrams.find { |d| d.name == "timing.unsampled" }
75
75
  assert_equal(60.0, unsampled_datagram.value)
@@ -208,7 +208,7 @@ class AggregatorTest < Minitest::Test
208
208
 
209
209
  # Additional metrics should also go through synchronously
210
210
  @subject.increment("foo", 1, tags: { foo: "bar" })
211
- @subject.aggregate_timing("bar", 200, tags: { foo: "bar" })
211
+ @subject.aggregate_timing("bar", 200, tags: { foo: "bar" }, sample_rate: 0.5)
212
212
 
213
213
  # Verify new metrics were also sent immediately
214
214
  assert_equal(5, @sink.datagrams.size)
@@ -220,6 +220,7 @@ class AggregatorTest < Minitest::Test
220
220
  timing_datagram = @sink.datagrams.select { |d| d.name == "bar" }.last
221
221
  assert_equal([200.0], [timing_datagram.value])
222
222
  assert_equal(["foo:bar"], timing_datagram.tags)
223
+ assert_equal(0.5, timing_datagram.sample_rate)
223
224
 
224
225
  # undo the stubbing
225
226
  @subject.unstub(:thread_healthcheck)
data/test/client_test.rb CHANGED
@@ -90,7 +90,7 @@ class ClientTest < Minitest::Test
90
90
  client.measure("block_duration_example") { 1 + 1 }
91
91
  client.force_flush
92
92
 
93
- datagram = client.sink.datagrams.first
93
+ datagram = client.sink.datagrams.find { |d| d.name == "bar.foo" }
94
94
  assert_equal("bar.foo", datagram.name)
95
95
  assert_equal(2, datagram.value)
96
96
 
@@ -249,12 +249,17 @@ class ClientTest < Minitest::Test
249
249
  mock_sink = mock("sink")
250
250
  mock_sink.stubs(:sample?).returns(false, true, false, false, true)
251
251
  # Since we are aggregating, we only expect a single datagram.
252
- mock_sink.expects(:<<).with("metric:60:60|d").once
252
+ mock_sink.expects(:<<).with("metric:60:60|d|@0.5").once
253
253
  mock_sink.expects(:flush).once
254
254
 
255
255
  client = StatsD::Instrument::Client.new(sink: mock_sink, default_sample_rate: 0.5, enable_aggregation: true)
256
256
  5.times { client.distribution("metric", 60) }
257
257
  client.force_flush
258
+
259
+ # undo mock
260
+ mock_sink.unstub(:sample?)
261
+ mock_sink.unstub(:<<)
262
+ mock_sink.unstub(:flush)
258
263
  end
259
264
 
260
265
  def test_clone_with_prefix_option
@@ -77,4 +77,30 @@ class IntegrationTest < Minitest::Test
77
77
  assert_equal("counter:20|c", @server.recvfrom(100).first)
78
78
  assert_operator(Time.now - before_flush, :<, 0.3, "Flush and ingest should have happened within 0.4s")
79
79
  end
80
+
81
+ def test_live_local_udp_socket_with_aggregation_sampled_scenario
82
+ client = StatsD::Instrument::Environment.new(
83
+ "STATSD_ADDR" => "#{@server.addr[2]}:#{@server.addr[1]}",
84
+ "STATSD_IMPLEMENTATION" => "dogstatsd",
85
+ "STATSD_ENV" => "production",
86
+ "STATSD_ENABLE_AGGREGATION" => "true",
87
+ "STATSD_AGGREGATION_INTERVAL" => "0.1",
88
+ ).client
89
+
90
+ 100.times do
91
+ client.increment("counter", 2)
92
+ client.distribution("test_distribution", 3, sample_rate: 0.1)
93
+ end
94
+
95
+ sleep(0.2)
96
+
97
+ packets = []
98
+ while IO.select([@server], nil, nil, 0.1)
99
+ packets << @server.recvfrom(300).first
100
+ end
101
+ packets = packets.map { |packet| packet.split("\n") }.flatten
102
+
103
+ assert_match(/counter:\d+|c/, packets.find { |packet| packet.start_with?("counter:") })
104
+ assert_match(/test_distribution:\d+:3|d/, packets.find { |packet| packet.start_with?("test_distribution:") })
105
+ end
80
106
  end
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.5
4
+ version: 3.9.6
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-10-30 00:00:00.000000000 Z
13
+ date: 2024-10-31 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.