statsd-instrument 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
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