statsd-instrument 3.0.0 → 3.0.1

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +3 -3
  3. data/.rubocop.yml +3 -13
  4. data/CHANGELOG.md +6 -0
  5. data/Gemfile +8 -0
  6. data/README.md +2 -2
  7. data/Rakefile +1 -1
  8. data/bin/rake +29 -0
  9. data/bin/rubocop +29 -0
  10. data/lib/statsd/instrument.rb +4 -1
  11. data/lib/statsd/instrument/assertions.rb +200 -196
  12. data/lib/statsd/instrument/capture_sink.rb +23 -19
  13. data/lib/statsd/instrument/client.rb +414 -410
  14. data/lib/statsd/instrument/datagram.rb +69 -65
  15. data/lib/statsd/instrument/datagram_builder.rb +81 -77
  16. data/lib/statsd/instrument/dogstatsd_datagram.rb +76 -72
  17. data/lib/statsd/instrument/dogstatsd_datagram_builder.rb +68 -64
  18. data/lib/statsd/instrument/environment.rb +80 -77
  19. data/lib/statsd/instrument/expectation.rb +96 -92
  20. data/lib/statsd/instrument/helpers.rb +11 -7
  21. data/lib/statsd/instrument/log_sink.rb +20 -16
  22. data/lib/statsd/instrument/matchers.rb +86 -70
  23. data/lib/statsd/instrument/null_sink.rb +12 -8
  24. data/lib/statsd/instrument/railtie.rb +11 -7
  25. data/lib/statsd/instrument/statsd_datagram_builder.rb +12 -8
  26. data/lib/statsd/instrument/udp_sink.rb +50 -46
  27. data/lib/statsd/instrument/version.rb +1 -1
  28. data/statsd-instrument.gemspec +2 -8
  29. data/test/assertions_test.rb +12 -12
  30. data/test/capture_sink_test.rb +8 -8
  31. data/test/client_test.rb +54 -54
  32. data/test/datagram_builder_test.rb +29 -29
  33. data/test/datagram_test.rb +1 -1
  34. data/test/dogstatsd_datagram_builder_test.rb +28 -28
  35. data/test/environment_test.rb +9 -9
  36. data/test/helpers/rubocop_helper.rb +9 -6
  37. data/test/helpers_test.rb +5 -5
  38. data/test/integration_test.rb +1 -1
  39. data/test/log_sink_test.rb +2 -2
  40. data/test/matchers_test.rb +36 -36
  41. data/test/null_sink_test.rb +2 -2
  42. data/test/rubocop/metric_return_value_test.rb +3 -3
  43. data/test/rubocop/positional_arguments_test.rb +10 -10
  44. data/test/statsd_instrumentation_test.rb +66 -66
  45. data/test/statsd_test.rb +44 -44
  46. data/test/test_helper.rb +6 -4
  47. data/test/udp_sink_test.rb +8 -8
  48. metadata +7 -103
  49. data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +0 -1027
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e941d77f1b0893b2a919f8c36e902e119c657338e6a4e8b45fc5eaa7b5a05a3
4
- data.tar.gz: f80105adf47e4379a59716bd7bb46080db3ed9751edf9ef21ef64689ce39920a
3
+ metadata.gz: 3a26da2deac1a048fae156e2e8804ec5a423fde1e383ed1b3c446d34b0c553ec
4
+ data.tar.gz: edae81c0c408a10c4729d019930596e2a586abc17863b57642e3f2a0ff1b3084
5
5
  SHA512:
6
- metadata.gz: 3518393ed260edb75f138168afad1e0f1cbd604bf12511dd73596b84d1721d0008cae138cfdef03291895bd4f8b861dd18b641dcfda093e84976a0d446da5bd3
7
- data.tar.gz: 4fd2bc2646b88b497802103eaed1538234e37619ef35363ed061b43ce100dd4d59f03de037b5b766c46e8937b7c926fbba2a0dba7f10d5610fae43e2c31f17f2
6
+ metadata.gz: 87037561be37e4fbf2cdee8e32564b35ae66b9d4c5a308e4784764d879171644ce2e0e5470fca8ac949b3e4ac3bff633e4bf95e83c37449dbbbe365543305bba
7
+ data.tar.gz: 9679d5832ffb8406ab800580bbab62ac3ba3d2b936ac9e841a755a90a9f09883ab62777f084a1ad6c979dbb4372f283cfed61e7e200dd32ee164da2673b82669
@@ -11,7 +11,7 @@ jobs:
11
11
  matrix:
12
12
  # Windows on macOS builds started failing, so they are disabled for noew
13
13
 
14
- ruby: [2.4, 2.5, 2.6]
14
+ ruby: [2.4, 2.5, 2.6, 2.7]
15
15
  # platform: [windows-2019, macOS-10.14, ubuntu-18.04]
16
16
 
17
17
  # exclude:
@@ -43,7 +43,7 @@ jobs:
43
43
  run: gem install bundler && bundle install --jobs 4 --retry 3
44
44
 
45
45
  - name: Run test suite
46
- run: bundle exec rake
46
+ run: rake test
47
47
 
48
48
  - name: Run Rubocop
49
- run: bundle exec rubocop
49
+ run: bin/rubocop
@@ -1,11 +1,11 @@
1
- inherit_from:
2
- - https://shopify.github.io/ruby-style-guide/rubocop.yml
1
+ inherit_gem:
2
+ rubocop-shopify: rubocop.yml
3
3
 
4
4
  require:
5
5
  - ./lib/statsd/instrument/rubocop.rb
6
6
 
7
7
  AllCops:
8
- TargetRubyVersion: 2.3
8
+ TargetRubyVersion: 2.4
9
9
  UseCache: true
10
10
  CacheRootDirectory: tmp/rubocop
11
11
  Exclude:
@@ -16,16 +16,6 @@ Naming/FileName:
16
16
  Exclude:
17
17
  - lib/statsd-instrument.rb
18
18
 
19
- Style/ClassAndModuleChildren:
20
- Enabled: false # TODO: enable later
21
-
22
-
23
- Style/MethodCallWithArgsParentheses:
24
- Enabled: false # TODO: enable later
25
-
26
- Lint/UnusedMethodArgument:
27
- AllowUnusedKeywordArguments: true
28
-
29
19
  # Enable our own cops on our own repo
30
20
 
31
21
  StatsD/MetricReturnValue:
@@ -8,6 +8,12 @@ section below.
8
8
 
9
9
  _Nothing yet_
10
10
 
11
+ ## Version 3.0.1
12
+
13
+ - Fix metaprograming methods to not print keyword argument warnings on
14
+ Ruby 2.7.
15
+ - Fix the gemspec to no longer register `rake` and `rubocop` as executables.
16
+
11
17
  ## Version 3.0.0
12
18
 
13
19
  This version makes the new client that was added in version 2.6+ the default
data/Gemfile CHANGED
@@ -3,5 +3,13 @@
3
3
  source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
+ gem 'rake'
7
+ gem 'minitest'
8
+ gem 'rspec'
9
+ gem 'mocha'
10
+ gem 'yard'
11
+ gem 'rubocop'
12
+ gem 'rubocop-shopify', require: false
13
+
6
14
  # benchmark-ips save! method is not part of a released version yet.
7
15
  gem 'benchmark-ips', git: 'https://github.com/evanphx/benchmark-ips', branch: 'master'
data/README.md CHANGED
@@ -105,7 +105,7 @@ Because you are counting unique values, the results of using a sampling value le
105
105
  Builds a histogram of numeric values.
106
106
  ``` ruby
107
107
 
108
- StatsD.histogram('Order.value', order.value_in_usd.to_f tags: { source: 'POS' })
108
+ StatsD.histogram('Order.value', order.value_in_usd.to_f, tags: { source: 'POS' })
109
109
  ```
110
110
 
111
111
  Because you are counting unique values, the results of using a sampling value less than 1.0 can lead to unexpected, hard to interpret results.
@@ -128,7 +128,7 @@ An event is a (title, text) tuple that can be used to correlate metrics with som
128
128
  This is a good fit for instance to correlate response time variation with a deploy of the new code.
129
129
 
130
130
  ```ruby
131
- StatsD.event('shipit.deploy', 'started', sample_rate: 1.0)
131
+ StatsD.event('shipit.deploy', 'started')
132
132
  ```
133
133
 
134
134
  *Note: This is only supported by the [datadog implementation](https://docs.datadoghq.com/guides/dogstatsd/#events).*
data/Rakefile CHANGED
@@ -9,4 +9,4 @@ Rake::TestTask.new('test') do |t|
9
9
  t.test_files = FileList['test/**/*_test.rb']
10
10
  end
11
11
 
12
- task default: :test
12
+ task(default: :test)
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load(Gem.bin_path("rake", "rake"))
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load(Gem.bin_path("rubocop", "rubocop"))
@@ -275,6 +275,9 @@ module StatsD
275
275
 
276
276
  instrumentation_module.module_eval(&block)
277
277
  instrumentation_module.send(method_scope, method)
278
+ if instrumentation_module.respond_to?(:ruby2_keywords, true)
279
+ instrumentation_module.send(:ruby2_keywords, method)
280
+ end
278
281
  prepend(instrumentation_module) unless self < instrumentation_module
279
282
  end
280
283
 
@@ -333,7 +336,7 @@ module StatsD
333
336
  # @!method distribution(name, value = nil, sample_rate: nil, tags: nil, &block)
334
337
  # (see StatsD::Instrument::Client#distribution)
335
338
  #
336
- # @!method event(title, text, tags: nil, hostname: nil, timestamp: nil, aggregation_key: nil, priority: nil, source_type_name: nil, alert_type: nil) # rubocop:disable Metrics/LineLength
339
+ # @!method event(title, text, tags: nil, hostname: nil, timestamp: nil, aggregation_key: nil, priority: nil, source_type_name: nil, alert_type: nil) # rubocop:disable Layout/LineLength
337
340
  # (see StatsD::Instrument::Client#event)
338
341
  #
339
342
  # @!method service_check(name, status, tags: nil, hostname: nil, timestamp: nil, message: nil)
@@ -1,219 +1,223 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This module defines several assertion methods that can be used to verify that
4
- # your application is emitting the right StatsD metrics.
5
- #
6
- # Every metric type has its own assertion method, like {#assert_statsd_increment}
7
- # to assert `StatsD.increment` calls. You can also assert other properties of the
8
- # metric that was emitted, like the sample rate or presence of tags.
9
- # To check for the absence of metrics, use {#assert_no_statsd_calls}.
10
- #
11
- # @example Check for metric properties:
12
- # assert_statsd_measure('foo', sample_rate: 0.1, tags: ["bar"]) do
13
- # StatsD.measure('foo', sample_rate: 0.5, tags: ['bar','baz']) do
14
- # some_code_to_measure
15
- # end
16
- # end
17
- #
18
- # @example Check for multiple occurrences:
19
- # assert_statsd_increment('foo', times: 2) do
20
- # StatsD.increment('foo')
21
- # StatsD.increment('foo')
22
- # end
23
- #
24
- # @example Absence of metrics
25
- # assert_no_statsd_calls do
26
- # foo
27
- # end
28
- #
29
- # @example Handling exceptions
30
- # assert_statsd_increment('foo.error') do
31
- # # If we expect exceptions to occur, we have to handle them inside
32
- # # the block we pass to assert_statsd_increment.
33
- # assert_raises(RuntimeError) do
34
- # begin
35
- # attempt_foo
36
- # rescue
37
- # StatsD.increment('foo.error')
38
- # raise 'foo failed'
39
- # end
40
- # end
41
- # end
42
- module StatsD::Instrument::Assertions
43
- include StatsD::Instrument::Helpers
44
-
45
- # Asserts no metric occurred during the execution of the provided block.
46
- #
47
- # @param [Array<String>] metric_names (default: []) The metric names that are not
48
- # allowed to happen inside the block. If this is set to `[]`, the assertion
49
- # will fail if any metric occurs.
50
- # @yield A block in which the specified metric should not occur. This block
51
- # should not raise any exceptions.
52
- # @return [void]
53
- # @raise [Minitest::Assertion] If an exception occurs, or if any metric (with the
54
- # provided names, or any), occurred during the execution of the provided block.
55
- def assert_no_statsd_calls(*metric_names, datagrams: nil, client: nil, &block)
56
- if datagrams.nil?
57
- raise LocalJumpError, "assert_no_statsd_calls requires a block" unless block_given?
58
- datagrams = capture_statsd_datagrams_with_exception_handling(client: client, &block)
59
- end
60
-
61
- datagrams.select! { |metric| metric_names.include?(metric.name) } unless metric_names.empty?
62
- assert(datagrams.empty?, "No StatsD calls for metric #{datagrams.map(&:name).join(', ')} expected.")
63
- end
64
-
65
- # Asserts that a given counter metric occurred inside the provided block.
66
- #
67
- # @param [String] metric_name The name of the metric that should occur.
68
- # @param [Hash] options (see StatsD::Instrument::MetricExpectation.new)
69
- # @yield A block in which the specified metric should occur. This block
70
- # should not raise any exceptions.
71
- # @return [void]
72
- # @raise [Minitest::Assertion] If an exception occurs, or if the metric did
73
- # not occur as specified during the execution the block.
74
- def assert_statsd_increment(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
75
- expectation = StatsD::Instrument::Expectation.increment(metric_name, value, **options)
76
- assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
77
- end
78
-
79
- # Asserts that a given timing metric occurred inside the provided block.
80
- #
81
- # @param metric_name (see #assert_statsd_increment)
82
- # @param options (see #assert_statsd_increment)
83
- # @yield (see #assert_statsd_increment)
84
- # @return [void]
85
- # @raise (see #assert_statsd_increment)
86
- def assert_statsd_measure(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
87
- expectation = StatsD::Instrument::Expectation.measure(metric_name, value, **options)
88
- assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
89
- end
90
-
91
- # Asserts that a given gauge metric occurred inside the provided block.
92
- #
93
- # @param metric_name (see #assert_statsd_increment)
94
- # @param options (see #assert_statsd_increment)
95
- # @yield (see #assert_statsd_increment)
96
- # @return [void]
97
- # @raise (see #assert_statsd_increment)
98
- def assert_statsd_gauge(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
99
- expectation = StatsD::Instrument::Expectation.gauge(metric_name, value, **options)
100
- assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
101
- end
3
+ module StatsD
4
+ module Instrument
5
+ # This module defines several assertion methods that can be used to verify that
6
+ # your application is emitting the right StatsD metrics.
7
+ #
8
+ # Every metric type has its own assertion method, like {#assert_statsd_increment}
9
+ # to assert `StatsD.increment` calls. You can also assert other properties of the
10
+ # metric that was emitted, like the sample rate or presence of tags.
11
+ # To check for the absence of metrics, use {#assert_no_statsd_calls}.
12
+ #
13
+ # @example Check for metric properties:
14
+ # assert_statsd_measure('foo', sample_rate: 0.1, tags: ["bar"]) do
15
+ # StatsD.measure('foo', sample_rate: 0.5, tags: ['bar','baz']) do
16
+ # some_code_to_measure
17
+ # end
18
+ # end
19
+ #
20
+ # @example Check for multiple occurrences:
21
+ # assert_statsd_increment('foo', times: 2) do
22
+ # StatsD.increment('foo')
23
+ # StatsD.increment('foo')
24
+ # end
25
+ #
26
+ # @example Absence of metrics
27
+ # assert_no_statsd_calls do
28
+ # foo
29
+ # end
30
+ #
31
+ # @example Handling exceptions
32
+ # assert_statsd_increment('foo.error') do
33
+ # # If we expect exceptions to occur, we have to handle them inside
34
+ # # the block we pass to assert_statsd_increment.
35
+ # assert_raises(RuntimeError) do
36
+ # begin
37
+ # attempt_foo
38
+ # rescue
39
+ # StatsD.increment('foo.error')
40
+ # raise 'foo failed'
41
+ # end
42
+ # end
43
+ # end
44
+ module Assertions
45
+ include StatsD::Instrument::Helpers
46
+
47
+ # Asserts no metric occurred during the execution of the provided block.
48
+ #
49
+ # @param [Array<String>] metric_names (default: []) The metric names that are not
50
+ # allowed to happen inside the block. If this is set to `[]`, the assertion
51
+ # will fail if any metric occurs.
52
+ # @yield A block in which the specified metric should not occur. This block
53
+ # should not raise any exceptions.
54
+ # @return [void]
55
+ # @raise [Minitest::Assertion] If an exception occurs, or if any metric (with the
56
+ # provided names, or any), occurred during the execution of the provided block.
57
+ def assert_no_statsd_calls(*metric_names, datagrams: nil, client: nil, &block)
58
+ if datagrams.nil?
59
+ raise LocalJumpError, "assert_no_statsd_calls requires a block" unless block_given?
60
+ datagrams = capture_statsd_datagrams_with_exception_handling(client: client, &block)
61
+ end
102
62
 
103
- # Asserts that a given histogram metric occurred inside the provided block.
104
- #
105
- # @param metric_name (see #assert_statsd_increment)
106
- # @param options (see #assert_statsd_increment)
107
- # @yield (see #assert_statsd_increment)
108
- # @return [void]
109
- # @raise (see #assert_statsd_increment)
110
- def assert_statsd_histogram(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
111
- expectation = StatsD::Instrument::Expectation.histogram(metric_name, value, **options)
112
- assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
113
- end
63
+ datagrams.select! { |metric| metric_names.include?(metric.name) } unless metric_names.empty?
64
+ assert(datagrams.empty?, "No StatsD calls for metric #{datagrams.map(&:name).join(', ')} expected.")
65
+ end
114
66
 
115
- # Asserts that a given distribution metric occurred inside the provided block.
116
- #
117
- # @param metric_name (see #assert_statsd_increment)
118
- # @param options (see #assert_statsd_increment)
119
- # @yield (see #assert_statsd_increment)
120
- # @return [void]
121
- # @raise (see #assert_statsd_increment)
122
- def assert_statsd_distribution(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
123
- expectation = StatsD::Instrument::Expectation.distribution(metric_name, value, **options)
124
- assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
125
- end
67
+ # Asserts that a given counter metric occurred inside the provided block.
68
+ #
69
+ # @param [String] metric_name The name of the metric that should occur.
70
+ # @param [Hash] options (see StatsD::Instrument::MetricExpectation.new)
71
+ # @yield A block in which the specified metric should occur. This block
72
+ # should not raise any exceptions.
73
+ # @return [void]
74
+ # @raise [Minitest::Assertion] If an exception occurs, or if the metric did
75
+ # not occur as specified during the execution the block.
76
+ def assert_statsd_increment(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
77
+ expectation = StatsD::Instrument::Expectation.increment(metric_name, value, **options)
78
+ assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
79
+ end
126
80
 
127
- # Asserts that a given set metric occurred inside the provided block.
128
- #
129
- # @param metric_name (see #assert_statsd_increment)
130
- # @param options (see #assert_statsd_increment)
131
- # @yield (see #assert_statsd_increment)
132
- # @return [void]
133
- # @raise (see #assert_statsd_increment)
134
- def assert_statsd_set(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
135
- expectation = StatsD::Instrument::Expectation.set(metric_name, value, **options)
136
- assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
137
- end
81
+ # Asserts that a given timing metric occurred inside the provided block.
82
+ #
83
+ # @param metric_name (see #assert_statsd_increment)
84
+ # @param options (see #assert_statsd_increment)
85
+ # @yield (see #assert_statsd_increment)
86
+ # @return [void]
87
+ # @raise (see #assert_statsd_increment)
88
+ def assert_statsd_measure(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
89
+ expectation = StatsD::Instrument::Expectation.measure(metric_name, value, **options)
90
+ assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
91
+ end
138
92
 
139
- # Asserts that the set of provided metric expectations came true.
140
- #
141
- # Generally, it's recommended to use more specific assertion methods, like
142
- # {#assert_statsd_increment} and others.
143
- #
144
- # @private
145
- # @param [Array<StatsD::Instrument::Expectation>] expectations The set of
146
- # expectations to verify.
147
- # @yield (see #assert_statsd_increment)
148
- # @return [void]
149
- # @raise (see #assert_statsd_increment)
150
- def assert_statsd_expectations(expectations, datagrams: nil, client: nil, &block)
151
- if datagrams.nil?
152
- raise LocalJumpError, "assert_statsd_expectations requires a block" unless block_given?
153
- datagrams = capture_statsd_datagrams_with_exception_handling(client: client, &block)
154
- end
93
+ # Asserts that a given gauge metric occurred inside the provided block.
94
+ #
95
+ # @param metric_name (see #assert_statsd_increment)
96
+ # @param options (see #assert_statsd_increment)
97
+ # @yield (see #assert_statsd_increment)
98
+ # @return [void]
99
+ # @raise (see #assert_statsd_increment)
100
+ def assert_statsd_gauge(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
101
+ expectation = StatsD::Instrument::Expectation.gauge(metric_name, value, **options)
102
+ assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
103
+ end
155
104
 
156
- expectations = Array(expectations)
157
- matched_expectations = []
158
- expectations.each do |expectation|
159
- expectation_times = expectation.times
160
- expectation_times_remaining = expectation.times
161
- filtered_datagrams = datagrams.select { |m| m.type == expectation.type && m.name == expectation.name }
105
+ # Asserts that a given histogram metric occurred inside the provided block.
106
+ #
107
+ # @param metric_name (see #assert_statsd_increment)
108
+ # @param options (see #assert_statsd_increment)
109
+ # @yield (see #assert_statsd_increment)
110
+ # @return [void]
111
+ # @raise (see #assert_statsd_increment)
112
+ def assert_statsd_histogram(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
113
+ expectation = StatsD::Instrument::Expectation.histogram(metric_name, value, **options)
114
+ assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
115
+ end
162
116
 
163
- if filtered_datagrams.empty?
164
- flunk("No StatsD calls for metric #{expectation.name} of type #{expectation.type} were made.")
117
+ # Asserts that a given distribution metric occurred inside the provided block.
118
+ #
119
+ # @param metric_name (see #assert_statsd_increment)
120
+ # @param options (see #assert_statsd_increment)
121
+ # @yield (see #assert_statsd_increment)
122
+ # @return [void]
123
+ # @raise (see #assert_statsd_increment)
124
+ def assert_statsd_distribution(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
125
+ expectation = StatsD::Instrument::Expectation.distribution(metric_name, value, **options)
126
+ assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
165
127
  end
166
128
 
167
- filtered_datagrams.each do |datagram|
168
- next unless expectation.matches(datagram)
129
+ # Asserts that a given set metric occurred inside the provided block.
130
+ #
131
+ # @param metric_name (see #assert_statsd_increment)
132
+ # @param options (see #assert_statsd_increment)
133
+ # @yield (see #assert_statsd_increment)
134
+ # @return [void]
135
+ # @raise (see #assert_statsd_increment)
136
+ def assert_statsd_set(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
137
+ expectation = StatsD::Instrument::Expectation.set(metric_name, value, **options)
138
+ assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
139
+ end
169
140
 
170
- if expectation_times_remaining == 0
171
- flunk("Unexpected StatsD call; number of times this metric " \
172
- "was expected exceeded: #{expectation.inspect}")
141
+ # Asserts that the set of provided metric expectations came true.
142
+ #
143
+ # Generally, it's recommended to use more specific assertion methods, like
144
+ # {#assert_statsd_increment} and others.
145
+ #
146
+ # @private
147
+ # @param [Array<StatsD::Instrument::Expectation>] expectations The set of
148
+ # expectations to verify.
149
+ # @yield (see #assert_statsd_increment)
150
+ # @return [void]
151
+ # @raise (see #assert_statsd_increment)
152
+ def assert_statsd_expectations(expectations, datagrams: nil, client: nil, &block)
153
+ if datagrams.nil?
154
+ raise LocalJumpError, "assert_statsd_expectations requires a block" unless block_given?
155
+ datagrams = capture_statsd_datagrams_with_exception_handling(client: client, &block)
173
156
  end
174
157
 
175
- expectation_times_remaining -= 1
176
- datagrams.delete(datagram)
177
- if expectation_times_remaining == 0
178
- matched_expectations << expectation
158
+ expectations = Array(expectations)
159
+ matched_expectations = []
160
+ expectations.each do |expectation|
161
+ expectation_times = expectation.times
162
+ expectation_times_remaining = expectation.times
163
+ filtered_datagrams = datagrams.select { |m| m.type == expectation.type && m.name == expectation.name }
164
+
165
+ if filtered_datagrams.empty?
166
+ flunk("No StatsD calls for metric #{expectation.name} of type #{expectation.type} were made.")
167
+ end
168
+
169
+ filtered_datagrams.each do |datagram|
170
+ next unless expectation.matches(datagram)
171
+
172
+ if expectation_times_remaining == 0
173
+ flunk("Unexpected StatsD call; number of times this metric " \
174
+ "was expected exceeded: #{expectation.inspect}")
175
+ end
176
+
177
+ expectation_times_remaining -= 1
178
+ datagrams.delete(datagram)
179
+ if expectation_times_remaining == 0
180
+ matched_expectations << expectation
181
+ end
182
+ end
183
+
184
+ next if expectation_times_remaining == 0
185
+
186
+ msg = +"Metric expected #{expectation_times} times but seen " \
187
+ "#{expectation_times - expectation_times_remaining} " \
188
+ "times: #{expectation.inspect}."
189
+ msg << "\nCaptured metrics with the same key: #{filtered_datagrams}" if filtered_datagrams.any?
190
+ flunk(msg)
179
191
  end
180
- end
192
+ expectations -= matched_expectations
181
193
 
182
- next if expectation_times_remaining == 0
183
-
184
- msg = +"Metric expected #{expectation_times} times but seen " \
185
- "#{expectation_times - expectation_times_remaining} " \
186
- "times: #{expectation.inspect}."
187
- msg << "\nCaptured metrics with the same key: #{filtered_datagrams}" if filtered_datagrams.any?
188
- flunk(msg)
189
- end
190
- expectations -= matched_expectations
191
-
192
- unless expectations.empty?
193
- flunk("Unexpected StatsD calls; the following metric expectations " \
194
- "were not satisfied: #{expectations.inspect}")
195
- end
194
+ unless expectations.empty?
195
+ flunk("Unexpected StatsD calls; the following metric expectations " \
196
+ "were not satisfied: #{expectations.inspect}")
197
+ end
196
198
 
197
- pass
198
- end
199
+ pass
200
+ end
199
201
 
200
- # For backwards compatibility
201
- alias_method :assert_statsd_calls, :assert_statsd_expectations
202
- alias_method :assert_statsd_expectation, :assert_statsd_expectations
202
+ # For backwards compatibility
203
+ alias_method :assert_statsd_calls, :assert_statsd_expectations
204
+ alias_method :assert_statsd_expectation, :assert_statsd_expectations
203
205
 
204
- private
206
+ private
205
207
 
206
- def capture_statsd_datagrams_with_exception_handling(client:, &block)
207
- capture_statsd_datagrams(client: client, &block)
208
- rescue => exception
209
- flunk(<<~MESSAGE)
210
- An exception occurred in the block provided to the StatsD assertion.
208
+ def capture_statsd_datagrams_with_exception_handling(client:, &block)
209
+ capture_statsd_datagrams(client: client, &block)
210
+ rescue => exception
211
+ flunk(<<~MESSAGE)
212
+ An exception occurred in the block provided to the StatsD assertion.
211
213
 
212
- #{exception.class.name}: #{exception.message}
213
- \t#{exception.backtrace.join("\n\t")}
214
+ #{exception.class.name}: #{exception.message}
215
+ \t#{(exception.backtrace || []).join("\n\t")}
214
216
 
215
- If this exception is expected, make sure to handle it using `assert_raises`
216
- inside the block provided to the StatsD assertion.
217
- MESSAGE
217
+ If this exception is expected, make sure to handle it using `assert_raises`
218
+ inside the block provided to the StatsD assertion.
219
+ MESSAGE
220
+ end
221
+ end
218
222
  end
219
223
  end