statsd-instrument 3.9.4 → 3.9.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8248b85fead25773388f7bec728c5a6347f7b7af61e37e064ee8ed93ba31397d
4
- data.tar.gz: 110ab2e5db1b66ef7c76e11ed7b82c925f767df0b09a1ca442afe95c31e30a40
3
+ metadata.gz: 90a8111f77847ab11ea592d7b4a15c91a1d52b1f706b9296f29afa0c943658e8
4
+ data.tar.gz: 444ef926b623f13fa9cb453b4179969a3655071a20c39b0f429dee3f22272662
5
5
  SHA512:
6
- metadata.gz: e85d2333cae7f6e843b25b3a1e64cf8bd1e68e47bcb530b6483dfa05e2672374791209c65f888cc6c9354f0e5bca997098f776c5db10f4dfd155005dd3f22bc9
7
- data.tar.gz: 330d5d152a42dd76fae018e4af8c4daa64f9be50391468f64bd338ddd91ecd668a6775f590e45452b552c6fe28f0e82e125a3a91476d5269e52d19ad0adee092
6
+ metadata.gz: ead57ab89be89a51dabe4eb08c93fdd73cb5a439d5605f38305268b81e079a62c18555e1cf462ce1aa231b1928301dfe62376fa31f073c419408e478dd5cfef3
7
+ data.tar.gz: 372737145878f6b8eda3c1e2d498fd40dbb7f5aa38acf13e94b93b2ace670e2bf787162dcf54b1489fb9d057ea76511b07a83b03a3bbcc740edf1c64081b403f
data/CHANGELOG.md CHANGED
@@ -6,6 +6,11 @@ section below.
6
6
 
7
7
  ## Unreleased changes
8
8
 
9
+ ## Version 3.9.5
10
+
11
+ - [#387](https://github.com/Shopify/statsd-instrument/pull/387) - Fixing bug when using aggregation and sending sampled
12
+ histogram metrics, they will not be scaled properly because of missing sampling rate in the final sent sample.
13
+
9
14
  ## Version 3.9.4
10
15
 
11
16
  - [#384](https://github.com/Shopify/statsd-instrument/pull/384) - Aggregation: fixing bug when sending metrics synchronously
@@ -3,13 +3,14 @@
3
3
  module StatsD
4
4
  module Instrument
5
5
  class AggregationKey
6
- attr_reader :name, :tags, :no_prefix, :type, :hash
6
+ attr_reader :name, :tags, :no_prefix, :type, :hash, :sample_rate
7
7
 
8
- def initialize(name, tags, no_prefix, type)
8
+ def initialize(name, tags, no_prefix, type, sample_rate: 1.0)
9
9
  @name = name
10
10
  @tags = tags
11
11
  @no_prefix = no_prefix
12
12
  @type = type
13
+ @sample_rate = sample_rate
13
14
  @hash = [@name, @tags, @no_prefix, @type].hash
14
15
  end
15
16
 
@@ -56,7 +57,7 @@ module StatsD
56
57
  key.name,
57
58
  key.type.to_s,
58
59
  agg_value,
59
- CONST_SAMPLE_RATE,
60
+ key.sample_rate,
60
61
  key.tags,
61
62
  )
62
63
  when GAUGE
@@ -134,7 +135,7 @@ module StatsD
134
135
  end
135
136
  end
136
137
 
137
- def aggregate_timing(name, value, tags: [], no_prefix: false, type: DISTRIBUTION)
138
+ def aggregate_timing(name, value, tags: [], no_prefix: false, type: DISTRIBUTION, sample_rate: CONST_SAMPLE_RATE)
138
139
  unless thread_healthcheck
139
140
  @sink << datagram_builder(no_prefix: no_prefix).timing_value_packed(
140
141
  name, type.to_s, [value], CONST_SAMPLE_RATE, tags
@@ -143,7 +144,7 @@ module StatsD
143
144
  end
144
145
 
145
146
  tags = tags_sorted(tags)
146
- key = packet_key(name, tags, no_prefix, type)
147
+ key = packet_key(name, tags, no_prefix, type, sample_rate: sample_rate)
147
148
 
148
149
  @mutex.synchronize do
149
150
  values = @aggregation_state[key] ||= []
@@ -176,6 +177,9 @@ module StatsD
176
177
 
177
178
  EMPTY_ARRAY = [].freeze
178
179
 
180
+ # Flushes the aggregated metrics to the sink.
181
+ # Iterates over the aggregation state and sends each metric to the sink.
182
+ # If you change this function, you need to update the logic in the finalizer as well.
179
183
  def do_flush
180
184
  @aggregation_state.each do |key, value|
181
185
  case key.type
@@ -191,7 +195,7 @@ module StatsD
191
195
  key.name,
192
196
  key.type.to_s,
193
197
  value,
194
- CONST_SAMPLE_RATE,
198
+ key.sample_rate,
195
199
  key.tags,
196
200
  )
197
201
  when GAUGE
@@ -219,8 +223,14 @@ module StatsD
219
223
  datagram_builder(no_prefix: false).normalize_tags(tags)
220
224
  end
221
225
 
222
- def packet_key(name, tags = "".b, no_prefix = false, type = COUNT)
223
- AggregationKey.new(DatagramBuilder.normalize_string(name), tags, no_prefix, type).freeze
226
+ def packet_key(name, tags = "".b, no_prefix = false, type = COUNT, sample_rate: CONST_SAMPLE_RATE)
227
+ AggregationKey.new(
228
+ DatagramBuilder.normalize_string(name),
229
+ tags,
230
+ no_prefix,
231
+ type,
232
+ sample_rate: sample_rate,
233
+ ).freeze
224
234
  end
225
235
 
226
236
  def datagram_builder(no_prefix:)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module StatsD
4
4
  module Instrument
5
- VERSION = "3.9.4"
5
+ VERSION = "3.9.5"
6
6
  end
7
7
  end
@@ -58,6 +58,23 @@ class AggregatorTest < Minitest::Test
58
58
  assert_equal([1.0, 100.0], datagram.value)
59
59
  end
60
60
 
61
+ def test_timing_sampling_scaling
62
+ @subject.aggregate_timing("timing.sampled", 60.0, sample_rate: 0.01)
63
+ @subject.aggregate_timing("timing.sampled", 80.0, sample_rate: 0.01)
64
+ @subject.aggregate_timing("timing.unsampled", 60.0, sample_rate: 1.0)
65
+
66
+ @subject.flush
67
+
68
+ assert_equal(2, @sink.datagrams.size)
69
+
70
+ sampled_datagram = @sink.datagrams.find { |d| d.name == "timing.sampled" }
71
+ assert_equal([60.0, 80.0], sampled_datagram.value)
72
+ assert_equal(0.01, sampled_datagram.sample_rate)
73
+
74
+ unsampled_datagram = @sink.datagrams.find { |d| d.name == "timing.unsampled" }
75
+ assert_equal(60.0, unsampled_datagram.value)
76
+ end
77
+
61
78
  def test_mixed_type_timings
62
79
  @subject.aggregate_timing("foo_ms", 1, tags: { foo: "bar" }, type: :ms)
63
80
  @subject.aggregate_timing("foo_ms", 100, tags: { foo: "bar" }, type: :ms)
@@ -304,6 +321,7 @@ class AggregatorTest < Minitest::Test
304
321
  @subject.increment("foo", 1, tags: { foo: "bar" })
305
322
  @subject.aggregate_timing("bar", 100, tags: { foo: "bar" })
306
323
  @subject.gauge("baz", 100, tags: { foo: "bar" })
324
+ @subject.aggregate_timing("sampled_timing", 100, tags: { foo: "bar" }, sample_rate: 0.01)
307
325
 
308
326
  # Manually trigger the finalizer
309
327
  finalizer = StatsD::Instrument::Aggregator.finalize(
@@ -316,7 +334,7 @@ class AggregatorTest < Minitest::Test
316
334
  finalizer.call
317
335
 
318
336
  # Verify that all pending metrics are sent
319
- assert_equal(3, @sink.datagrams.size)
337
+ assert_equal(4, @sink.datagrams.size)
320
338
 
321
339
  counter_datagram = @sink.datagrams.find { |d| d.name == "foo" }
322
340
  assert_equal(1, counter_datagram.value)
@@ -329,5 +347,9 @@ class AggregatorTest < Minitest::Test
329
347
  gauge_datagram = @sink.datagrams.find { |d| d.name == "baz" }
330
348
  assert_equal(100, gauge_datagram.value)
331
349
  assert_equal(["foo:bar"], gauge_datagram.tags)
350
+
351
+ sampled_timing_datagram = @sink.datagrams.find { |d| d.name == "sampled_timing" }
352
+ assert_equal(100.0, sampled_timing_datagram.value)
353
+ assert_equal(0.01, sampled_timing_datagram.sample_rate)
332
354
  end
333
355
  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.4
4
+ version: 3.9.5
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-29 00:00:00.000000000 Z
13
+ date: 2024-10-30 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.