statsd-instrument 2.1.1 → 2.1.2

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: 46fc4b2306e65ec55ec96d05f26653460d43ece8
4
- data.tar.gz: c4657dafe04761702c5464de9b277f77e1106530
3
+ metadata.gz: 185cb2c919df0365e7808fdc36f0eece2ffac2aa
4
+ data.tar.gz: 6f64c341a7d7cd1ef9ae7400b99cca75641388f8
5
5
  SHA512:
6
- metadata.gz: 2e450334ecc746a8066b86975a208a5bf9d0bec99d6117080aa407106909cc3636321fd49e6663f847bce8d40da7a19e3bfd945087420c8ad04b70032f029c45
7
- data.tar.gz: a080a4c6497edd7881a9abd20f955e2796b08c9524c246cfbbd62cc6d7a66e8d03a4978c4c8dcd544110b5e7c07365dbae89b7f8748f5916eaf95d038a08c6da
6
+ metadata.gz: 95db3eab39e1cecaa4938bab5df81de7f9c4c0b36d8f0640a0a95b6b0d036f65edb91f180a41d3ee64446841430f29d58d42ad9c58bfec1967114236f0d18030
7
+ data.tar.gz: 7df38af3a361e4ba803994f09292c66c2c78ecaf681e02aa937982cdd7ab9005c0872a1442a96d0d2fdcafc43e36535363a38cb3dadc94cc3bf49761bc49b6cd
@@ -1,10 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.0
4
- - 2.1
5
- - 2.2
6
- - jruby-19mode
7
- - rbx-2
3
+ - 2.1.10
4
+ - 2.2.6
5
+ - 2.3.3
8
6
  - ruby-head
9
7
 
10
8
  matrix:
@@ -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
@@ -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 |old_method, new_method, metric_name, *args|
74
- define_method(new_method) do |*args, &block|
75
- StatsD.measure(StatsD::Instrument.generate_metric_name(metric_name, self, *args), nil, *metric_options) { send(old_method, *args, &block) }
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 |old_method, new_method, metric_name|
97
- define_method(new_method) do |*args, &block|
106
+ add_to_method(method, name, :count_success) do
107
+ define_method(method) do |*args, &block|
98
108
  begin
99
- truthiness = result = send(old_method, *args, &block)
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(metric_name, self, *args)}.#{suffix}", 1, *metric_options)
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 |old_method, new_method, metric_name|
129
- define_method(new_method) do |*args, &block|
138
+ add_to_method(method, name, :count_if) do
139
+ define_method(method) do |*args, &block|
130
140
  begin
131
- truthiness = result = send(old_method, *args, &block)
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(metric_name, self, *args), *metric_options) if truthiness
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 |old_method, new_method, metric_name|
156
- define_method(new_method) do |*args, &block|
157
- StatsD.increment(StatsD::Instrument.generate_metric_name(metric_name, self, *args), 1, *metric_options)
158
- send(old_method, *args, &block)
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 add_to_method(method, name, action, &block)
202
- metric_name = name
203
-
204
- method_name_without_statsd = :"#{method}_for_#{action}_on_#{self.name}_without_#{name}"
205
- # raw_ssl_request_for_measure_on_FedEx_without_ActiveMerchant.Shipping.#{self.class.name}.ssl_request
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
- method_name_with_statsd = :"#{method}_for_#{action}_on_#{self.name}_with_#{name}"
208
- # raw_ssl_request_for_measure_on_FedEx_with_ActiveMerchant.Shipping.#{self.class.name}.ssl_request
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? method_name_without_statsd
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
- alias_method method_name_without_statsd, method
216
- yield method_name_without_statsd, method_name_with_statsd, metric_name
217
- alias_method method, method_name_with_statsd
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
- method_name_without_statsd = :"#{method}_for_#{action}_on_#{self.name}_without_#{name}"
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
- if metrics.all? { |m| m.public_send(expectation) != options[expectation] }
59
- raise RSpec::Expectations::ExpectationNotMetError, "Unexpected StatsD #{expectation.to_s.gsub('_', ' ')} for metric #{metric_name}"
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|
@@ -1,5 +1,5 @@
1
1
  module StatsD
2
2
  module Instrument
3
- VERSION = "2.1.1"
3
+ VERSION = "2.1.2"
4
4
  end
5
5
  end
@@ -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
@@ -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 test_statsd_increment_compound
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.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-28 00:00:00.000000000 Z
13
+ date: 2016-12-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake