statsd-instrument 2.1.1 → 2.1.2
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/.travis.yml +3 -5
- data/CHANGELOG.md +44 -3
- data/README.md +6 -0
- data/lib/statsd/instrument.rb +43 -40
- data/lib/statsd/instrument/environment.rb +1 -1
- data/lib/statsd/instrument/matchers.rb +22 -2
- data/lib/statsd/instrument/version.rb +1 -1
- data/test/environment_test.rb +11 -0
- data/test/matchers_test.rb +49 -1
- data/test/statsd_instrumentation_test.rb +16 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 185cb2c919df0365e7808fdc36f0eece2ffac2aa
|
4
|
+
data.tar.gz: 6f64c341a7d7cd1ef9ae7400b99cca75641388f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95db3eab39e1cecaa4938bab5df81de7f9c4c0b36d8f0640a0a95b6b0d036f65edb91f180a41d3ee64446841430f29d58d42ad9c58bfec1967114236f0d18030
|
7
|
+
data.tar.gz: 7df38af3a361e4ba803994f09292c66c2c78ecaf681e02aa937982cdd7ab9005c0872a1442a96d0d2fdcafc43e36535363a38cb3dadc94cc3bf49761bc49b6cd
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -5,9 +5,51 @@ please at an entry to the "unreleased changes" section below.
|
|
5
5
|
|
6
6
|
### Unreleased changes
|
7
7
|
|
8
|
+
### Version 2.1.2
|
9
|
+
|
10
|
+
- Use `prepend` instead of rewriting classes for metaprogramming methods.
|
11
|
+
- RSpec: make matchers more flexible.
|
12
|
+
- Bugfix: Only ask Rails for the environment when it's actually loaded.
|
13
|
+
|
14
|
+
### Version 2.1.1
|
15
|
+
|
16
|
+
- Add `assert_statsd_calls` to from validating cases where one has multiple metrics with the same name and type being recorded, but with different options.
|
17
|
+
|
18
|
+
### Version 2.1.0
|
19
|
+
|
20
|
+
- Fix rspec-rails compatibility
|
21
|
+
- Add `value` keyword argument to all metric types.
|
22
|
+
|
23
|
+
### Version 2.0.12
|
24
|
+
|
25
|
+
- Make StatsD client thread-safe
|
26
|
+
- Assertions: Ensure sample rates have proper values.
|
27
|
+
- Assertions: Make tag assertions work more intuitively
|
28
|
+
- RSpec: Add backwards compatibility for RSpec 2
|
29
|
+
|
30
|
+
### Version 2.0.11
|
31
|
+
|
32
|
+
- Don't change method visibility when adding instrumentation to methods using metaprogramming
|
33
|
+
- RSpec: add support for Compound expectations
|
34
|
+
|
35
|
+
### Version 2.0.10
|
36
|
+
|
37
|
+
- Assertions: allow ignoring certain tags when asserting for other tags to be present.
|
38
|
+
|
39
|
+
### Version 2.0.9
|
40
|
+
|
41
|
+
- Better error message for `assert_no_statsd_calls`
|
42
|
+
|
43
|
+
### Version 2.0.8
|
44
|
+
|
45
|
+
- More tag handling performance improvements.
|
46
|
+
- RSpec matchers documentation improvements
|
47
|
+
|
48
|
+
### Version 2.0.7
|
49
|
+
|
50
|
+
- Tag handling performance improvements.
|
51
|
+
- Test against Ruby 2.2.
|
8
52
|
- Drop support for Ruby 1.9.3.
|
9
|
-
- Add support for Ruby 2.2.
|
10
|
-
- Make library compatible with RSpec 2.
|
11
53
|
|
12
54
|
### Version 2.0.6
|
13
55
|
|
@@ -15,7 +57,6 @@ please at an entry to the "unreleased changes" section below.
|
|
15
57
|
- Default behavior: in a **staging** environment, the defaults are now the same as in a **production environment**.
|
16
58
|
- Documentation overhaul
|
17
59
|
|
18
|
-
|
19
60
|
### Version 2.0.5
|
20
61
|
|
21
62
|
- Allow for nested assertions using the `assert_statsd_*` assertion methods.
|
data/README.md
CHANGED
@@ -280,6 +280,12 @@ RSpec.describe 'Matchers' do
|
|
280
280
|
}.to trigger_statsd_increment('counter', times: 2)
|
281
281
|
end
|
282
282
|
|
283
|
+
it 'will pass if it matches argument' do
|
284
|
+
expect {
|
285
|
+
StatsD.measure('counter', 0.3001)
|
286
|
+
}.to trigger_statsd_measure('counter', value: be_between(0.29, 0.31))
|
287
|
+
end
|
288
|
+
|
283
289
|
it 'will pass if there is no matching StatsD call on negative expectation' do
|
284
290
|
expect { StatsD.increment('other_counter') }.not_to trigger_statsd_increment('counter')
|
285
291
|
end
|
data/lib/statsd/instrument.rb
CHANGED
@@ -40,6 +40,16 @@ module StatsD
|
|
40
40
|
# StatsD metrics. E.g., yopu can create counters on how often a method is called, how often it is
|
41
41
|
# successful, the duration of the methods call, etc.
|
42
42
|
module Instrument
|
43
|
+
# @private
|
44
|
+
def statsd_instrumentations
|
45
|
+
if defined?(@statsd_instrumentations)
|
46
|
+
@statsd_instrumentations
|
47
|
+
elsif respond_to?(:superclass) && superclass.respond_to?(:statsd_instrumentations)
|
48
|
+
superclass.statsd_instrumentations
|
49
|
+
else
|
50
|
+
@statsd_instrumentations = {}
|
51
|
+
end
|
52
|
+
end
|
43
53
|
|
44
54
|
# @private
|
45
55
|
def self.generate_metric_name(metric_name, callee, *args)
|
@@ -70,9 +80,9 @@ module StatsD
|
|
70
80
|
# @param metric_options (see StatsD#measure)
|
71
81
|
# @return [void]
|
72
82
|
def statsd_measure(method, name, *metric_options)
|
73
|
-
add_to_method(method, name, :measure) do
|
74
|
-
define_method(
|
75
|
-
StatsD.measure(StatsD::Instrument.generate_metric_name(
|
83
|
+
add_to_method(method, name, :measure) do
|
84
|
+
define_method(method) do |*args, &block|
|
85
|
+
StatsD.measure(StatsD::Instrument.generate_metric_name(name, self, *args), nil, *metric_options) { super(*args, &block) }
|
76
86
|
end
|
77
87
|
end
|
78
88
|
end
|
@@ -93,10 +103,10 @@ module StatsD
|
|
93
103
|
# @return [void]
|
94
104
|
# @see #statsd_count_if
|
95
105
|
def statsd_count_success(method, name, *metric_options)
|
96
|
-
add_to_method(method, name, :count_success) do
|
97
|
-
define_method(
|
106
|
+
add_to_method(method, name, :count_success) do
|
107
|
+
define_method(method) do |*args, &block|
|
98
108
|
begin
|
99
|
-
truthiness = result =
|
109
|
+
truthiness = result = super(*args, &block)
|
100
110
|
rescue
|
101
111
|
truthiness = false
|
102
112
|
raise
|
@@ -105,7 +115,7 @@ module StatsD
|
|
105
115
|
result
|
106
116
|
ensure
|
107
117
|
suffix = truthiness == false ? 'failure' : 'success'
|
108
|
-
StatsD.increment("#{StatsD::Instrument.generate_metric_name(
|
118
|
+
StatsD.increment("#{StatsD::Instrument.generate_metric_name(name, self, *args)}.#{suffix}", 1, *metric_options)
|
109
119
|
end
|
110
120
|
end
|
111
121
|
end
|
@@ -125,10 +135,10 @@ module StatsD
|
|
125
135
|
# @return [void]
|
126
136
|
# @see #statsd_count_success
|
127
137
|
def statsd_count_if(method, name, *metric_options)
|
128
|
-
add_to_method(method, name, :count_if) do
|
129
|
-
define_method(
|
138
|
+
add_to_method(method, name, :count_if) do
|
139
|
+
define_method(method) do |*args, &block|
|
130
140
|
begin
|
131
|
-
truthiness = result =
|
141
|
+
truthiness = result = super(*args, &block)
|
132
142
|
rescue
|
133
143
|
truthiness = false
|
134
144
|
raise
|
@@ -136,7 +146,7 @@ module StatsD
|
|
136
146
|
truthiness = (yield(result) rescue false) if block_given?
|
137
147
|
result
|
138
148
|
ensure
|
139
|
-
StatsD.increment(StatsD::Instrument.generate_metric_name(
|
149
|
+
StatsD.increment(StatsD::Instrument.generate_metric_name(name, self, *args), *metric_options) if truthiness
|
140
150
|
end
|
141
151
|
end
|
142
152
|
end
|
@@ -152,10 +162,10 @@ module StatsD
|
|
152
162
|
# @param metric_options (see #statsd_measure)
|
153
163
|
# @return [void]
|
154
164
|
def statsd_count(method, name, *metric_options)
|
155
|
-
add_to_method(method, name, :count) do
|
156
|
-
define_method(
|
157
|
-
StatsD.increment(StatsD::Instrument.generate_metric_name(
|
158
|
-
|
165
|
+
add_to_method(method, name, :count) do
|
166
|
+
define_method(method) do |*args, &block|
|
167
|
+
StatsD.increment(StatsD::Instrument.generate_metric_name(name, self, *args), 1, *metric_options)
|
168
|
+
super(*args, &block)
|
159
169
|
end
|
160
170
|
end
|
161
171
|
end
|
@@ -198,40 +208,33 @@ module StatsD
|
|
198
208
|
|
199
209
|
private
|
200
210
|
|
201
|
-
def
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
211
|
+
def statsd_instrumentation_for(method, name, action)
|
212
|
+
unless statsd_instrumentations.key?([method, name, action])
|
213
|
+
mod = Module.new do
|
214
|
+
define_singleton_method(:inspect) do
|
215
|
+
"StatsD_Instrument_#{method}_for_#{action}_with_#{name}"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
@statsd_instrumentations = statsd_instrumentations.merge([method, name, action] => mod)
|
219
|
+
end
|
220
|
+
@statsd_instrumentations[[method, name, action]]
|
221
|
+
end
|
206
222
|
|
207
|
-
|
208
|
-
|
223
|
+
def add_to_method(method, name, action, &block)
|
224
|
+
instrumentation_module = statsd_instrumentation_for(method, name, action)
|
209
225
|
|
210
|
-
raise ArgumentError, "already instrumented #{method} for #{self.name}" if method_defined?
|
226
|
+
raise ArgumentError, "already instrumented #{method} for #{self.name}" if instrumentation_module.method_defined?(method)
|
211
227
|
raise ArgumentError, "could not find method #{method} for #{self.name}" unless method_defined?(method) || private_method_defined?(method)
|
212
228
|
|
213
229
|
method_scope = method_visibility(method)
|
214
230
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
private(method_name_without_statsd)
|
220
|
-
send(method_scope, method)
|
221
|
-
private(method_name_with_statsd)
|
231
|
+
instrumentation_module.module_eval(&block)
|
232
|
+
instrumentation_module.send(method_scope, method)
|
233
|
+
prepend(instrumentation_module) unless self < instrumentation_module
|
222
234
|
end
|
223
235
|
|
224
236
|
def remove_from_method(method, name, action)
|
225
|
-
|
226
|
-
method_name_with_statsd = :"#{method}_for_#{action}_on_#{self.name}_with_#{name}"
|
227
|
-
|
228
|
-
method_scope = method_visibility(method)
|
229
|
-
|
230
|
-
send(:remove_method, method_name_with_statsd)
|
231
|
-
alias_method method, method_name_without_statsd
|
232
|
-
send(:remove_method, method_name_without_statsd)
|
233
|
-
|
234
|
-
send(method_scope, method)
|
237
|
+
statsd_instrumentation_for(method, name, action).send(:remove_method, method)
|
235
238
|
end
|
236
239
|
|
237
240
|
def method_visibility(method)
|
@@ -28,7 +28,7 @@ module StatsD::Instrument::Environment
|
|
28
28
|
#
|
29
29
|
# @return [String] The detected environment.
|
30
30
|
def environment
|
31
|
-
if defined?(Rails)
|
31
|
+
if defined?(Rails) && Rails.respond_to?(:env)
|
32
32
|
Rails.env.to_s
|
33
33
|
else
|
34
34
|
ENV['RAILS_ENV'] || ENV['RACK_ENV'] || ENV['ENV'] || 'development'
|
@@ -55,13 +55,33 @@ module StatsD::Instrument::Matchers
|
|
55
55
|
[:sample_rate, :value, :tags].each do |expectation|
|
56
56
|
next unless options[expectation]
|
57
57
|
|
58
|
-
|
59
|
-
|
58
|
+
num_matches = metrics.count do |m|
|
59
|
+
matcher = RSpec::Matchers::BuiltIn::Match.new(options[expectation])
|
60
|
+
matcher.matches?(m.public_send(expectation))
|
61
|
+
end
|
62
|
+
|
63
|
+
found = options[:times] ? num_matches == options[:times] : num_matches > 0
|
64
|
+
|
65
|
+
if !found
|
66
|
+
message = metric_information(metric_name, options, metrics, expectation)
|
67
|
+
raise RSpec::Expectations::ExpectationNotMetError, message
|
60
68
|
end
|
61
69
|
end
|
62
70
|
|
63
71
|
true
|
64
72
|
end
|
73
|
+
|
74
|
+
def metric_information(metric_name, options, metrics, expectation)
|
75
|
+
message = "expected StatsD #{expectation.inspect} for metric '#{metric_name}' to be called"
|
76
|
+
|
77
|
+
message += "\n "
|
78
|
+
message += options[:times] ? "exactly #{options[:times]} times" : "at least once"
|
79
|
+
message += " with: #{options[expectation]}"
|
80
|
+
|
81
|
+
message += "\n captured metric values: #{metrics.map(&expectation).join(', ')}"
|
82
|
+
|
83
|
+
message
|
84
|
+
end
|
65
85
|
end
|
66
86
|
|
67
87
|
CUSTOM_MATCHERS.each do |method_name, metric_type|
|
data/test/environment_test.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
+
module Rails; end
|
4
|
+
|
3
5
|
class EnvironmentTest < Minitest::Test
|
4
6
|
|
5
7
|
def setup
|
@@ -32,4 +34,13 @@ class EnvironmentTest < Minitest::Test
|
|
32
34
|
assert_equal 1234, backend.port
|
33
35
|
assert_equal :datadog, backend.implementation
|
34
36
|
end
|
37
|
+
|
38
|
+
def test_uses_env_when_rails_does_not_respond_to_env
|
39
|
+
assert_equal ENV['ENV'], StatsD::Instrument::Environment.environment
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_uses_rails_env_when_rails_is_available
|
43
|
+
Rails.stubs(:env).returns('production')
|
44
|
+
assert_equal 'production', StatsD::Instrument::Environment.environment
|
45
|
+
end
|
35
46
|
end
|
data/test/matchers_test.rb
CHANGED
@@ -10,7 +10,7 @@ class MatchersTest < Minitest::Test
|
|
10
10
|
refute StatsD::Instrument::Matchers::Increment.new(:c, 'counter', {}).matches? lambda { StatsD.increment('not_counter') }
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
13
|
+
def test_statsd_increment_compound_matched
|
14
14
|
matcher_1 = StatsD::Instrument::Matchers::Increment.new(:c, 'counter', tags: ['a'])
|
15
15
|
matcher_2 = StatsD::Instrument::Matchers::Increment.new(:c, 'counter', tags: ['b'])
|
16
16
|
|
@@ -20,6 +20,16 @@ class MatchersTest < Minitest::Test
|
|
20
20
|
}
|
21
21
|
end
|
22
22
|
|
23
|
+
def test_statsd_increment_compound_not_matched
|
24
|
+
matcher_1 = StatsD::Instrument::Matchers::Increment.new(:c, 'counter', tags: ['a'])
|
25
|
+
matcher_2 = StatsD::Instrument::Matchers::Increment.new(:c, 'counter', tags: ['b'])
|
26
|
+
|
27
|
+
refute RSpec::Matchers::BuiltIn::Compound::And.new(matcher_1, matcher_2).matches? lambda {
|
28
|
+
StatsD.increment('counter', tags: ['a'])
|
29
|
+
StatsD.increment('counter', tags: ['a'])
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
23
33
|
def test_statsd_increment_with_times_matched
|
24
34
|
assert StatsD::Instrument::Matchers::Increment.new(:c, 'counter', times: 1).matches? lambda { StatsD.increment('counter') }
|
25
35
|
end
|
@@ -40,6 +50,20 @@ class MatchersTest < Minitest::Test
|
|
40
50
|
assert StatsD::Instrument::Matchers::Increment.new(:c, 'counter', value: 1).matches? lambda { StatsD.increment('counter') }
|
41
51
|
end
|
42
52
|
|
53
|
+
def test_statsd_increment_with_value_matched_when_multiple_metrics
|
54
|
+
assert StatsD::Instrument::Matchers::Increment.new(:c, 'counter', value: 1).matches? lambda {
|
55
|
+
StatsD.increment('counter', value: 2)
|
56
|
+
StatsD.increment('counter', value: 1)
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_statsd_increment_with_value_not_matched_when_multiple_metrics
|
61
|
+
refute StatsD::Instrument::Matchers::Increment.new(:c, 'counter', value: 1).matches? lambda {
|
62
|
+
StatsD.increment('counter', value: 2)
|
63
|
+
StatsD.increment('counter', value: 3)
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
43
67
|
def test_statsd_increment_with_value_not_matched
|
44
68
|
refute StatsD::Instrument::Matchers::Increment.new(:c, 'counter', value: 3).matches? lambda { StatsD.increment('counter') }
|
45
69
|
end
|
@@ -51,4 +75,28 @@ class MatchersTest < Minitest::Test
|
|
51
75
|
def test_statsd_increment_with_tags_not_matched
|
52
76
|
refute StatsD::Instrument::Matchers::Increment.new(:c, 'counter', tags: ['a', 'b']).matches? lambda { StatsD.increment('counter', tags: ['c']) }
|
53
77
|
end
|
78
|
+
|
79
|
+
def test_statsd_increment_with_times_and_value_matched
|
80
|
+
assert StatsD::Instrument::Matchers::Increment.new(:c, 'counter', times: 2, value: 1).matches? lambda {
|
81
|
+
StatsD.increment('counter', value: 1)
|
82
|
+
StatsD.increment('counter', value: 1)
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_statsd_increment_with_times_and_value_not_matched
|
87
|
+
refute StatsD::Instrument::Matchers::Increment.new(:c, 'counter', times: 2, value: 1).matches? lambda {
|
88
|
+
StatsD.increment('counter', value: 1)
|
89
|
+
StatsD.increment('counter', value: 2)
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_statsd_increment_with_sample_rate_and_argument_matcher_matched
|
94
|
+
between_matcher = RSpec::Matchers::BuiltIn::BeBetween.new(0.4, 0.6).inclusive
|
95
|
+
assert StatsD::Instrument::Matchers::Increment.new(:c, 'counter', sample_rate: between_matcher).matches? lambda { StatsD.increment('counter', sample_rate: 0.5) }
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_statsd_increment_with_sample_rate_and_argument_matcher_not_matched
|
99
|
+
between_matcher = RSpec::Matchers::BuiltIn::BeBetween.new(0.4, 0.6).inclusive
|
100
|
+
refute StatsD::Instrument::Matchers::Increment.new(:c, 'counter', sample_rate: between_matcher).matches? lambda { StatsD.increment('counter', sample_rate: 0.7) }
|
101
|
+
end
|
54
102
|
end
|
@@ -288,6 +288,22 @@ class StatsDInstrumentationTest < Minitest::Test
|
|
288
288
|
InstrumentedClass.statsd_count :private_and_instrumented, 'InstrumentedClass.private_and_instrumented'
|
289
289
|
end
|
290
290
|
|
291
|
+
def test_statsd_works_with_prepended_modules
|
292
|
+
mod = Module.new do
|
293
|
+
define_method(:foo) { super() }
|
294
|
+
end
|
295
|
+
klass = Class.new do
|
296
|
+
prepend mod
|
297
|
+
extend StatsD::Instrument
|
298
|
+
define_method(:foo) {}
|
299
|
+
statsd_count :foo, "foo"
|
300
|
+
end
|
301
|
+
|
302
|
+
assert_statsd_increment("foo") do
|
303
|
+
klass.new.foo
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
291
307
|
private
|
292
308
|
|
293
309
|
def assert_scope(klass, method, expected_scope)
|
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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jesse Storimer
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-06
|
13
|
+
date: 2016-12-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|