statsd-instrument 3.0.0.pre1 → 3.1.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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint.yml +22 -0
  3. data/.github/workflows/tests.yml +31 -0
  4. data/.rubocop.yml +3 -13
  5. data/CHANGELOG.md +50 -0
  6. data/Gemfile +8 -2
  7. data/README.md +6 -3
  8. data/Rakefile +7 -7
  9. data/benchmark/send-metrics-to-dev-null-log +12 -11
  10. data/benchmark/send-metrics-to-local-udp-receiver +16 -15
  11. data/bin/rake +29 -0
  12. data/bin/rubocop +29 -0
  13. data/lib/statsd-instrument.rb +1 -1
  14. data/lib/statsd/instrument.rb +112 -145
  15. data/lib/statsd/instrument/assertions.rb +200 -208
  16. data/lib/statsd/instrument/batched_udp_sink.rb +154 -0
  17. data/lib/statsd/instrument/capture_sink.rb +23 -19
  18. data/lib/statsd/instrument/client.rb +410 -306
  19. data/lib/statsd/instrument/datagram.rb +69 -65
  20. data/lib/statsd/instrument/datagram_builder.rb +81 -77
  21. data/lib/statsd/instrument/dogstatsd_datagram.rb +76 -72
  22. data/lib/statsd/instrument/dogstatsd_datagram_builder.rb +68 -64
  23. data/lib/statsd/instrument/environment.rb +88 -77
  24. data/lib/statsd/instrument/expectation.rb +96 -96
  25. data/lib/statsd/instrument/helpers.rb +11 -7
  26. data/lib/statsd/instrument/log_sink.rb +20 -16
  27. data/lib/statsd/instrument/matchers.rb +93 -74
  28. data/lib/statsd/instrument/null_sink.rb +12 -8
  29. data/lib/statsd/instrument/railtie.rb +11 -7
  30. data/lib/statsd/instrument/rubocop.rb +8 -8
  31. data/lib/statsd/instrument/rubocop/measure_as_dist_argument.rb +1 -1
  32. data/lib/statsd/instrument/rubocop/metaprogramming_positional_arguments.rb +2 -2
  33. data/lib/statsd/instrument/rubocop/metric_prefix_argument.rb +1 -1
  34. data/lib/statsd/instrument/rubocop/metric_return_value.rb +2 -2
  35. data/lib/statsd/instrument/rubocop/metric_value_keyword_argument.rb +1 -1
  36. data/lib/statsd/instrument/rubocop/positional_arguments.rb +4 -4
  37. data/lib/statsd/instrument/rubocop/singleton_configuration.rb +1 -1
  38. data/lib/statsd/instrument/rubocop/splat_arguments.rb +2 -2
  39. data/lib/statsd/instrument/statsd_datagram_builder.rb +12 -8
  40. data/lib/statsd/instrument/strict.rb +1 -6
  41. data/lib/statsd/instrument/udp_sink.rb +49 -47
  42. data/lib/statsd/instrument/version.rb +1 -1
  43. data/statsd-instrument.gemspec +4 -8
  44. data/test/assertions_test.rb +205 -161
  45. data/test/benchmark/clock_gettime.rb +1 -1
  46. data/test/benchmark/default_tags.rb +9 -9
  47. data/test/benchmark/metrics.rb +8 -8
  48. data/test/benchmark/tags.rb +4 -4
  49. data/test/capture_sink_test.rb +14 -14
  50. data/test/client_test.rb +96 -96
  51. data/test/datagram_builder_test.rb +55 -55
  52. data/test/datagram_test.rb +5 -5
  53. data/test/dogstatsd_datagram_builder_test.rb +37 -37
  54. data/test/environment_test.rb +30 -21
  55. data/test/helpers/rubocop_helper.rb +12 -9
  56. data/test/helpers_test.rb +15 -15
  57. data/test/integration_test.rb +7 -7
  58. data/test/log_sink_test.rb +4 -4
  59. data/test/matchers_test.rb +54 -54
  60. data/test/null_sink_test.rb +4 -4
  61. data/test/rubocop/measure_as_dist_argument_test.rb +2 -2
  62. data/test/rubocop/metaprogramming_positional_arguments_test.rb +2 -2
  63. data/test/rubocop/metric_prefix_argument_test.rb +2 -2
  64. data/test/rubocop/metric_return_value_test.rb +6 -6
  65. data/test/rubocop/metric_value_keyword_argument_test.rb +3 -3
  66. data/test/rubocop/positional_arguments_test.rb +12 -12
  67. data/test/rubocop/singleton_configuration_test.rb +8 -8
  68. data/test/rubocop/splat_arguments_test.rb +2 -2
  69. data/test/statsd_datagram_builder_test.rb +6 -6
  70. data/test/statsd_instrumentation_test.rb +122 -122
  71. data/test/statsd_test.rb +69 -67
  72. data/test/test_helper.rb +19 -10
  73. data/test/udp_sink_test.rb +122 -50
  74. metadata +12 -92
  75. data/.github/workflows/ci.yml +0 -56
  76. data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +0 -1027
data/test/statsd_test.rb CHANGED
@@ -1,33 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'test_helper'
3
+ require "test_helper"
4
4
 
5
5
  class StatsDTest < Minitest::Test
6
6
  include StatsD::Instrument::Assertions
7
7
 
8
8
  def test_statsd_measure_with_explicit_value
9
- metric = capture_statsd_call { StatsD.measure('values.foobar', 42) }
10
- assert_equal 'values.foobar', metric.name
11
- assert_equal 42, metric.value
12
- assert_equal :ms, metric.type
9
+ metric = capture_statsd_call { StatsD.measure("values.foobar", 42) }
10
+ assert_equal("values.foobar", metric.name)
11
+ assert_equal(42, metric.value)
12
+ assert_equal(:ms, metric.type)
13
13
  end
14
14
 
15
15
  def test_statsd_measure_with_explicit_value_and_sample_rate
16
- metric = capture_statsd_call { StatsD.measure('values.foobar', 42, sample_rate: 0.1) }
17
- assert_equal 0.1, metric.sample_rate
16
+ metric = capture_statsd_call { StatsD.measure("values.foobar", 42, sample_rate: 0.1) }
17
+ assert_equal(0.1, metric.sample_rate)
18
18
  end
19
19
 
20
20
  def test_statsd_measure_with_benchmarked_block_duration
21
21
  Process.stubs(:clock_gettime).returns(5.0, 5.0 + 1.12)
22
22
  metric = capture_statsd_call do
23
- StatsD.measure('values.foobar') { 'foo' }
23
+ StatsD.measure("values.foobar") { "foo" }
24
24
  end
25
- assert_equal 1120.0, metric.value
25
+ assert_equal(1120.0, metric.value)
26
26
  end
27
27
 
28
28
  def test_statsd_measure_returns_return_value_of_block
29
- return_value = StatsD.measure('values.foobar') { 'sarah' }
30
- assert_equal 'sarah', return_value
29
+ return_value = StatsD.measure("values.foobar") { "sarah" }
30
+ assert_equal("sarah", return_value)
31
31
  end
32
32
 
33
33
  def test_statsd_measure_with_return_in_block_still_captures
@@ -35,14 +35,14 @@ class StatsDTest < Minitest::Test
35
35
  result = nil
36
36
  metric = capture_statsd_call do
37
37
  lambda = -> do
38
- StatsD.measure('values.foobar') { return 'from lambda' }
38
+ StatsD.measure("values.foobar") { return "from lambda" }
39
39
  end
40
40
 
41
41
  result = lambda.call
42
42
  end
43
43
 
44
- assert_equal 'from lambda', result
45
- assert_equal 1120.0, metric.value
44
+ assert_equal("from lambda", result)
45
+ assert_equal(1120.0, metric.value)
46
46
  end
47
47
 
48
48
  def test_statsd_measure_with_exception_in_block_still_captures
@@ -50,73 +50,74 @@ class StatsDTest < Minitest::Test
50
50
  result = nil
51
51
  metric = capture_statsd_call do
52
52
  lambda = -> do
53
- StatsD.measure('values.foobar') { raise 'from lambda' }
53
+ StatsD.measure("values.foobar") { raise "from lambda" }
54
54
  end
55
55
 
56
56
  begin
57
57
  result = lambda.call
58
- rescue # rubocop:disable Lint/HandleExceptions:
58
+ rescue
59
+ # noop
59
60
  end
60
61
  end
61
62
 
62
- assert_nil result
63
- assert_equal 1120.0, metric.value
63
+ assert_nil(result)
64
+ assert_equal(1120.0, metric.value)
64
65
  end
65
66
 
66
67
  def test_statsd_increment
67
- metric = capture_statsd_call { StatsD.increment('values.foobar', 3) }
68
- assert_equal :c, metric.type
69
- assert_equal 'values.foobar', metric.name
70
- assert_equal 3, metric.value
68
+ metric = capture_statsd_call { StatsD.increment("values.foobar", 3) }
69
+ assert_equal(:c, metric.type)
70
+ assert_equal("values.foobar", metric.name)
71
+ assert_equal(3, metric.value)
71
72
  end
72
73
 
73
74
  def test_statsd_increment_with_hash_argument
74
- metric = capture_statsd_call { StatsD.increment('values.foobar', tags: ['test']) }
75
- assert_equal StatsD.singleton_client.default_sample_rate, metric.sample_rate
76
- assert_equal ['test'], metric.tags
77
- assert_equal 1, metric.value
75
+ metric = capture_statsd_call { StatsD.increment("values.foobar", tags: ["test"]) }
76
+ assert_equal(StatsD.singleton_client.default_sample_rate, metric.sample_rate)
77
+ assert_equal(["test"], metric.tags)
78
+ assert_equal(1, metric.value)
78
79
  end
79
80
 
80
81
  def test_statsd_gauge
81
- metric = capture_statsd_call { StatsD.gauge('values.foobar', 12) }
82
- assert_equal :g, metric.type
83
- assert_equal 'values.foobar', metric.name
84
- assert_equal 12, metric.value
82
+ metric = capture_statsd_call { StatsD.gauge("values.foobar", 12) }
83
+ assert_equal(:g, metric.type)
84
+ assert_equal("values.foobar", metric.name)
85
+ assert_equal(12, metric.value)
85
86
  end
86
87
 
87
88
  def test_statsd_gauge_without_value
88
- assert_raises(ArgumentError) { StatsD.gauge('values.foobar') }
89
+ assert_raises(ArgumentError) { StatsD.gauge("values.foobar") }
89
90
  end
90
91
 
91
92
  def test_statsd_set
92
- metric = capture_statsd_call { StatsD.set('values.foobar', 'unique_identifier') }
93
- assert_equal :s, metric.type
94
- assert_equal 'values.foobar', metric.name
95
- assert_equal 'unique_identifier', metric.value
93
+ metric = capture_statsd_call { StatsD.set("values.foobar", "unique_identifier") }
94
+ assert_equal(:s, metric.type)
95
+ assert_equal("values.foobar", metric.name)
96
+ assert_equal("unique_identifier", metric.value)
96
97
  end
97
98
 
98
99
  def test_statsd_histogram
99
- metric = capture_statsd_call { StatsD.histogram('values.foobar', 42) }
100
- assert_equal :h, metric.type
101
- assert_equal 'values.foobar', metric.name
102
- assert_equal 42, metric.value
100
+ metric = capture_statsd_call { StatsD.histogram("values.foobar", 42) }
101
+ assert_equal(:h, metric.type)
102
+ assert_equal("values.foobar", metric.name)
103
+ assert_equal(42, metric.value)
103
104
  end
104
105
 
105
106
  def test_statsd_distribution
106
- metric = capture_statsd_call { StatsD.distribution('values.foobar', 42) }
107
- assert_equal :d, metric.type
108
- assert_equal 'values.foobar', metric.name
109
- assert_equal 42, metric.value
107
+ metric = capture_statsd_call { StatsD.distribution("values.foobar", 42) }
108
+ assert_equal(:d, metric.type)
109
+ assert_equal("values.foobar", metric.name)
110
+ assert_equal(42, metric.value)
110
111
  end
111
112
 
112
113
  def test_statsd_distribution_with_benchmarked_block_duration
113
114
  Process.stubs(:clock_gettime).returns(5.0, 5.0 + 1.12)
114
115
  metric = capture_statsd_call do
115
- result = StatsD.distribution('values.foobar') { 'foo' }
116
- assert_equal 'foo', result
116
+ result = StatsD.distribution("values.foobar") { "foo" }
117
+ assert_equal("foo", result)
117
118
  end
118
- assert_equal :d, metric.type
119
- assert_equal 1120.0, metric.value
119
+ assert_equal(:d, metric.type)
120
+ assert_equal(1120.0, metric.value)
120
121
  end
121
122
 
122
123
  def test_statsd_distribution_with_return_in_block_still_captures
@@ -124,16 +125,16 @@ class StatsDTest < Minitest::Test
124
125
  result = nil
125
126
  metric = capture_statsd_call do
126
127
  lambda = -> do
127
- StatsD.distribution('values.foobar') { return 'from lambda' }
128
+ StatsD.distribution("values.foobar") { return "from lambda" }
128
129
  flunk("This code should not be reached")
129
130
  end
130
131
 
131
132
  result = lambda.call
132
133
  end
133
134
 
134
- assert_equal 'from lambda', result
135
- assert_equal :d, metric.type
136
- assert_equal 1120.0, metric.value
135
+ assert_equal("from lambda", result)
136
+ assert_equal(:d, metric.type)
137
+ assert_equal(1120.0, metric.value)
137
138
  end
138
139
 
139
140
  def test_statsd_distribution_with_exception_in_block_still_captures
@@ -141,44 +142,45 @@ class StatsDTest < Minitest::Test
141
142
  result = nil
142
143
  metric = capture_statsd_call do
143
144
  lambda = -> do
144
- StatsD.distribution('values.foobar') { raise 'from lambda' }
145
+ StatsD.distribution("values.foobar") { raise "from lambda" }
145
146
  end
146
147
 
147
148
  begin
148
149
  result = lambda.call
149
- rescue # rubocop:disable Lint/HandleExceptions
150
+ rescue
151
+ # noop
150
152
  end
151
153
  end
152
154
 
153
- assert_nil result
154
- assert_equal :d, metric.type
155
- assert_equal 1120.0, metric.value
155
+ assert_nil(result)
156
+ assert_equal(:d, metric.type)
157
+ assert_equal(1120.0, metric.value)
156
158
  end
157
159
 
158
160
  def test_statsd_distribution_with_block_and_options
159
161
  Process.stubs(:clock_gettime).returns(5.0, 5.0 + 1.12)
160
162
  metric = capture_statsd_call do
161
- StatsD.distribution('values.foobar', tags: ['test'], sample_rate: 0.9) { 'foo' }
163
+ StatsD.distribution("values.foobar", tags: ["test"], sample_rate: 0.9) { "foo" }
162
164
  end
163
- assert_equal 1120.0, metric.value
164
- assert_equal 'values.foobar', metric.name
165
- assert_equal 0.9, metric.sample_rate
166
- assert_equal ['test'], metric.tags
165
+ assert_equal(1120.0, metric.value)
166
+ assert_equal("values.foobar", metric.name)
167
+ assert_equal(0.9, metric.sample_rate)
168
+ assert_equal(["test"], metric.tags)
167
169
  end
168
170
 
169
171
  def test_statsd_distribution_returns_return_value_of_block
170
- return_value = StatsD.distribution('values.foobar') { 'sarah' }
171
- assert_equal 'sarah', return_value
172
+ return_value = StatsD.distribution("values.foobar") { "sarah" }
173
+ assert_equal("sarah", return_value)
172
174
  end
173
175
 
174
176
  def test_statsd_measure_returns_return_value_of_block_even_if_nil
175
- return_value = StatsD.distribution('values.foobar') { nil }
176
- assert_nil return_value
177
+ return_value = StatsD.distribution("values.foobar") { nil }
178
+ assert_nil(return_value)
177
179
  end
178
180
 
179
181
  def test_statsd_duration_returns_time_in_seconds
180
182
  duration = StatsD::Instrument.duration {}
181
- assert_kind_of Float, duration
183
+ assert_kind_of(Float, duration)
182
184
  end
183
185
 
184
186
  def test_statsd_duration_does_not_swallow_exceptions
@@ -191,7 +193,7 @@ class StatsDTest < Minitest::Test
191
193
 
192
194
  def capture_statsd_call(&block)
193
195
  metrics = capture_statsd_calls(&block)
194
- assert_equal 1, metrics.length
196
+ assert_equal(1, metrics.length)
195
197
  metrics.first
196
198
  end
197
199
  end
data/test/test_helper.rb CHANGED
@@ -1,19 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- ENV['ENV'] = 'test'
3
+ if Warning.respond_to?(:[]=)
4
+ Warning[:deprecated] = true
5
+ end
6
+
7
+ ENV["ENV"] = "test"
4
8
 
5
- require 'minitest/autorun'
6
- require 'minitest/pride'
7
- require 'mocha/setup'
8
- require 'statsd-instrument'
9
+ require "minitest/autorun"
10
+ require "minitest/pride"
11
+ require "mocha/minitest"
12
+ require "statsd-instrument"
9
13
 
10
- require_relative 'helpers/rubocop_helper'
14
+ require_relative "helpers/rubocop_helper"
11
15
 
12
- module StatsD::Instrument
13
- def self.strict_mode_enabled?
14
- StatsD::Instrument.const_defined?(:Strict) &&
15
- StatsD.singleton_class.ancestors.include?(StatsD::Instrument::Strict)
16
+ module StatsD
17
+ module Instrument
18
+ def self.strict_mode_enabled?
19
+ StatsD::Instrument.const_defined?(:Strict) &&
20
+ StatsD.singleton_class.ancestors.include?(StatsD::Instrument::Strict)
21
+ end
16
22
  end
17
23
  end
18
24
 
19
25
  StatsD.logger = Logger.new(File::NULL)
26
+
27
+ Thread.abort_on_exception = true
28
+ Thread.report_on_exception = true
@@ -1,83 +1,155 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'test_helper'
4
-
5
- class UDPSinkTest < Minitest::Test
6
- def setup
7
- @receiver = UDPSocket.new
8
- @receiver.bind('localhost', 0)
9
- @host = @receiver.addr[2]
10
- @port = @receiver.addr[1]
11
- end
12
-
13
- def teardown
14
- @receiver.close
15
- end
3
+ require "test_helper"
16
4
 
5
+ module UDPSinkTests
17
6
  def test_udp_sink_sends_data_over_udp
18
- udp_sink = StatsD::Instrument::UDPSink.new(@host, @port)
19
- udp_sink << 'foo:1|c'
7
+ udp_sink = build_sink(@host, @port)
8
+ udp_sink << "foo:1|c"
20
9
 
21
10
  datagram, _source = @receiver.recvfrom(100)
22
- assert_equal 'foo:1|c', datagram
11
+ assert_equal("foo:1|c", datagram)
12
+ end
13
+
14
+ def large_datagram
15
+ datagram = "#{"a" * 1000}:1|c"
16
+ udp_sink = build_sink(@host, @port)
17
+ udp_sink << datagram
18
+
19
+ datagram, _source = @receiver.recvfrom(1500)
20
+ assert_equal(datagram, datagram)
23
21
  end
24
22
 
25
23
  def test_sample?
26
- udp_sink = StatsD::Instrument::UDPSink.new(@host, @port)
27
- assert udp_sink.sample?(1)
28
- refute udp_sink.sample?(0)
24
+ udp_sink = build_sink(@host, @port)
25
+ assert(udp_sink.sample?(1))
26
+ refute(udp_sink.sample?(0))
29
27
 
30
28
  udp_sink.stubs(:rand).returns(0.3)
31
- assert udp_sink.sample?(0.5)
29
+ assert(udp_sink.sample?(0.5))
32
30
 
33
31
  udp_sink.stubs(:rand).returns(0.7)
34
- refute udp_sink.sample?(0.5)
32
+ refute(udp_sink.sample?(0.5))
35
33
  end
36
34
 
37
35
  def test_parallelism
38
- udp_sink = StatsD::Instrument::UDPSink.new(@host, @port)
39
- 50.times { |i| Thread.new { udp_sink << "foo:#{i}|c" << "bar:#{i}|c" } }
36
+ udp_sink = build_sink(@host, @port)
37
+ 50.times.map { |i| Thread.new { udp_sink << "foo:#{i}|c" << "bar:#{i}|c" } }
40
38
  datagrams = []
41
- 100.times do
42
- datagram, _source = @receiver.recvfrom(100)
43
- datagrams << datagram
39
+
40
+ while @receiver.wait_readable(2)
41
+ datagram, _source = @receiver.recvfrom(4000)
42
+ datagrams += datagram.split("\n")
44
43
  end
45
44
 
46
- assert_equal 100, datagrams.size
45
+ assert_equal(100, datagrams.size)
47
46
  end
48
47
 
49
- def test_socket_error_should_invalidate_socket
50
- UDPSocket.stubs(:new).returns(socket = mock('socket'))
51
-
52
- seq = sequence('connect_fail_connect_succeed')
53
- socket.expects(:connect).with('localhost', 8125).in_sequence(seq)
54
- socket.expects(:send).raises(Errno::EDESTADDRREQ).in_sequence(seq)
55
- socket.expects(:connect).with('localhost', 8125).in_sequence(seq)
56
- socket.expects(:send).returns(1).in_sequence(seq)
57
-
58
- udp_sink = StatsD::Instrument::UDPSink.new('localhost', 8125)
59
- udp_sink << 'foo:1|c'
60
- udp_sink << 'bar:1|c'
48
+ class SimpleFormatter < ::Logger::Formatter
49
+ def call(_severity, _timestamp, _progname, msg)
50
+ "#{String === msg ? msg : msg.inspect}\n"
51
+ end
61
52
  end
62
53
 
63
54
  def test_sends_datagram_in_signal_handler
64
- udp_sink = StatsD::Instrument::UDPSink.new(@host, @port)
55
+ udp_sink = build_sink(@host, @port)
56
+ Signal.trap("USR1") { udp_sink << "exiting:1|c" }
57
+
65
58
  pid = fork do
66
- Signal.trap('TERM') do
67
- udp_sink << "exiting:1|c"
68
- Process.exit!(0)
59
+ sleep(5)
60
+ end
61
+
62
+ Signal.trap("USR1", "DEFAULT")
63
+
64
+ Process.kill("USR1", pid)
65
+ @receiver.wait_readable(1)
66
+ assert_equal("exiting:1|c", @receiver.recvfrom_nonblock(100).first)
67
+ Process.kill("KILL", pid)
68
+ rescue NotImplementedError
69
+ pass("Fork is not implemented on #{RUBY_PLATFORM}")
70
+ end
71
+
72
+ private
73
+
74
+ def build_sink(host = @host, port = @port)
75
+ @sink_class.new(host, port)
76
+ end
77
+
78
+ class UDPSinkTest < Minitest::Test
79
+ include UDPSinkTests
80
+
81
+ def setup
82
+ @receiver = UDPSocket.new
83
+ @receiver.bind("localhost", 0)
84
+ @host = @receiver.addr[2]
85
+ @port = @receiver.addr[1]
86
+ @sink_class = StatsD::Instrument::UDPSink
87
+ end
88
+
89
+ def teardown
90
+ @receiver.close
91
+ end
92
+
93
+ def test_socket_error_should_invalidate_socket
94
+ previous_logger = StatsD.logger
95
+ begin
96
+ logs = StringIO.new
97
+ StatsD.logger = Logger.new(logs)
98
+ StatsD.logger.formatter = SimpleFormatter.new
99
+ UDPSocket.stubs(:new).returns(socket = mock("socket"))
100
+
101
+ seq = sequence("connect_fail_connect_succeed")
102
+ socket.expects(:connect).with("localhost", 8125).in_sequence(seq)
103
+ socket.expects(:send).raises(Errno::EDESTADDRREQ).in_sequence(seq)
104
+ socket.expects(:connect).with("localhost", 8125).in_sequence(seq)
105
+ socket.expects(:send).returns(1).in_sequence(seq)
106
+
107
+ udp_sink = build_sink("localhost", 8125)
108
+ udp_sink << "foo:1|c"
109
+ udp_sink << "bar:1|c"
110
+
111
+ assert_equal(
112
+ "[#{@sink_class}] Resetting connection because of " \
113
+ "Errno::EDESTADDRREQ: Destination address required\n",
114
+ logs.string,
115
+ )
116
+ ensure
117
+ StatsD.logger = previous_logger
69
118
  end
119
+ end
120
+ end
70
121
 
71
- sleep(10)
122
+ class BatchedUDPSinkTest < Minitest::Test
123
+ include UDPSinkTests
124
+
125
+ def setup
126
+ @receiver = UDPSocket.new
127
+ @receiver.bind("localhost", 0)
128
+ @host = @receiver.addr[2]
129
+ @port = @receiver.addr[1]
130
+ @sink_class = StatsD::Instrument::BatchedUDPSink
72
131
  end
73
132
 
74
- Process.kill('TERM', pid)
75
- _, exit_status = Process.waitpid2(pid)
133
+ def teardown
134
+ @receiver.close
135
+ end
76
136
 
77
- assert_equal 0, exit_status, "The forked process did not exit cleanly"
78
- assert_equal "exiting:1|c", @receiver.recvfrom_nonblock(100).first
137
+ def test_parallelism_buffering
138
+ udp_sink = build_sink(@host, @port)
139
+ 50.times.map do |i|
140
+ Thread.new do
141
+ udp_sink << "foo:#{i}|c" << "bar:#{i}|c" << "baz:#{i}|c" << "plop:#{i}|c"
142
+ end
143
+ end
79
144
 
80
- rescue NotImplementedError
81
- pass("Fork is not implemented on #{RUBY_PLATFORM}")
145
+ datagrams = []
146
+
147
+ while @receiver.wait_readable(2)
148
+ datagram, _source = @receiver.recvfrom(1000)
149
+ datagrams += datagram.split("\n")
150
+ end
151
+
152
+ assert_equal(200, datagrams.size)
153
+ end
82
154
  end
83
155
  end