Module: StatsD::Instrument::Assertions

Includes:
Helpers
Defined in:
lib/statsd/instrument/assertions.rb

Overview

This module defines several assertion methods that can be used to verify that your application is emitting the right StatsD metrics.

Every metric type has its own assertion method, like #assert_statsd_increment to assert StatsD.increment calls. You can also assert other properties of the metric that was emitted, like the sample rate or presence of tags. To check for the absence of metrics, use #assert_no_statsd_calls.

Examples:

Check for metric properties:

assert_statsd_measure('foo', sample_rate: 0.1, tags: ["bar"]) do
  StatsD.measure('foo', sample_rate: 0.5, tags: ['bar','baz']) do
    some_code_to_measure
  end
end

Check for multiple occurrences:

assert_statsd_increment('foo', times: 2) do
  StatsD.increment('foo')
  StatsD.increment('foo')
end

Absence of metrics

assert_no_statsd_calls do
  foo
end

Handling exceptions

assert_statsd_increment('foo.error') do
  # If we expect exceptions to occur, we have to handle them inside
  # the block we pass to assert_statsd_increment.
  assert_raises(RuntimeError) do
    begin
      attempt_foo
    rescue
      StatsD.increment('foo.error')
      raise 'foo failed'
    end
  end
end

Instance Method Summary collapse

Methods included from Helpers

add_tag, #capture_statsd_datagrams, prefix_metric, prefixed_metric?

Instance Method Details

#assert_no_statsd_calls(*metric_names, datagrams: nil, client: nil, no_prefix: false) { ... } ⇒ void

This method returns an undefined value.

Asserts no metric occurred during the execution of the provided block.

Parameters:

  • metric_names (Array<String>)

    (default: []) The metric names that are not allowed to happen inside the block. If this is set to [], the assertion will fail if any metric occurs.

  • datagrams (Array<StatsD::Instrument::Datagram>) (defaults to: nil)

    (default: nil) The datagrams to be inspected for metric emission.

  • client (StatsD::Instrument::Client) (defaults to: nil)

    (default: nil) The client to be used for fetching datagrams (if not provided) and metric prefix. If not provided, the singleton client will attempt to be used.

  • no_prefix (Boolean) (defaults to: false)

    (default: false) A directive to indicate if the client's prefix should be prepended to the metric names.

Yields:

  • A block in which the specified metric should not occur. This block should not raise any exceptions.

Raises:

  • (Minitest::Assertion)

    If an exception occurs, or if any metric (with the provided names, or any), occurred during the execution of the provided block.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/statsd/instrument/assertions.rb', line 64

def assert_no_statsd_calls(*metric_names, datagrams: nil, client: nil, no_prefix: false, &block)
  client ||= StatsD.singleton_client

  if datagrams.nil?
    raise LocalJumpError, "assert_no_statsd_calls requires a block" unless block_given?

    datagrams = capture_statsd_datagrams_with_exception_handling(client: client, &block)
  end

  formatted_metrics = if no_prefix
    metric_names
  else
    metric_names.map do |metric|
      if StatsD::Instrument::Helpers.prefixed_metric?(metric, client: client)
        warn("`#{__method__}` will prefix metrics by default. `#{metric}` skipped due to existing prefix.")
        metric
      else
        StatsD::Instrument::Helpers.prefix_metric(metric, client: client)
      end
    end
  end

  datagrams.select! { |metric| formatted_metrics.include?(metric.name) } unless formatted_metrics.empty?
  assert(datagrams.empty?, "No StatsD calls for metric #{datagrams.map(&:name).join(", ")} expected.")
end

#assert_statsd_distribution(metric_name, value = nil, datagrams: nil, client: nil, **options) { ... } ⇒ void

This method returns an undefined value.

Asserts that a given distribution metric occurred inside the provided block.

Parameters:

  • metric_name (String)

    The name of the metric that should occur.

  • options (Hash)

    (see StatsD::Instrument::MetricExpectation.new)

Yields:

  • A block in which the specified metric should occur. This block should not raise any exceptions.

Raises:

  • (Minitest::Assertion)

    If an exception occurs, or if the metric did not occur as specified during the execution the block.



147
148
149
150
# File 'lib/statsd/instrument/assertions.rb', line 147

def assert_statsd_distribution(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
  expectation = StatsD::Instrument::Expectation.distribution(metric_name, value, client: client, **options)
  assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
end

#assert_statsd_expectations(expectations, datagrams: nil, client: nil) { ... } ⇒ void Also known as: assert_statsd_calls, assert_statsd_expectation

This method returns an undefined value.

Asserts that the set of provided metric expectations came true.

Generally, it's recommended to use more specific assertion methods, like #assert_statsd_increment and others.

Parameters:

Yields:

  • A block in which the specified metric should occur. This block should not raise any exceptions.

Raises:

  • (Minitest::Assertion)

    If an exception occurs, or if the metric did not occur as specified during the execution the block.



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/statsd/instrument/assertions.rb', line 175

def assert_statsd_expectations(expectations, datagrams: nil, client: nil, &block)
  if datagrams.nil?
    raise LocalJumpError, "assert_statsd_expectations requires a block" unless block_given?

    datagrams = capture_statsd_datagrams_with_exception_handling(client: client, &block)
  end

  expectations = Array(expectations)
  matched_expectations = []
  expectations.each do |expectation|
    expectation_times = expectation.times
    expectation_times_remaining = expectation.times
    filtered_datagrams = datagrams.select { |m| m.type == expectation.type && m.name == expectation.name }

    if filtered_datagrams.empty?
      next if expectation_times == 0

      flunk("No StatsD calls for metric #{expectation.name} of type #{expectation.type} were made.")
    end

    filtered_datagrams.each do |datagram|
      next unless expectation.matches(datagram)

      if expectation_times_remaining == 0
        flunk("Unexpected StatsD call; number of times this metric " \
          "was expected exceeded: #{expectation.inspect}")
      end

      expectation_times_remaining -= 1
      datagrams.delete(datagram)
      if expectation_times_remaining == 0
        matched_expectations << expectation
      end
    end

    next if expectation_times_remaining == 0

    msg = +"Metric expected #{expectation_times} times but seen " \
      "#{expectation_times - expectation_times_remaining} " \
      "times: #{expectation.inspect}."
    msg << "\nCaptured metrics with the same key: #{filtered_datagrams}" if filtered_datagrams.any?
    flunk(msg)
  end
  expectations -= matched_expectations

  if expectations.any? { |m| m.times != 0 }
    flunk("Unexpected StatsD calls; the following metric expectations " \
      "were not satisfied: #{expectations.inspect}")
  end

  pass
end

#assert_statsd_gauge(metric_name, value = nil, datagrams: nil, client: nil, **options) { ... } ⇒ void

This method returns an undefined value.

Asserts that a given gauge metric occurred inside the provided block.

Parameters:

  • metric_name (String)

    The name of the metric that should occur.

  • options (Hash)

    (see StatsD::Instrument::MetricExpectation.new)

Yields:

  • A block in which the specified metric should occur. This block should not raise any exceptions.

Raises:

  • (Minitest::Assertion)

    If an exception occurs, or if the metric did not occur as specified during the execution the block.



123
124
125
126
# File 'lib/statsd/instrument/assertions.rb', line 123

def assert_statsd_gauge(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
  expectation = StatsD::Instrument::Expectation.gauge(metric_name, value, client: client, **options)
  assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
end

#assert_statsd_histogram(metric_name, value = nil, datagrams: nil, client: nil, **options) { ... } ⇒ void

This method returns an undefined value.

Asserts that a given histogram metric occurred inside the provided block.

Parameters:

  • metric_name (String)

    The name of the metric that should occur.

  • options (Hash)

    (see StatsD::Instrument::MetricExpectation.new)

Yields:

  • A block in which the specified metric should occur. This block should not raise any exceptions.

Raises:

  • (Minitest::Assertion)

    If an exception occurs, or if the metric did not occur as specified during the execution the block.



135
136
137
138
# File 'lib/statsd/instrument/assertions.rb', line 135

def assert_statsd_histogram(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
  expectation = StatsD::Instrument::Expectation.histogram(metric_name, value, client: client, **options)
  assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
end

#assert_statsd_increment(metric_name, value = nil, datagrams: nil, client: nil, **options) { ... } ⇒ void

This method returns an undefined value.

Asserts that a given counter metric occurred inside the provided block.

Parameters:

  • metric_name (String)

    The name of the metric that should occur.

  • options (Hash)

    (see StatsD::Instrument::MetricExpectation.new)

Yields:

  • A block in which the specified metric should occur. This block should not raise any exceptions.

Raises:

  • (Minitest::Assertion)

    If an exception occurs, or if the metric did not occur as specified during the execution the block.



99
100
101
102
# File 'lib/statsd/instrument/assertions.rb', line 99

def assert_statsd_increment(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
  expectation = StatsD::Instrument::Expectation.increment(metric_name, value, client: client, **options)
  assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
end

#assert_statsd_measure(metric_name, value = nil, datagrams: nil, client: nil, **options) { ... } ⇒ void

This method returns an undefined value.

Asserts that a given timing metric occurred inside the provided block.

Parameters:

  • metric_name (String)

    The name of the metric that should occur.

  • options (Hash)

    (see StatsD::Instrument::MetricExpectation.new)

Yields:

  • A block in which the specified metric should occur. This block should not raise any exceptions.

Raises:

  • (Minitest::Assertion)

    If an exception occurs, or if the metric did not occur as specified during the execution the block.



111
112
113
114
# File 'lib/statsd/instrument/assertions.rb', line 111

def assert_statsd_measure(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
  expectation = StatsD::Instrument::Expectation.measure(metric_name, value, client: client, **options)
  assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
end

#assert_statsd_set(metric_name, value = nil, datagrams: nil, client: nil, **options) { ... } ⇒ void

This method returns an undefined value.

Asserts that a given set metric occurred inside the provided block.

Parameters:

  • metric_name (String)

    The name of the metric that should occur.

  • options (Hash)

    (see StatsD::Instrument::MetricExpectation.new)

Yields:

  • A block in which the specified metric should occur. This block should not raise any exceptions.

Raises:

  • (Minitest::Assertion)

    If an exception occurs, or if the metric did not occur as specified during the execution the block.



159
160
161
162
# File 'lib/statsd/instrument/assertions.rb', line 159

def assert_statsd_set(metric_name, value = nil, datagrams: nil, client: nil, **options, &block)
  expectation = StatsD::Instrument::Expectation.set(metric_name, value, client: client, **options)
  assert_statsd_expectation(expectation, datagrams: datagrams, client: client, &block)
end