statsd-instrument 2.8.0 → 2.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +16 -7
  3. data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +6 -6
  4. data/CHANGELOG.md +28 -6
  5. data/CONTRIBUTING.md +3 -3
  6. data/README.md +11 -11
  7. data/lib/statsd/instrument.rb +33 -18
  8. data/lib/statsd/instrument/assertions.rb +7 -7
  9. data/lib/statsd/instrument/backend.rb +1 -1
  10. data/lib/statsd/instrument/client.rb +11 -10
  11. data/lib/statsd/instrument/datagram.rb +1 -2
  12. data/lib/statsd/instrument/datagram_builder.rb +1 -1
  13. data/lib/statsd/instrument/dogstatsd_datagram.rb +88 -0
  14. data/lib/statsd/instrument/dogstatsd_datagram_builder.rb +4 -0
  15. data/lib/statsd/instrument/expectation.rb +37 -1
  16. data/lib/statsd/instrument/legacy_client.rb +5 -5
  17. data/lib/statsd/instrument/metric.rb +2 -2
  18. data/lib/statsd/instrument/rubocop/metaprogramming_positional_arguments.rb +1 -1
  19. data/lib/statsd/instrument/rubocop/positional_arguments.rb +6 -6
  20. data/lib/statsd/instrument/rubocop/singleton_configuration.rb +1 -1
  21. data/lib/statsd/instrument/strict.rb +37 -17
  22. data/lib/statsd/instrument/version.rb +1 -1
  23. data/test/assertions_on_legacy_client_test.rb +1 -1
  24. data/test/assertions_test.rb +26 -1
  25. data/test/capture_sink_test.rb +1 -1
  26. data/test/client_test.rb +5 -5
  27. data/test/compatibility/dogstatsd_datagram_compatibility_test.rb +1 -1
  28. data/test/datagram_builder_test.rb +1 -1
  29. data/test/deprecations_test.rb +8 -1
  30. data/test/dogstatsd_datagram_builder_test.rb +41 -4
  31. data/test/environment_test.rb +1 -1
  32. data/test/integration_test.rb +1 -1
  33. data/test/log_sink_test.rb +1 -1
  34. data/test/null_sink_test.rb +1 -1
  35. data/test/rubocop/metric_prefix_argument_test.rb +1 -1
  36. data/test/rubocop/positional_arguments_test.rb +3 -3
  37. data/test/statsd_instrumentation_test.rb +11 -0
  38. data/test/statsd_test.rb +2 -9
  39. data/test/udp_backend_test.rb +3 -0
  40. data/test/udp_sink_test.rb +1 -1
  41. metadata +3 -2
@@ -333,7 +333,7 @@ class AssertionsOnLegacyClientTest < Minitest::Test
333
333
  end
334
334
 
335
335
  def test_assertion_block_with_other_assertion_failures
336
- # If another assertion failure happens inside the block, that failrue should have priority
336
+ # If another assertion failure happens inside the block, that failure should have priority
337
337
  assertion = assert_raises(Minitest::Assertion) do
338
338
  @test_case.assert_statsd_increment('counter') do
339
339
  @test_case.flunk('other assertion failure')
@@ -33,6 +33,31 @@ class AssertionsTest < Minitest::Test
33
33
  end
34
34
  assert_equal assertion.message, "No StatsD calls for metric counter expected."
35
35
 
36
+ @test_case.assert_no_statsd_calls('counter1', 'counter2') do
37
+ # noop
38
+ end
39
+
40
+ @test_case.assert_no_statsd_calls('counter1', 'counter2') do
41
+ StatsD.increment('counter')
42
+ end
43
+
44
+ assertion = assert_raises(Minitest::Assertion) do
45
+ @test_case.assert_no_statsd_calls('counter1', 'counter2') do
46
+ StatsD.increment('counter0')
47
+ StatsD.increment('counter1')
48
+ StatsD.increment('counter2')
49
+ StatsD.increment('counter3')
50
+ end
51
+ end
52
+ assert_equal assertion.message, "No StatsD calls for metric counter1, counter2 expected."
53
+
54
+ assertion = assert_raises(Minitest::Assertion) do
55
+ @test_case.assert_no_statsd_calls('counter0', 'counter1', 'counter2') do
56
+ StatsD.increment('counter1')
57
+ end
58
+ end
59
+ assert_equal assertion.message, "No StatsD calls for metric counter1 expected."
60
+
36
61
  assertion = assert_raises(Minitest::Assertion) do
37
62
  @test_case.assert_no_statsd_calls do
38
63
  StatsD.increment('other')
@@ -363,7 +388,7 @@ class AssertionsTest < Minitest::Test
363
388
  end
364
389
 
365
390
  def test_assertion_block_with_other_assertion_failures
366
- # If another assertion failure happens inside the block, that failrue should have priority
391
+ # If another assertion failure happens inside the block, that failure should have priority
367
392
  assertion = assert_raises(Minitest::Assertion) do
368
393
  @test_case.assert_statsd_increment('counter') do
369
394
  @test_case.flunk('other assertion failure')
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'test_helper'
4
4
 
5
- class CaptureSinktest < Minitest::Test
5
+ class CaptureSinkTest < Minitest::Test
6
6
  def test_capture_sink_captures_datagram_instances
7
7
  capture_sink = StatsD::Instrument::CaptureSink.new(parent: [])
8
8
  capture_sink << 'foo:1|c'
@@ -75,11 +75,11 @@ class ClientTest < Minitest::Test
75
75
  assert_equal ['baz'], inner_datagrams.map(&:name)
76
76
  end
77
77
 
78
- def test_metric_methods_return_nil
79
- assert_nil @client.increment('foo')
80
- assert_nil @client.measure('bar', 122.54)
81
- assert_nil @client.set('baz', 123)
82
- assert_nil @client.gauge('baz', 12.3)
78
+ def test_metric_methods_return_truish_void
79
+ assert @client.increment('foo')
80
+ assert @client.measure('bar', 122.54)
81
+ assert @client.set('baz', 123)
82
+ assert @client.gauge('baz', 12.3)
83
83
  end
84
84
 
85
85
  def test_increment_with_default_value
@@ -101,7 +101,7 @@ module Compatibility
101
101
  assert_equal_datagrams { |client| client.event('foo', "bar\nbaz") }
102
102
  assert_equal_datagrams { |client| client.event('foo', "bar\nbaz", no_prefix: true) }
103
103
  assert_equal_datagrams do |client|
104
- client.event('Something happend', "And it's not good", timestamp: Time.parse('2019-09-09T04:22:17Z'),
104
+ client.event('Something happened', "And it's not good", timestamp: Time.parse('2019-09-09T04:22:17Z'),
105
105
  hostname: 'localhost', tags: ['foo'], alert_type: 'warning', priority: 'low',
106
106
  aggregation_key: 'foo', source_type_name: 'logs')
107
107
  end
@@ -18,7 +18,7 @@ class DatagramBuilderTest < Minitest::Test
18
18
  assert_equal ['ign#ored'], @datagram_builder.send(:normalize_tags, ['ign#o|re,d'])
19
19
  # Note: how this is interpreted by the backend is undefined.
20
20
  # We rely on the user to not do stuff like this if they don't want to be surprised.
21
- # We do not want to take the performance hit of normaling this.
21
+ # We do not want to take the performance hit of normalizing this.
22
22
  assert_equal ['lol::class:omg::lol'], @datagram_builder.send(:normalize_tags, "lol::class" => "omg::lol")
23
23
  end
24
24
 
@@ -74,7 +74,7 @@ class DeprecationsTest < Minitest::Test
74
74
  # rubocop:enable StatsD/MetricValueKeywordArgument
75
75
 
76
76
  # rubocop:disable StatsD/MetricReturnValue
77
- def test__deprecated__statsd_increment_retuns_metric_instance
77
+ def test__deprecated__statsd_increment_returns_metric_instance
78
78
  metric = StatsD.increment('key')
79
79
  assert_kind_of StatsD::Instrument::Metric, metric
80
80
  assert_equal 'key', metric.name
@@ -122,6 +122,13 @@ class DeprecationsTest < Minitest::Test
122
122
  end
123
123
  # rubocop:enable StatsD/MetricPrefixArgument
124
124
 
125
+ def test__deprecated__statsd_key_value
126
+ metric = capture_statsd_call { StatsD.key_value('values.foobar', 42) }
127
+ assert_equal :kv, metric.type
128
+ assert_equal 'values.foobar', metric.name
129
+ assert_equal 42, metric.value
130
+ end
131
+
125
132
  protected
126
133
 
127
134
  def capture_statsd_call(&block)
@@ -11,20 +11,57 @@ class DogStatsDDatagramBuilderTest < Minitest::Test
11
11
  assert_raises(NotImplementedError) { @datagram_builder.kv('foo', 10, nil, nil) }
12
12
  end
13
13
 
14
- def test_service_check
15
- assert_equal '_sc|service|0', @datagram_builder._sc('service', :ok)
14
+ def test_simple_service_check
15
+ datagram = @datagram_builder._sc('service', :ok)
16
+ assert_equal '_sc|service|0', datagram
17
+ parsed_datagram = StatsD::Instrument::DogStatsDDatagramBuilder.datagram_class.new(datagram)
18
+ assert_equal :_sc, parsed_datagram.type
19
+ assert_equal 'service', parsed_datagram.name
20
+ assert_equal 0, parsed_datagram.value
21
+ end
22
+
23
+ def test_complex_service_check
16
24
  datagram = @datagram_builder._sc('service', :warning, timestamp: Time.parse('2019-09-30T04:22:12Z'),
17
25
  hostname: 'localhost', tags: { foo: 'bar|baz' }, message: 'blah')
18
26
  assert_equal "_sc|service|1|h:localhost|d:1569817332|#foo:barbaz|m:blah", datagram
27
+
28
+ parsed_datagram = StatsD::Instrument::DogStatsDDatagramBuilder.datagram_class.new(datagram)
29
+ assert_equal :_sc, parsed_datagram.type
30
+ assert_equal 'service', parsed_datagram.name
31
+ assert_equal 1, parsed_datagram.value
32
+ assert_equal 'localhost', parsed_datagram.hostname
33
+ assert_equal Time.parse('2019-09-30T04:22:12Z'), parsed_datagram.timestamp
34
+ assert_equal ["foo:barbaz"], parsed_datagram.tags
35
+ assert_equal 'blah', parsed_datagram.message
19
36
  end
20
37
 
21
- def test_event
22
- assert_equal '_e{5,5}:hello|world', @datagram_builder._e('hello', "world")
38
+ def test_simple_event
39
+ datagram = @datagram_builder._e('hello', "world")
40
+ assert_equal '_e{5,5}:hello|world', datagram
23
41
 
42
+ parsed_datagram = StatsD::Instrument::DogStatsDDatagramBuilder.datagram_class.new(datagram)
43
+ assert_equal :_e, parsed_datagram.type
44
+ assert_equal 'hello', parsed_datagram.name
45
+ assert_equal 'world', parsed_datagram.value
46
+ end
47
+
48
+ def test_complex_event
24
49
  datagram = @datagram_builder._e("testing", "with\nnewline", timestamp: Time.parse('2019-09-30T04:22:12Z'),
25
50
  hostname: 'localhost', aggregation_key: 'my-key', priority: 'low', source_type_name: 'source',
26
51
  alert_type: 'success', tags: { foo: 'bar|baz' })
27
52
  assert_equal '_e{7,13}:testing|with\\nnewline|h:localhost|d:1569817332|k:my-key|' \
28
53
  'p:low|s:source|t:success|#foo:barbaz', datagram
54
+
55
+ parsed_datagram = StatsD::Instrument::DogStatsDDatagramBuilder.datagram_class.new(datagram)
56
+ assert_equal :_e, parsed_datagram.type
57
+ assert_equal 'testing', parsed_datagram.name
58
+ assert_equal "with\nnewline", parsed_datagram.value
59
+ assert_equal 'localhost', parsed_datagram.hostname
60
+ assert_equal Time.parse('2019-09-30T04:22:12Z'), parsed_datagram.timestamp
61
+ assert_equal ["foo:barbaz"], parsed_datagram.tags
62
+ assert_equal "my-key", parsed_datagram.aggregation_key
63
+ assert_equal "low", parsed_datagram.priority
64
+ assert_equal "source", parsed_datagram.source_type_name
65
+ assert_equal "success", parsed_datagram.alert_type
29
66
  end
30
67
  end
@@ -67,7 +67,7 @@ class EnvironmentTest < Minitest::Test
67
67
  assert_kind_of StatsD::Instrument::LegacyClient, env.client
68
68
  end
69
69
 
70
- def test_client_returns_new_client_if_envcironment_asks_for_it
70
+ def test_client_returns_new_client_if_environment_asks_for_it
71
71
  env = StatsD::Instrument::Environment.new('STATSD_USE_NEW_CLIENT' => '1')
72
72
  assert_kind_of StatsD::Instrument::Client, env.client
73
73
  end
@@ -35,7 +35,7 @@ class IntegrationTest < Minitest::Test
35
35
  Process.kill('TERM', pid)
36
36
  _, exit_status = Process.waitpid2(pid)
37
37
 
38
- assert_equal 0, exit_status, "The foked process did not exit cleanly"
38
+ assert_equal 0, exit_status, "The forked process did not exit cleanly"
39
39
  assert_equal "exiting:1|c", @server.recvfrom_nonblock(100).first
40
40
 
41
41
  rescue NotImplementedError
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'test_helper'
4
4
 
5
- class LogSinktest < Minitest::Test
5
+ class LogSinkTest < Minitest::Test
6
6
  def test_log_sink
7
7
  logger = Logger.new(log = StringIO.new)
8
8
  logger.formatter = proc do |severity, _datetime, _progname, msg|
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'test_helper'
4
4
 
5
- class NullSinktest < Minitest::Test
5
+ class NullSinkTest < Minitest::Test
6
6
  def test_null_sink
7
7
  null_sink = StatsD::Instrument::NullSink.new
8
8
  null_sink << 'foo:1|c' << 'bar:1|c'
@@ -19,7 +19,7 @@ module Rubocop
19
19
 
20
20
  def test_ok_for_metaprogramming_method_without_prefix_argument
21
21
  assert_no_offenses("statsd_measure(:method, 'metric_name')")
22
- assert_no_offenses("statsd_count(:method, 'metric_name', sample_rate: 1, no_pefix: true)")
22
+ assert_no_offenses("statsd_count(:method, 'metric_name', sample_rate: 1, no_prefix: true)")
23
23
  assert_no_offenses("statsd_count_if(:method, 'metric_name', sample_rate: 1) {}")
24
24
  end
25
25
 
@@ -21,7 +21,7 @@ module Rubocop
21
21
  assert_no_offenses("StatsD.gauge('foo', 2, **kwargs)")
22
22
  end
23
23
 
24
- def test_no_offense_for_now_when_using_value_keyword_argumenr
24
+ def test_no_offense_for_now_when_using_value_keyword_argument
25
25
  assert_no_offenses("StatsD.increment 'foo', value: 3")
26
26
  assert_no_offenses("StatsD.increment 'foo', value: 3, sample_rate: 0.5")
27
27
  assert_no_offenses("StatsD.increment('foo', value: 3, tags: ['foo']) { foo }")
@@ -29,7 +29,7 @@ module Rubocop
29
29
 
30
30
  def test_offense_when_using_method_or_constant
31
31
  assert_offense("StatsD.gauge('foo', 2, SAMPLE_RATE_CONSTANT)")
32
- assert_offense("StatsD.gauge('foo', 2, method_ruturning_a_hash)")
32
+ assert_offense("StatsD.gauge('foo', 2, method_returning_a_hash)")
33
33
  end
34
34
 
35
35
  def test_offense_when_using_local_variable
@@ -46,7 +46,7 @@ module Rubocop
46
46
 
47
47
  def test_no_autocorrect_when_using_method_or_constant
48
48
  assert_no_autocorrect("StatsD.gauge('foo', 2, SAMPLE_RATE_CONSTANT)")
49
- assert_no_autocorrect("StatsD.gauge('foo', 2, method_ruturning_a_hash)")
49
+ assert_no_autocorrect("StatsD.gauge('foo', 2, method_returning_a_hash)")
50
50
  end
51
51
 
52
52
  def test_autocorrect_only_sample_rate
@@ -443,6 +443,17 @@ class StatsDInstrumentationTest < Minitest::Test
443
443
  StatsD.singleton_client = old_client
444
444
  end
445
445
 
446
+ def test_statsd_count_with_injected_client
447
+ client = StatsD::Instrument::Client.new(prefix: 'prefix')
448
+
449
+ ActiveMerchant::Gateway.statsd_count(:ssl_post, 'ActiveMerchant.Gateway.ssl_post', client: client)
450
+ assert_statsd_increment('prefix.ActiveMerchant.Gateway.ssl_post', client: client) do
451
+ ActiveMerchant::Gateway.new.purchase(true)
452
+ end
453
+ ensure
454
+ ActiveMerchant::Gateway.statsd_remove_count :ssl_post, 'ActiveMerchant.Gateway.ssl_post'
455
+ end
456
+
446
457
  private
447
458
 
448
459
  def assert_scope(klass, method, expected_scope)
@@ -189,19 +189,12 @@ class StatsDTest < Minitest::Test
189
189
  assert_nil return_value
190
190
  end
191
191
 
192
- def test_statsd_key_value
193
- metric = capture_statsd_call { StatsD.key_value('values.foobar', 42) }
194
- assert_equal :kv, metric.type
195
- assert_equal 'values.foobar', metric.name
196
- assert_equal 42, metric.value
197
- end
198
-
199
- def test_statsd_durarion_returns_time_in_seconds
192
+ def test_statsd_duration_returns_time_in_seconds
200
193
  duration = StatsD::Instrument.duration {}
201
194
  assert_kind_of Float, duration
202
195
  end
203
196
 
204
- def test_statsd_durarion_does_not_swallow_exceptions
197
+ def test_statsd_duration_does_not_swallow_exceptions
205
198
  assert_raises(RuntimeError) do
206
199
  StatsD::Instrument.duration { raise "Foo" }
207
200
  end
@@ -160,6 +160,7 @@ class UDPBackendTest < Minitest::Test
160
160
  end
161
161
 
162
162
  def test_supports_key_value_syntax_on_statsite
163
+ skip if StatsD::Instrument.strict_mode_enabled?
163
164
  @backend.implementation = :statsite
164
165
  @backend.expects(:write_packet).with("fooy:42|kv\n")
165
166
  StatsD.key_value('fooy', 42)
@@ -173,6 +174,7 @@ class UDPBackendTest < Minitest::Test
173
174
 
174
175
  # rubocop:disable StatsD/PositionalArguments
175
176
  def test_supports_key_value_with_timestamp_on_statsite
177
+ skip if StatsD::Instrument.strict_mode_enabled?
176
178
  @backend.implementation = :statsite
177
179
  @backend.expects(:write_packet).with("fooy:42|kv|@123456\n")
178
180
  StatsD.key_value('fooy', 42, 123456)
@@ -180,6 +182,7 @@ class UDPBackendTest < Minitest::Test
180
182
  # rubocop:enable StatsD/PositionalArguments
181
183
 
182
184
  def test_warn_when_using_key_value_and_not_on_statsite
185
+ skip if StatsD::Instrument.strict_mode_enabled?
183
186
  @backend.implementation = :other
184
187
  @backend.expects(:write_packet).never
185
188
  @logger.expects(:warn)
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'test_helper'
4
4
 
5
- class UDPSinktest < Minitest::Test
5
+ class UDPSinkTest < Minitest::Test
6
6
  def setup
7
7
  @receiver = UDPSocket.new
8
8
  @receiver.bind('localhost', 0)
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: 2.8.0
4
+ version: 2.9.0
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: 2019-10-21 00:00:00.000000000 Z
13
+ date: 2019-10-31 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
@@ -148,6 +148,7 @@ files:
148
148
  - lib/statsd/instrument/client.rb
149
149
  - lib/statsd/instrument/datagram.rb
150
150
  - lib/statsd/instrument/datagram_builder.rb
151
+ - lib/statsd/instrument/dogstatsd_datagram.rb
151
152
  - lib/statsd/instrument/dogstatsd_datagram_builder.rb
152
153
  - lib/statsd/instrument/environment.rb
153
154
  - lib/statsd/instrument/expectation.rb