statsd-instrument 3.8.0 → 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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