statsd-instrument 2.3.2 → 2.4.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/workflows/ci.yml +31 -0
  4. data/.gitignore +1 -0
  5. data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +1027 -0
  6. data/.rubocop.yml +21 -0
  7. data/CHANGELOG.md +41 -0
  8. data/CONTRIBUTING.md +26 -6
  9. data/Gemfile +2 -0
  10. data/Rakefile +3 -1
  11. data/lib/statsd/instrument/assertions.rb +24 -18
  12. data/lib/statsd/instrument/backend.rb +3 -2
  13. data/lib/statsd/instrument/backends/capture_backend.rb +2 -1
  14. data/lib/statsd/instrument/backends/logger_backend.rb +3 -3
  15. data/lib/statsd/instrument/backends/null_backend.rb +2 -0
  16. data/lib/statsd/instrument/backends/udp_backend.rb +20 -17
  17. data/lib/statsd/instrument/environment.rb +2 -0
  18. data/lib/statsd/instrument/helpers.rb +6 -2
  19. data/lib/statsd/instrument/matchers.rb +14 -11
  20. data/lib/statsd/instrument/metric.rb +34 -21
  21. data/lib/statsd/instrument/metric_expectation.rb +32 -18
  22. data/lib/statsd/instrument/railtie.rb +2 -1
  23. data/lib/statsd/instrument/version.rb +3 -1
  24. data/lib/statsd/instrument.rb +85 -36
  25. data/lib/statsd-instrument.rb +2 -0
  26. data/statsd-instrument.gemspec +13 -10
  27. data/test/assertions_test.rb +15 -4
  28. data/test/benchmark/default_tags.rb +47 -0
  29. data/test/benchmark/metrics.rb +9 -8
  30. data/test/benchmark/tags.rb +5 -3
  31. data/test/capture_backend_test.rb +4 -2
  32. data/test/environment_test.rb +2 -1
  33. data/test/helpers_test.rb +2 -1
  34. data/test/integration_test.rb +27 -7
  35. data/test/logger_backend_test.rb +10 -8
  36. data/test/matchers_test.rb +34 -20
  37. data/test/metric_test.rb +15 -4
  38. data/test/statsd_instrumentation_test.rb +7 -7
  39. data/test/statsd_test.rb +100 -10
  40. data/test/test_helper.rb +2 -0
  41. data/test/udp_backend_test.rb +5 -28
  42. metadata +23 -5
  43. data/.travis.yml +0 -12
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This Railtie runs some initializers that will set the logger to <tt>Rails#logger</tt>,
2
4
  # and will initialize the {StatsD#backend} based on the Rails environment.
3
5
  #
4
6
  # @see StatsD::Instrument::Environment
5
7
  class StatsD::Instrument::Railtie < Rails::Railtie
6
-
7
8
  initializer 'statsd-instrument.use_rails_logger' do
8
9
  ::StatsD.logger = Rails.logger
9
10
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module StatsD
2
4
  module Instrument
3
- VERSION = "2.3.2"
5
+ VERSION = "2.4.0"
4
6
  end
5
7
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'socket'
2
4
  require 'logger'
3
5
 
@@ -28,6 +30,10 @@ require 'logger'
28
30
  # The logger to use in case of any errors. The logger is also used as default logger
29
31
  # for the LoggerBackend (although this can be overwritten).
30
32
  #
33
+ # @!attribute default_tags
34
+ # The tags to apply to all metrics.
35
+ # @return [Array<String>, Hash<String, String>, nil] The default tags, or <tt>nil</tt> when no default tags is used
36
+ #
31
37
  # @see StatsD::Instrument::Backends::LoggerBackend
32
38
  # @return [Logger]
33
39
  #
@@ -58,20 +64,26 @@ module StatsD
58
64
 
59
65
  if Process.respond_to?(:clock_gettime)
60
66
  # @private
61
- def self.duration
62
- start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
63
- yield
64
- Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
67
+ def self.current_timestamp
68
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
65
69
  end
66
70
  else
67
71
  # @private
68
- def self.duration
69
- start = Time.now
70
- yield
71
- Time.now - start
72
+ def self.current_timestamp
73
+ Time.now
72
74
  end
73
75
  end
74
76
 
77
+ # Even though this method is considered private, and is no longer used internally,
78
+ # applications in the wild rely on it. As a result, we cannot remove this method
79
+ # until the next major version.
80
+ # @private
81
+ def self.duration
82
+ start = current_timestamp
83
+ yield
84
+ current_timestamp - start
85
+ end
86
+
75
87
  # Adds execution duration instrumentation to a method as a timing.
76
88
  #
77
89
  # @param method [Symbol] The name of the method to instrument.
@@ -82,7 +94,8 @@ module StatsD
82
94
  def statsd_measure(method, name, *metric_options)
83
95
  add_to_method(method, name, :measure) do
84
96
  define_method(method) do |*args, &block|
85
- StatsD.measure(StatsD::Instrument.generate_metric_name(name, self, *args), *metric_options) { super(*args, &block) }
97
+ metric_name = StatsD::Instrument.generate_metric_name(name, self, *args)
98
+ StatsD.measure(metric_name, *metric_options) { super(*args, &block) }
86
99
  end
87
100
  end
88
101
  end
@@ -98,7 +111,8 @@ module StatsD
98
111
  def statsd_distribution(method, name, *metric_options)
99
112
  add_to_method(method, name, :distribution) do
100
113
  define_method(method) do |*args, &block|
101
- StatsD.distribution(StatsD::Instrument.generate_metric_name(name, self, *args), *metric_options) { super(*args, &block) }
114
+ metric_name = StatsD::Instrument.generate_metric_name(name, self, *args)
115
+ StatsD.distribution(metric_name, *metric_options) { super(*args, &block) }
102
116
  end
103
117
  end
104
118
  end
@@ -127,20 +141,27 @@ module StatsD
127
141
  truthiness = false
128
142
  raise
129
143
  else
130
- truthiness = (yield(result) rescue false) if block_given?
144
+ if block_given?
145
+ begin
146
+ truthiness = yield(result)
147
+ rescue
148
+ truthiness = false
149
+ end
150
+ end
131
151
  result
132
152
  ensure
133
153
  suffix = truthiness == false ? 'failure' : 'success'
134
- StatsD.increment("#{StatsD::Instrument.generate_metric_name(name, self, *args)}.#{suffix}", 1, *metric_options)
154
+ metric_name = "#{StatsD::Instrument.generate_metric_name(name, self, *args)}.#{suffix}"
155
+ StatsD.increment(metric_name, 1, *metric_options)
135
156
  end
136
157
  end
137
158
  end
138
159
  end
139
160
 
140
- # Adds success and failure counter instrumentation to a method.
161
+ # Adds success counter instrumentation to a method.
141
162
  #
142
163
  # A method call will be considered successful if it does not raise an exception, and the result is true-y.
143
- # Only for successful calls, the metric will be icnremented
164
+ # Only for successful calls, the metric will be incremented.
144
165
  #
145
166
  # @param method (see #statsd_measure)
146
167
  # @param name (see #statsd_measure)
@@ -159,10 +180,19 @@ module StatsD
159
180
  truthiness = false
160
181
  raise
161
182
  else
162
- truthiness = (yield(result) rescue false) if block_given?
183
+ if block_given?
184
+ begin
185
+ truthiness = yield(result)
186
+ rescue
187
+ truthiness = false
188
+ end
189
+ end
163
190
  result
164
191
  ensure
165
- StatsD.increment(StatsD::Instrument.generate_metric_name(name, self, *args), *metric_options) if truthiness
192
+ if truthiness
193
+ metric_name = StatsD::Instrument.generate_metric_name(name, self, *args)
194
+ StatsD.increment(metric_name, *metric_options)
195
+ end
166
196
  end
167
197
  end
168
198
  end
@@ -180,7 +210,8 @@ module StatsD
180
210
  def statsd_count(method, name, *metric_options)
181
211
  add_to_method(method, name, :count) do
182
212
  define_method(method) do |*args, &block|
183
- StatsD.increment(StatsD::Instrument.generate_metric_name(name, self, *args), 1, *metric_options)
213
+ metric_name = StatsD::Instrument.generate_metric_name(name, self, *args)
214
+ StatsD.increment(metric_name, 1, *metric_options)
184
215
  super(*args, &block)
185
216
  end
186
217
  end
@@ -248,8 +279,13 @@ module StatsD
248
279
  def add_to_method(method, name, action, &block)
249
280
  instrumentation_module = statsd_instrumentation_for(method, name, action)
250
281
 
251
- raise ArgumentError, "already instrumented #{method} for #{self.name}" if instrumentation_module.method_defined?(method)
252
- raise ArgumentError, "could not find method #{method} for #{self.name}" unless method_defined?(method) || private_method_defined?(method)
282
+ if instrumentation_module.method_defined?(method)
283
+ raise ArgumentError, "Already instrumented #{method} for #{self.name}"
284
+ end
285
+
286
+ unless method_defined?(method) || private_method_defined?(method)
287
+ raise ArgumentError, "could not find method #{method} for #{self.name}"
288
+ end
253
289
 
254
290
  method_scope = method_visibility(method)
255
291
 
@@ -263,10 +299,9 @@ module StatsD
263
299
  end
264
300
 
265
301
  def method_visibility(method)
266
- case
267
- when private_method_defined?(method)
302
+ if private_method_defined?(method)
268
303
  :private
269
- when protected_method_defined?(method)
304
+ elsif protected_method_defined?(method)
270
305
  :protected
271
306
  else
272
307
  :public
@@ -276,6 +311,11 @@ module StatsD
276
311
 
277
312
  attr_accessor :logger, :default_sample_rate, :prefix
278
313
  attr_writer :backend
314
+ attr_reader :default_tags
315
+
316
+ def default_tags=(tags)
317
+ @default_tags = StatsD::Instrument::Metric.normalize_tags(tags)
318
+ end
279
319
 
280
320
  def backend
281
321
  @backend ||= StatsD::Instrument::Environment.default_backend
@@ -310,11 +350,16 @@ module StatsD
310
350
  value, metric_options = parse_options(value, metric_options)
311
351
  type = (!metric_options.empty? && metric_options.first[:as_dist] ? :d : :ms)
312
352
 
313
- result = nil
314
- value = 1000 * StatsD::Instrument.duration { result = block.call } if block_given?
315
- metric = collect_metric(type, key, value, metric_options)
316
- result = metric unless block_given?
317
- result
353
+ return collect_metric(type, key, value, metric_options) unless block_given?
354
+
355
+ start = StatsD::Instrument.current_timestamp
356
+ begin
357
+ block.call
358
+ ensure
359
+ # Ensure catches both a raised exception and a return in the invoked block
360
+ value = 1000 * (StatsD::Instrument.current_timestamp - start)
361
+ collect_metric(type, key, value, metric_options)
362
+ end
318
363
  end
319
364
 
320
365
  # Emits a counter metric.
@@ -371,13 +416,18 @@ module StatsD
371
416
  # http_response = StatsD.distribution('HTTP.call.duration') do
372
417
  # HTTP.get(url)
373
418
  # end
374
- def distribution(key, value=nil, *metric_options, &block)
419
+ def distribution(key, value = nil, *metric_options, &block)
375
420
  value, metric_options = parse_options(value, metric_options)
376
- result = nil
377
- value = 1000 * StatsD::Instrument.duration { result = block.call } if block_given?
378
- metric = collect_metric(:d, key, value, metric_options)
379
- result = metric unless block_given?
380
- result
421
+
422
+ return collect_metric(:d, key, value, metric_options) unless block_given?
423
+
424
+ start = StatsD::Instrument.current_timestamp
425
+ begin
426
+ block.call
427
+ ensure
428
+ value = 1000 * (StatsD::Instrument.current_timestamp - start)
429
+ collect_metric(:d, key, value, metric_options)
430
+ end
381
431
  end
382
432
 
383
433
  # Emits a key/value metric.
@@ -426,7 +476,7 @@ module StatsD
426
476
  # @param args [Array] The list of non-required arguments.
427
477
  # @return [Hash] The hash of optional arguments.
428
478
  def hash_argument(args)
429
- return {} if args.length == 0
479
+ return {} if args.empty?
430
480
  return args.first if args.length == 1 && args.first.is_a?(Hash)
431
481
 
432
482
  order = [:sample_rate, :tags]
@@ -434,8 +484,7 @@ module StatsD
434
484
  args.each_with_index do |value, index|
435
485
  hash[order[index]] = value
436
486
  end
437
-
438
- return hash
487
+ hash
439
488
  end
440
489
 
441
490
  def parse_options(value, metric_options)
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'statsd/instrument'
@@ -1,21 +1,23 @@
1
+ # frozen-string-literal: true
1
2
  # encoding: utf-8
3
+
2
4
  lib = File.expand_path('../lib', __FILE__)
3
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
6
  require 'statsd/instrument/version'
5
7
 
6
8
  Gem::Specification.new do |spec|
7
- spec.name = "statsd-instrument"
8
- spec.version = StatsD::Instrument::VERSION
9
- spec.authors = ["Jesse Storimer", "Tobias Lutke", "Willem van Bergen"]
10
- spec.email = ["jesse@shopify.com"]
11
- spec.homepage = "https://github.com/Shopify/statsd-instrument"
12
- spec.summary = %q{A StatsD client for Ruby apps}
9
+ spec.name = "statsd-instrument"
10
+ spec.version = StatsD::Instrument::VERSION
11
+ spec.authors = ["Jesse Storimer", "Tobias Lutke", "Willem van Bergen"]
12
+ spec.email = ["jesse@shopify.com"]
13
+ spec.homepage = "https://github.com/Shopify/statsd-instrument"
14
+ spec.summary = %q{A StatsD client for Ruby apps}
13
15
  spec.description = %q{A StatsD client for Ruby apps. Provides metaprogramming methods to inject StatsD instrumentation into your code.}
14
- spec.license = "MIT"
16
+ spec.license = "MIT"
15
17
 
16
- spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.files = `git ls-files`.split($/)
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
21
  spec.require_paths = ["lib"]
20
22
 
21
23
  spec.add_development_dependency 'rake'
@@ -23,5 +25,6 @@ Gem::Specification.new do |spec|
23
25
  spec.add_development_dependency 'rspec'
24
26
  spec.add_development_dependency 'mocha'
25
27
  spec.add_development_dependency 'yard'
28
+ spec.add_development_dependency 'rubocop'
26
29
  spec.add_development_dependency 'benchmark-ips'
27
30
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class AssertionsTest < Minitest::Test
@@ -163,6 +165,15 @@ class AssertionsTest < Minitest::Test
163
165
  end
164
166
  end
165
167
 
168
+ def test_tags_friendly_error
169
+ @test_case.assert_statsd_increment('counter', tags: { class: "AnotherJob" }) do
170
+ StatsD.increment('counter', tags: { class: "MyJob" })
171
+ end
172
+ rescue MiniTest::Assertion => assertion
173
+ assert_match(/Captured metrics with the same key/, assertion.message)
174
+ assert_match(/MyJob/, assertion.message)
175
+ end
176
+
166
177
  def test_multiple_metrics_are_not_order_dependent
167
178
  assert_no_assertion_triggered do
168
179
  foo_1_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:1'])
@@ -262,7 +273,7 @@ class AssertionsTest < Minitest::Test
262
273
  def test_assert_statsd_call_with_wrong_sample_rate_type
263
274
  assert_assertion_triggered "Unexpected sample rate type for metric counter, must be numeric" do
264
275
  @test_case.assert_statsd_increment('counter', tags: ['a', 'b']) do
265
- StatsD.increment('counter', sample_rate: 'abc', tags: ['a', 'b'])
276
+ StatsD.increment('counter', sample_rate: 'abc', tags: ['a', 'b'])
266
277
  end
267
278
  end
268
279
  end
@@ -309,7 +320,7 @@ class AssertionsTest < Minitest::Test
309
320
  def assert_no_assertion_triggered(&block)
310
321
  block.call
311
322
  rescue MiniTest::Assertion => assertion
312
- flunk "No assertion trigger expected, but one was triggered with message #{assertion.message}."
323
+ flunk("No assertion trigger expected, but one was triggered with message #{assertion.message}.")
313
324
  else
314
325
  pass
315
326
  end
@@ -318,12 +329,12 @@ class AssertionsTest < Minitest::Test
318
329
  block.call
319
330
  rescue MiniTest::Assertion => assertion
320
331
  if message
321
- assert_equal message, assertion.message, "Assertion triggered, but message was not what was expected."
332
+ assert_equal(message, assertion.message, "Assertion triggered, but message was not what was expected.")
322
333
  else
323
334
  pass
324
335
  end
325
336
  assertion
326
337
  else
327
- flunk "No assertion was triggered, but one was expected."
338
+ flunk("No assertion was triggered, but one was expected.")
328
339
  end
329
340
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'statsd-instrument'
4
+ require 'benchmark/ips'
5
+
6
+ StatsD.logger = Logger.new('/dev/null')
7
+
8
+ class Suite
9
+ def warming(*args)
10
+ StatsD.default_tags = if args[0] == "with default tags"
11
+ { first_tag: 'first_value', second_tag: 'second_value' }
12
+ end
13
+ puts "warming with default tags: #{StatsD.default_tags}"
14
+ end
15
+
16
+ def running(*args)
17
+ StatsD.default_tags = if args[0] == "with default tags"
18
+ { first_tag: 'first_value', second_tag: 'second_value' }
19
+ end
20
+ puts "running with default tags: #{StatsD.default_tags}"
21
+ end
22
+
23
+ def warmup_stats(*)
24
+ end
25
+
26
+ def add_report(*)
27
+ end
28
+ end
29
+
30
+ suite = Suite.new
31
+
32
+ Benchmark.ips do |bench|
33
+ bench.config(suite: suite)
34
+ bench.report("without default tags") do
35
+ StatsD.increment('GoogleBase.insert', tags: {
36
+ first_tag: 'first_value',
37
+ second_tag: 'second_value',
38
+ third_tag: 'third_value',
39
+ })
40
+ end
41
+
42
+ bench.report("with default tags") do
43
+ StatsD.increment('GoogleBase.insert', tags: { third_tag: 'third_value' })
44
+ end
45
+
46
+ bench.compare!
47
+ end
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'statsd-instrument'
2
4
  require 'benchmark/ips'
3
5
 
4
- def helperFunction()
5
- a = 10
6
- a += a
7
- a -= a
8
- a *= a
6
+ def helper_function
7
+ a = 10
8
+ a += a
9
+ a -= a
10
+ a * a
9
11
  end
10
12
 
11
13
  Benchmark.ips do |bench|
@@ -14,8 +16,8 @@ Benchmark.ips do |bench|
14
16
  end
15
17
 
16
18
  bench.report("measure metric benchmark") do
17
- StatsD.measure('helperFunction') do
18
- helperFunction()
19
+ StatsD.measure('helper_function') do
20
+ helper_function
19
21
  end
20
22
  end
21
23
 
@@ -34,5 +36,4 @@ Benchmark.ips do |bench|
34
36
  bench.report("service check metric benchmark") do
35
37
  StatsD.service_check('shipit.redis_connection', 'ok')
36
38
  end
37
-
38
39
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'statsd-instrument'
2
4
  require 'benchmark/ips'
3
5
 
4
6
  Benchmark.ips do |bench|
5
7
  bench.report("normalized tags with simple hash") do
6
- StatsD::Instrument::Metric.normalize_tags(:tag => 'value')
8
+ StatsD::Instrument::Metric.normalize_tags(tag: 'value')
7
9
  end
8
10
 
9
11
  bench.report("normalized tags with simple array") do
@@ -11,14 +13,14 @@ Benchmark.ips do |bench|
11
13
  end
12
14
 
13
15
  bench.report("normalized tags with large hash") do
14
- StatsD::Instrument::Metric.normalize_tags({
16
+ StatsD::Instrument::Metric.normalize_tags(
15
17
  mobile: true,
16
18
  pod: "1",
17
19
  protocol: "https",
18
20
  country: "Langbortistan",
19
21
  complete: true,
20
22
  shop: "omg shop that has a longer name",
21
- })
23
+ )
22
24
  end
23
25
 
24
26
  bench.report("normalized tags with large array") do
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class CaptureBackendTest < Minitest::Test
4
6
  def setup
5
7
  @backend = StatsD::Instrument::Backends::CaptureBackend.new
6
- @metric1 = StatsD::Instrument::Metric::new(type: :c, name: 'mock.counter')
7
- @metric2 = StatsD::Instrument::Metric::new(type: :ms, name: 'mock.measure', value: 123)
8
+ @metric1 = StatsD::Instrument::Metric.new(type: :c, name: 'mock.counter')
9
+ @metric2 = StatsD::Instrument::Metric.new(type: :ms, name: 'mock.measure', value: 123)
8
10
  end
9
11
 
10
12
  def test_collecting_metric
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module Rails; end
4
6
 
5
7
  class EnvironmentTest < Minitest::Test
6
-
7
8
  def setup
8
9
  ENV['STATSD_ADDR'] = nil
9
10
  ENV['IMPLEMENTATION'] = nil
data/test/helpers_test.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class HelpersTest < Minitest::Test
@@ -21,4 +23,3 @@ class HelpersTest < Minitest::Test
21
23
  assert_equal 12, metrics[1].value
22
24
  end
23
25
  end
24
-
@@ -1,20 +1,40 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class IntegrationTest < Minitest::Test
4
-
5
6
  def setup
6
- @old_backend, StatsD.backend = StatsD.backend, StatsD::Instrument::Backends::UDPBackend.new("localhost:31798")
7
+ @server = UDPSocket.new
8
+ @server.bind('localhost', 0)
9
+ port = @server.addr[1]
10
+
11
+ @old_backend = StatsD.backend
12
+ StatsD.backend = StatsD::Instrument::Backends::UDPBackend.new("localhost:#{port}")
7
13
  end
8
-
14
+
9
15
  def teardown
16
+ @server.close
10
17
  StatsD.backend = @old_backend
11
18
  end
12
19
 
13
20
  def test_live_local_udp_socket
14
- server = UDPSocket.new
15
- server.bind('localhost', 31798)
16
-
17
21
  StatsD.increment('counter')
18
- assert_equal "counter:1|c", server.recvfrom(100).first
22
+ assert_equal "counter:1|c", @server.recvfrom(100).first
23
+ end
24
+
25
+ def test_synchronize_in_exit_handler_handles_thread_error_and_exits_cleanly
26
+ pid = fork do
27
+ Signal.trap('TERM') do
28
+ StatsD.increment('exiting')
29
+ Process.exit!(0)
30
+ end
31
+
32
+ sleep 100
33
+ end
34
+
35
+ Process.kill('TERM', pid)
36
+ Process.waitpid(pid)
37
+
38
+ assert_equal "exiting:1|c", @server.recvfrom(100).first
19
39
  end
20
40
  end
@@ -1,20 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class LoggerBackendTest < Minitest::Test
4
6
  def setup
5
7
  logger = Logger.new(@io = StringIO.new)
6
- logger.formatter = lambda { |_,_,_, msg| "#{msg}\n" }
8
+ logger.formatter = lambda { |_, _, _, msg| "#{msg}\n" }
7
9
  @backend = StatsD::Instrument::Backends::LoggerBackend.new(logger)
8
- @metric1 = StatsD::Instrument::Metric::new(type: :c, name: 'mock.counter', tags: { a: 'b', c: 'd'})
9
- @metric2 = StatsD::Instrument::Metric::new(type: :ms, name: 'mock.measure', value: 123, sample_rate: 0.3)
10
+ @metric1 = StatsD::Instrument::Metric.new(type: :c, name: 'mock.counter', tags: { a: 'b', c: 'd' })
11
+ @metric2 = StatsD::Instrument::Metric.new(type: :ms, name: 'mock.measure', value: 123, sample_rate: 0.3)
10
12
  end
11
13
 
12
14
  def test_logs_metrics
13
15
  @backend.collect_metric(@metric1)
14
- assert_equal @io.string, "[StatsD] increment mock.counter:1 #a:b #c:d\n"
15
- @io.string = ""
16
-
17
16
  @backend.collect_metric(@metric2)
18
- assert_equal @io.string, "[StatsD] measure mock.measure:123 @0.3\n"
17
+ assert_equal <<~LOG, @io.string
18
+ [StatsD] increment mock.counter:1 #a:b #c:d
19
+ [StatsD] measure mock.measure:123 @0.3
20
+ LOG
19
21
  end
20
- end
22
+ end