statsd-instrument 3.8.0 → 3.9.0

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.
@@ -107,7 +107,8 @@ module UDPSinkTests
107
107
  private
108
108
 
109
109
  def build_sink(host = @host, port = @port)
110
- @sink_class.new(host, port)
110
+ connection = StatsD::Instrument::UdpConnection.new(host, port)
111
+ StatsD::Instrument::Sink.new(connection)
111
112
  end
112
113
 
113
114
  def read_datagrams(count, timeout: ENV["CI"] ? 5 : 1)
@@ -132,7 +133,7 @@ class UDPSinkTest < Minitest::Test
132
133
  @receiver.bind("localhost", 0)
133
134
  @host = @receiver.addr[2]
134
135
  @port = @receiver.addr[1]
135
- @sink_class = StatsD::Instrument::UDPSink
136
+ @sink_class = StatsD::Instrument::Sink
136
137
  end
137
138
 
138
139
  def teardown
@@ -167,7 +168,7 @@ class UDPSinkTest < Minitest::Test
167
168
  ensure
168
169
  StatsD.logger = previous_logger
169
170
  # Make sure our fake socket is closed so that it doesn't interfere with other tests
170
- udp_sink&.send(:invalidate_socket)
171
+ udp_sink&.send(:invalidate_connection)
171
172
  end
172
173
  end
173
174
  end
@@ -180,7 +181,7 @@ class BatchedUDPSinkTest < Minitest::Test
180
181
  @receiver.bind("localhost", 0)
181
182
  @host = @receiver.addr[2]
182
183
  @port = @receiver.addr[1]
183
- @sink_class = StatsD::Instrument::BatchedUDPSink
184
+ @sink_class = StatsD::Instrument::BatchedSink
184
185
  @sinks = []
185
186
  end
186
187
 
@@ -221,9 +222,9 @@ class BatchedUDPSinkTest < Minitest::Test
221
222
  private
222
223
 
223
224
  def build_sink(host = @host, port = @port, buffer_capacity: 50, statistics_interval: 0)
225
+ sink = StatsD::Instrument::Sink.for_addr("#{host}:#{port}")
224
226
  sink = @sink_class.new(
225
- host,
226
- port,
227
+ sink,
227
228
  buffer_capacity: buffer_capacity,
228
229
  statistics_interval: statistics_interval,
229
230
  )
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ module UdsTestHelper
6
+ MAX_READ_BYTES = 64 * 1024
7
+ private_constant :MAX_READ_BYTES
8
+
9
+ private
10
+
11
+ def create_socket_file
12
+ tmpdir = Dir.mktmpdir
13
+ socket_path = File.join(tmpdir, "sockets", "statsd.sock")
14
+ FileUtils.mkdir_p(File.dirname(socket_path))
15
+
16
+ socket_path
17
+ end
18
+
19
+ def create_receiver(socket_path)
20
+ FileUtils.rm_f(socket_path)
21
+ receiver = Socket.new(Socket::AF_UNIX, Socket::SOCK_DGRAM)
22
+ receiver.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
23
+ receiver.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVBUF, (2 * MAX_READ_BYTES).to_i)
24
+ receiver.bind(Socket.pack_sockaddr_un(socket_path))
25
+
26
+ receiver
27
+ end
28
+
29
+ def build_sink(socket_path)
30
+ connection = StatsD::Instrument::UdsConnection.new(socket_path)
31
+ @sink_class.new(connection)
32
+ end
33
+
34
+ def sink
35
+ @sink ||= build_sink(@socket_path)
36
+ end
37
+
38
+ def skip_on_jruby(message = "JRuby does not support UNIX domain sockets")
39
+ skip(message) if RUBY_PLATFORM == "java"
40
+ end
41
+
42
+ def read_datagrams(count, timeout: ENV["CI"] ? 5 : 1)
43
+ datagrams = []
44
+ count.times do
45
+ if @receiver.wait_readable(timeout)
46
+
47
+ datagrams += @receiver.recvfrom(MAX_READ_BYTES).first.lines(chomp: true)
48
+ break if datagrams.size >= count
49
+ else
50
+ break
51
+ end
52
+ end
53
+
54
+ datagrams
55
+ end
56
+ end
57
+
58
+ class UdsSinkTest < Minitest::Test
59
+ include UdsTestHelper
60
+
61
+ def setup
62
+ @sink_class = StatsD::Instrument::Sink
63
+ @socket_path = create_socket_file
64
+ skip_on_jruby
65
+
66
+ @receiver = create_receiver(@socket_path)
67
+ end
68
+
69
+ def teardown
70
+ return if RUBY_PLATFORM == "java"
71
+
72
+ @receiver.close
73
+ FileUtils.rm_f(@socket_path)
74
+ end
75
+
76
+ def test_send_metric_with_tags
77
+ metric = "test.metric"
78
+ value = 42
79
+ tags = { region: "us-west", environment: "production" }
80
+ sink << "#{metric}:#{value}|c|##{"region:#{tags[:region]},environment:#{tags[:environment]}"}"
81
+ # Assert that the metric with tags was sent successfully
82
+
83
+ datagrams = read_datagrams(1)
84
+ assert_equal("test.metric:42|c|#region:us-west,environment:production".b, datagrams.first)
85
+ end
86
+
87
+ def test_send_metric_with_sample_rate
88
+ metric = "test.metric"
89
+ value = 42
90
+ sample_rate = 0.5
91
+ sink << "#{metric}:#{value}|c|@#{sample_rate}"
92
+ datagrams = read_datagrams(1)
93
+ assert_equal("test.metric:42|c|@0.5".b, datagrams.first)
94
+ end
95
+
96
+ def test_flush_with_empty_batch
97
+ sink.flush
98
+ datagrams = read_datagrams(1, timeout: 0.1)
99
+ assert_empty(datagrams)
100
+ end
101
+ end
102
+
103
+ class BatchedUdsSinkTest < Minitest::Test
104
+ include UdsTestHelper
105
+
106
+ def setup
107
+ @socket_path = create_socket_file
108
+ @sink_class = StatsD::Instrument::BatchedSink
109
+ @sinks = []
110
+
111
+ skip_on_jruby
112
+
113
+ @receiver = create_receiver(@socket_path)
114
+ end
115
+
116
+ def teardown
117
+ return if RUBY_PLATFORM == "java"
118
+
119
+ @receiver.close
120
+ FileUtils.remove_entry(@socket_path)
121
+ @sinks.each(&:shutdown)
122
+ end
123
+
124
+ def test_send_metric_with_tags
125
+ metric = "test.metric"
126
+ value = 42
127
+ tags = { region: "us-west", environment: "production" }
128
+ sink << "#{metric}:#{value}|c|##{"region:#{tags[:region]},environment:#{tags[:environment]}"}"
129
+ datagrams = read_datagrams(1)
130
+ assert_equal("test.metric:42|c|#region:us-west,environment:production".b, datagrams.first)
131
+ end
132
+
133
+ def test_send_metric_with_sample_rate
134
+ metric = "test.metric"
135
+ value = 42
136
+ sample_rate = 0.5
137
+ sink << "#{metric}:#{value}|c|@#{sample_rate}"
138
+ datagrams = read_datagrams(1)
139
+ assert_equal("test.metric:42|c|@0.5".b, datagrams.first)
140
+ end
141
+
142
+ def test_flush_with_empty_batch
143
+ sink.flush(blocking: false)
144
+ datagrams = read_datagrams(1, timeout: 0.1)
145
+ assert_empty(datagrams)
146
+ end
147
+
148
+ def test_flush
149
+ buffer_size = 50
150
+ sink = build_sink(@socket_path, buffer_capacity: buffer_size)
151
+ dispatcher = sink.instance_variable_get(:@dispatcher)
152
+ buffer = dispatcher.instance_variable_get(:@buffer)
153
+ (buffer_size * 2).times { |i| sink << "foo:#{i}|c" }
154
+ assert(!buffer.empty?)
155
+ sink.flush(blocking: false)
156
+ assert(buffer.empty?)
157
+ end
158
+
159
+ def test_statistics
160
+ datagrams = StatsD.singleton_client.capture do
161
+ buffer_size = 2
162
+ sink = build_sink(@socket_path, buffer_capacity: buffer_size, statistics_interval: 0.1)
163
+ 2.times { |i| sink << "foo:#{i}|c" }
164
+ sink.flush(blocking: false)
165
+ sink.instance_variable_get(:@dispatcher).instance_variable_get(:@statistics).maybe_flush!(force: true)
166
+ end
167
+
168
+ assert(datagrams.any? { |d| d.name.start_with?("statsd_instrument.batched_uds_sink.avg_batch_length") })
169
+ assert(datagrams.any? { |d| d.name.start_with?("statsd_instrument.batched_uds_sink.avg_batched_packet_size") })
170
+ assert(datagrams.any? { |d| d.name.start_with?("statsd_instrument.batched_uds_sink.avg_buffer_length") })
171
+ assert(datagrams.any? { |d| d.name.start_with?("statsd_instrument.batched_uds_sink.batched_sends") })
172
+ assert(datagrams.any? { |d| d.name.start_with?("statsd_instrument.batched_uds_sink.synchronous_sends") })
173
+ end
174
+
175
+ private
176
+
177
+ def build_sink(socket_path, buffer_capacity: 50, statistics_interval: 0)
178
+ sink = StatsD::Instrument::Sink.for_addr(socket_path)
179
+ sink = @sink_class.new(
180
+ sink,
181
+ buffer_capacity: buffer_capacity,
182
+ statistics_interval: statistics_interval,
183
+ )
184
+ @sinks << sink
185
+ sink
186
+ end
187
+ end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: statsd-instrument
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.0
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesse Storimer
8
8
  - Tobias Lutke
9
9
  - Willem van Bergen
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-06-19 00:00:00.000000000 Z
13
+ date: 2024-08-19 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.
@@ -21,6 +21,7 @@ extensions: []
21
21
  extra_rdoc_files: []
22
22
  files:
23
23
  - ".github/CODEOWNERS"
24
+ - ".github/pull_request_template.md"
24
25
  - ".github/workflows/benchmark.yml"
25
26
  - ".github/workflows/cla.yml"
26
27
  - ".github/workflows/lint.yml"
@@ -43,8 +44,9 @@ files:
43
44
  - bin/rubocop
44
45
  - lib/statsd-instrument.rb
45
46
  - lib/statsd/instrument.rb
47
+ - lib/statsd/instrument/aggregator.rb
46
48
  - lib/statsd/instrument/assertions.rb
47
- - lib/statsd/instrument/batched_udp_sink.rb
49
+ - lib/statsd/instrument/batched_sink.rb
48
50
  - lib/statsd/instrument/capture_sink.rb
49
51
  - lib/statsd/instrument/client.rb
50
52
  - lib/statsd/instrument/datagram.rb
@@ -67,12 +69,15 @@ files:
67
69
  - lib/statsd/instrument/rubocop/positional_arguments.rb
68
70
  - lib/statsd/instrument/rubocop/singleton_configuration.rb
69
71
  - lib/statsd/instrument/rubocop/splat_arguments.rb
72
+ - lib/statsd/instrument/sink.rb
70
73
  - lib/statsd/instrument/statsd_datagram_builder.rb
71
74
  - lib/statsd/instrument/strict.rb
72
- - lib/statsd/instrument/udp_sink.rb
75
+ - lib/statsd/instrument/udp_connection.rb
76
+ - lib/statsd/instrument/uds_connection.rb
73
77
  - lib/statsd/instrument/version.rb
74
78
  - shipit.rubygems.yml
75
79
  - statsd-instrument.gemspec
80
+ - test/aggregator_test.rb
76
81
  - test/assertions_test.rb
77
82
  - test/benchmark/clock_gettime.rb
78
83
  - test/benchmark/metrics.rb
@@ -104,12 +109,13 @@ files:
104
109
  - test/statsd_test.rb
105
110
  - test/test_helper.rb
106
111
  - test/udp_sink_test.rb
112
+ - test/uds_sink_test.rb
107
113
  homepage: https://github.com/Shopify/statsd-instrument
108
114
  licenses:
109
115
  - MIT
110
116
  metadata:
111
117
  allowed_push_host: https://rubygems.org
112
- post_install_message:
118
+ post_install_message:
113
119
  rdoc_options: []
114
120
  require_paths:
115
121
  - lib
@@ -124,11 +130,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
130
  - !ruby/object:Gem::Version
125
131
  version: '0'
126
132
  requirements: []
127
- rubygems_version: 3.5.11
128
- signing_key:
133
+ rubygems_version: 3.5.17
134
+ signing_key:
129
135
  specification_version: 4
130
136
  summary: A StatsD client for Ruby apps
131
137
  test_files:
138
+ - test/aggregator_test.rb
132
139
  - test/assertions_test.rb
133
140
  - test/benchmark/clock_gettime.rb
134
141
  - test/benchmark/metrics.rb
@@ -160,3 +167,4 @@ test_files:
160
167
  - test/statsd_test.rb
161
168
  - test/test_helper.rb
162
169
  - test/udp_sink_test.rb
170
+ - test/uds_sink_test.rb