statsd-instrument 2.1.0 → 2.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 18047951724aa18b3d78beeb6f41dc4de83af59c
4
- data.tar.gz: aca4e756c32bfeb9564e485cd95406d11028cc05
3
+ metadata.gz: 46fc4b2306e65ec55ec96d05f26653460d43ece8
4
+ data.tar.gz: c4657dafe04761702c5464de9b277f77e1106530
5
5
  SHA512:
6
- metadata.gz: d14651044e4b148c3caefaac65f7d4c7b49471ddf769c8124d9e9a5f0034eb4069c1139ea0ccb772e0ad78c1378599b0b5fae56f64c85d289df69c780096578b
7
- data.tar.gz: e4187bb6b8d76a86e7fb0e46800fe5d2a7625234bb54cdb3630165590834fe5a27555367cb6148ae67a9993883bfa6be7decf6ad18abe50cf476d077cfb43ac3
6
+ metadata.gz: 2e450334ecc746a8066b86975a208a5bf9d0bec99d6117080aa407106909cc3636321fd49e6663f847bce8d40da7a19e3bfd945087420c8ad04b70032f029c45
7
+ data.tar.gz: a080a4c6497edd7881a9abd20f955e2796b08c9524c246cfbbd62cc6d7a66e8d03a4978c4c8dcd544110b5e7c07365dbae89b7f8748f5916eaf95d038a08c6da
@@ -399,5 +399,6 @@ require 'statsd/instrument/backend'
399
399
  require 'statsd/instrument/environment'
400
400
  require 'statsd/instrument/helpers'
401
401
  require 'statsd/instrument/assertions'
402
+ require 'statsd/instrument/metric_expectation'
402
403
  require 'statsd/instrument/matchers' if defined?(::RSpec)
403
404
  require 'statsd/instrument/railtie' if defined?(Rails)
@@ -31,41 +31,51 @@ module StatsD::Instrument::Assertions
31
31
  assert_statsd_call(:kv, metric_name, options, &block)
32
32
  end
33
33
 
34
- private
35
-
36
- def assert_statsd_call(metric_type, metric_name, options = {}, &block)
37
- options[:times] ||= 1
34
+ # @private
35
+ def assert_statsd_calls(expected_metrics, &block)
38
36
  metrics = capture_statsd_calls(&block)
39
- metrics = metrics.select { |m| m.type == metric_type && m.name == metric_name }
40
- assert metrics.length > 0, "No StatsD calls for metric #{metric_name} were made."
41
- assert options[:times] === metrics.length, "The amount of StatsD calls for metric #{metric_name} was unexpected. Expected #{options[:times].inspect}, found #{metrics.length}"
42
-
43
- metrics.each do |metric|
44
-
45
- assert within_numeric_range?(metric.sample_rate), "Unexpected sample rate type for metric #{metric_name}, must be numeric"
46
- assert_equal options[:sample_rate], metric.sample_rate, "Unexpected StatsD sample rate for metric #{metric_name}" if options[:sample_rate]
47
- assert_equal options[:value], metric.value, "Unexpected value submitted for StatsD metric #{metric_name}" if options[:value]
48
-
49
- if options[:tags]
50
-
51
- expected_tags = Set.new(StatsD::Instrument::Metric.normalize_tags(options[:tags]))
52
- actual_tags = Set.new(metric.tags)
53
-
54
- if options[:ignore_tags]
55
- ignored_tags = Set.new(StatsD::Instrument::Metric.normalize_tags(options[:ignore_tags])) - expected_tags
56
- actual_tags -= ignored_tags
57
-
58
- if options[:ignore_tags].is_a?(Array)
59
- actual_tags.delete_if{ |key| options[:ignore_tags].include?(key.split(":").first) }
37
+ matched_expected_metrics = []
38
+
39
+ expected_metrics.each do |expected_metric|
40
+ expected_metric_times = expected_metric.times
41
+ expected_metric_times_remaining = expected_metric.times
42
+ filtered_metrics = metrics.select { |m| m.type == expected_metric.type && m.name == expected_metric.name }
43
+ assert filtered_metrics.length > 0,
44
+ "No StatsD calls for metric #{expected_metric.name} of type #{expected_metric.type} were made."
45
+
46
+ filtered_metrics.each do |metric|
47
+ assert within_numeric_range?(metric.sample_rate),
48
+ "Unexpected sample rate type for metric #{metric.name}, must be numeric"
49
+ if expected_metric.matches(metric)
50
+ assert expected_metric_times_remaining > 0,
51
+ "Unexpected StatsD call; number of times this metric was expected exceeded: #{expected_metric.inspect}"
52
+ expected_metric_times_remaining -= 1
53
+ metrics.delete(metric)
54
+ if expected_metric_times_remaining == 0
55
+ matched_expected_metrics << expected_metric
60
56
  end
61
57
  end
62
-
63
- assert_equal expected_tags, actual_tags,
64
- "Unexpected StatsD tags for metric #{metric_name}. Expected: #{expected_tags.inspect}, actual: #{actual_tags.inspect}"
65
58
  end
66
59
 
67
- metric
60
+ assert expected_metric_times_remaining == 0,
61
+ "Metric expected #{expected_metric_times} times but seen"\
62
+ " #{expected_metric_times-expected_metric_times_remaining}"\
63
+ " times: #{expected_metric.inspect}"
68
64
  end
65
+ expected_metrics -= matched_expected_metrics
66
+
67
+ assert expected_metrics.empty?,
68
+ "Unexpected StatsD calls; the following metric expectations were not satisfied: #{expected_metrics.inspect}"
69
+ end
70
+
71
+ private
72
+
73
+ def assert_statsd_call(metric_type, metric_name, options = {}, &block)
74
+ options[:name] = metric_name
75
+ options[:type] = metric_type
76
+ options[:times] ||= 1
77
+ expected_metric = StatsD::Instrument::MetricExpectation.new(options)
78
+ assert_statsd_calls([expected_metric], &block)
69
79
  end
70
80
 
71
81
  def within_numeric_range?(object)
@@ -0,0 +1,67 @@
1
+ # @private
2
+ class StatsD::Instrument::MetricExpectation
3
+
4
+ attr_accessor :times, :type, :name, :value, :sample_rate, :tags
5
+ attr_reader :ignore_tags
6
+
7
+ def initialize(options = {})
8
+ @type = options[:type] or raise ArgumentError, "Metric :type is required."
9
+ @name = options[:name] or raise ArgumentError, "Metric :name is required."
10
+ @name = StatsD.prefix ? "#{StatsD.prefix}.#{@name}" : @name unless options[:no_prefix]
11
+ @tags = StatsD::Instrument::Metric.normalize_tags(options[:tags])
12
+ @times = options[:times] or raise ArgumentError, "Metric :times is required."
13
+ @sample_rate = options[:sample_rate]
14
+ @value = options[:value]
15
+ @ignore_tags = StatsD::Instrument::Metric.normalize_tags(options[:ignore_tags])
16
+ end
17
+
18
+ def matches(actual_metric)
19
+ return false if sample_rate && sample_rate != actual_metric.sample_rate
20
+ return false if value && value != actual_metric.value
21
+
22
+ if tags
23
+
24
+ expected_tags = Set.new(tags)
25
+ actual_tags = Set.new(actual_metric.tags)
26
+
27
+ if ignore_tags
28
+ ignored_tags = Set.new(ignore_tags) - expected_tags
29
+ actual_tags -= ignored_tags
30
+
31
+ if ignore_tags.is_a?(Array)
32
+ actual_tags.delete_if{ |key| ignore_tags.include?(key.split(":").first) }
33
+ end
34
+ end
35
+
36
+ return expected_tags.subset?(actual_tags)
37
+ end
38
+ true
39
+ end
40
+
41
+ def default_value
42
+ case type
43
+ when :c; 1
44
+ end
45
+ end
46
+
47
+ TYPES = {
48
+ c: 'increment',
49
+ ms: 'measure',
50
+ g: 'gauge',
51
+ h: 'histogram',
52
+ kv: 'key/value',
53
+ s: 'set',
54
+ }
55
+
56
+ def to_s
57
+ str = "#{TYPES[type]} #{name}:#{value}"
58
+ str << " @#{sample_rate}" if sample_rate != 1.0
59
+ str << " " << tags.map { |t| "##{t}"}.join(' ') if tags
60
+ str << " times:#{times}" if times > 1
61
+ str
62
+ end
63
+
64
+ def inspect
65
+ "#<StatsD::Instrument::MetricExpectation #{self.to_s}>"
66
+ end
67
+ end
@@ -1,5 +1,5 @@
1
1
  module StatsD
2
2
  module Instrument
3
- VERSION = "2.1.0"
3
+ VERSION = "2.1.1"
4
4
  end
5
5
  end
@@ -124,7 +124,7 @@ class AssertionsTest < Minitest::Test
124
124
  end
125
125
  end
126
126
 
127
- assert_assertion_triggered do
127
+ assert_no_assertion_triggered do
128
128
  @test_case.assert_statsd_increment('counter', sample_rate: 0.5, tags: { a: 1 }, ignore_tags: { b: 2 }) do
129
129
  StatsD.increment('counter', sample_rate: 0.5, tags: { a: 1, b: 3 })
130
130
  end
@@ -149,6 +149,102 @@ class AssertionsTest < Minitest::Test
149
149
  end
150
150
  end
151
151
 
152
+ def test_tags_will_match_subsets
153
+ assert_no_assertion_triggered do
154
+ @test_case.assert_statsd_increment('counter', sample_rate: 0.5, tags: { a: 1 }) do
155
+ StatsD.increment('counter', sample_rate: 0.5, tags: { a: 1, b: 2 })
156
+ end
157
+ end
158
+
159
+ assert_assertion_triggered do
160
+ @test_case.assert_statsd_increment('counter', sample_rate: 0.5, tags: { a: 1, b: 3 }) do
161
+ StatsD.increment('counter', sample_rate: 0.5, tags: { a: 1, b: 2, c: 4 })
162
+ end
163
+ end
164
+ end
165
+
166
+ def test_multiple_metrics_are_not_order_dependent
167
+ assert_no_assertion_triggered do
168
+ foo_1_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:1'])
169
+ foo_2_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:2'])
170
+ @test_case.assert_statsd_calls([foo_1_metric, foo_2_metric]) do
171
+ StatsD.increment('counter', tags: { foo: 1 })
172
+ StatsD.increment('counter', tags: { foo: 2 })
173
+ end
174
+ end
175
+
176
+ assert_no_assertion_triggered do
177
+ foo_1_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:1'])
178
+ foo_2_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:2'])
179
+ @test_case.assert_statsd_calls([foo_2_metric, foo_1_metric]) do
180
+ StatsD.increment('counter', tags: { foo: 1 })
181
+ StatsD.increment('counter', tags: { foo: 2 })
182
+ end
183
+ end
184
+
185
+ assert_no_assertion_triggered do
186
+ foo_1_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 2, tags: ['foo:1'])
187
+ foo_2_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:2'])
188
+ @test_case.assert_statsd_calls([foo_1_metric, foo_2_metric]) do
189
+ StatsD.increment('counter', tags: { foo: 1 })
190
+ StatsD.increment('counter', tags: { foo: 1 })
191
+ StatsD.increment('counter', tags: { foo: 2 })
192
+ end
193
+ end
194
+
195
+ assert_no_assertion_triggered do
196
+ foo_1_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 2, tags: ['foo:1'])
197
+ foo_2_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:2'])
198
+ @test_case.assert_statsd_calls([foo_2_metric, foo_1_metric]) do
199
+ StatsD.increment('counter', tags: { foo: 1 })
200
+ StatsD.increment('counter', tags: { foo: 1 })
201
+ StatsD.increment('counter', tags: { foo: 2 })
202
+ end
203
+ end
204
+
205
+ assert_no_assertion_triggered do
206
+ foo_1_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 2, tags: ['foo:1'])
207
+ foo_2_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:2'])
208
+ @test_case.assert_statsd_calls([foo_2_metric, foo_1_metric]) do
209
+ StatsD.increment('counter', tags: { foo: 1 })
210
+ StatsD.increment('counter', tags: { foo: 2 })
211
+ StatsD.increment('counter', tags: { foo: 1 })
212
+ end
213
+ end
214
+ end
215
+
216
+ def test_assert_multiple_statsd_calls
217
+ assert_assertion_triggered do
218
+ foo_1_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 2, tags: ['foo:1'])
219
+ foo_2_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:2'])
220
+ @test_case.assert_statsd_calls([foo_1_metric, foo_2_metric]) do
221
+ StatsD.increment('counter', tags: { foo: 1 })
222
+ StatsD.increment('counter', tags: { foo: 2 })
223
+ end
224
+ end
225
+
226
+ assert_assertion_triggered do
227
+ foo_1_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 2, tags: ['foo:1'])
228
+ foo_2_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:2'])
229
+ @test_case.assert_statsd_calls([foo_1_metric, foo_2_metric]) do
230
+ StatsD.increment('counter', tags: { foo: 1 })
231
+ StatsD.increment('counter', tags: { foo: 1 })
232
+ StatsD.increment('counter', tags: { foo: 2 })
233
+ StatsD.increment('counter', tags: { foo: 2 })
234
+ end
235
+ end
236
+
237
+ assert_no_assertion_triggered do
238
+ foo_1_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 2, tags: ['foo:1'])
239
+ foo_2_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:2'])
240
+ @test_case.assert_statsd_calls([foo_1_metric, foo_2_metric]) do
241
+ StatsD.increment('counter', tags: { foo: 1 })
242
+ StatsD.increment('counter', tags: { foo: 1 })
243
+ StatsD.increment('counter', tags: { foo: 2 })
244
+ end
245
+ end
246
+ end
247
+
152
248
  def test_assert_statsd_call_with_tags
153
249
  assert_no_assertion_triggered do
154
250
  @test_case.assert_statsd_increment('counter', tags: ['a:b', 'c:d']) do
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.1.0
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesse Storimer
@@ -10,90 +10,90 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-06-16 00:00:00.000000000 Z
13
+ date: 2016-06-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - ">="
19
+ - - '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - ">="
26
+ - - '>='
27
27
  - !ruby/object:Gem::Version
28
28
  version: '0'
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: minitest
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
- - - ">="
33
+ - - '>='
34
34
  - !ruby/object:Gem::Version
35
35
  version: '0'
36
36
  type: :development
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
- - - ">="
40
+ - - '>='
41
41
  - !ruby/object:Gem::Version
42
42
  version: '0'
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: rspec
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - ">="
47
+ - - '>='
48
48
  - !ruby/object:Gem::Version
49
49
  version: '0'
50
50
  type: :development
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
- - - ">="
54
+ - - '>='
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0'
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: mocha
59
59
  requirement: !ruby/object:Gem::Requirement
60
60
  requirements:
61
- - - ">="
61
+ - - '>='
62
62
  - !ruby/object:Gem::Version
63
63
  version: '0'
64
64
  type: :development
65
65
  prerelease: false
66
66
  version_requirements: !ruby/object:Gem::Requirement
67
67
  requirements:
68
- - - ">="
68
+ - - '>='
69
69
  - !ruby/object:Gem::Version
70
70
  version: '0'
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: yard
73
73
  requirement: !ruby/object:Gem::Requirement
74
74
  requirements:
75
- - - ">="
75
+ - - '>='
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
78
  type: :development
79
79
  prerelease: false
80
80
  version_requirements: !ruby/object:Gem::Requirement
81
81
  requirements:
82
- - - ">="
82
+ - - '>='
83
83
  - !ruby/object:Gem::Version
84
84
  version: '0'
85
85
  - !ruby/object:Gem::Dependency
86
86
  name: benchmark-ips
87
87
  requirement: !ruby/object:Gem::Requirement
88
88
  requirements:
89
- - - ">="
89
+ - - '>='
90
90
  - !ruby/object:Gem::Version
91
91
  version: '0'
92
92
  type: :development
93
93
  prerelease: false
94
94
  version_requirements: !ruby/object:Gem::Requirement
95
95
  requirements:
96
- - - ">="
96
+ - - '>='
97
97
  - !ruby/object:Gem::Version
98
98
  version: '0'
99
99
  description: A StatsD client for Ruby apps. Provides metaprogramming methods to inject
@@ -104,8 +104,8 @@ executables: []
104
104
  extensions: []
105
105
  extra_rdoc_files: []
106
106
  files:
107
- - ".gitignore"
108
- - ".travis.yml"
107
+ - .gitignore
108
+ - .travis.yml
109
109
  - CHANGELOG.md
110
110
  - CONTRIBUTING.md
111
111
  - Gemfile
@@ -124,6 +124,7 @@ files:
124
124
  - lib/statsd/instrument/helpers.rb
125
125
  - lib/statsd/instrument/matchers.rb
126
126
  - lib/statsd/instrument/metric.rb
127
+ - lib/statsd/instrument/metric_expectation.rb
127
128
  - lib/statsd/instrument/railtie.rb
128
129
  - lib/statsd/instrument/version.rb
129
130
  - shipit.rubygems.yml
@@ -151,17 +152,17 @@ require_paths:
151
152
  - lib
152
153
  required_ruby_version: !ruby/object:Gem::Requirement
153
154
  requirements:
154
- - - ">="
155
+ - - '>='
155
156
  - !ruby/object:Gem::Version
156
157
  version: '0'
157
158
  required_rubygems_version: !ruby/object:Gem::Requirement
158
159
  requirements:
159
- - - ">="
160
+ - - '>='
160
161
  - !ruby/object:Gem::Version
161
162
  version: '0'
162
163
  requirements: []
163
164
  rubyforge_project:
164
- rubygems_version: 2.4.5.1
165
+ rubygems_version: 2.0.14.1
165
166
  signing_key:
166
167
  specification_version: 4
167
168
  summary: A StatsD client for Ruby apps