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 +4 -4
- data/lib/statsd/instrument.rb +1 -0
- data/lib/statsd/instrument/assertions.rb +39 -29
- data/lib/statsd/instrument/metric_expectation.rb +67 -0
- data/lib/statsd/instrument/version.rb +1 -1
- data/test/assertions_test.rb +97 -1
- metadata +20 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46fc4b2306e65ec55ec96d05f26653460d43ece8
|
4
|
+
data.tar.gz: c4657dafe04761702c5464de9b277f77e1106530
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e450334ecc746a8066b86975a208a5bf9d0bec99d6117080aa407106909cc3636321fd49e6663f847bce8d40da7a19e3bfd945087420c8ad04b70032f029c45
|
7
|
+
data.tar.gz: a080a4c6497edd7881a9abd20f955e2796b08c9524c246cfbbd62cc6d7a66e8d03a4978c4c8dcd544110b5e7c07365dbae89b7f8748f5916eaf95d038a08c6da
|
data/lib/statsd/instrument.rb
CHANGED
@@ -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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
assert
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
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
|
data/test/assertions_test.rb
CHANGED
@@ -124,7 +124,7 @@ class AssertionsTest < Minitest::Test
|
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
|
-
|
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.
|
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-
|
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
|
-
-
|
108
|
-
-
|
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.
|
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
|