qubole-statsd-instrument 2.1.4
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 +7 -0
- data/.gitignore +7 -0
- data/.travis.yml +12 -0
- data/CHANGELOG.md +89 -0
- data/CONTRIBUTING.md +34 -0
- data/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.md +319 -0
- data/Rakefile +10 -0
- data/lib/statsd/instrument/assertions.rb +88 -0
- data/lib/statsd/instrument/backend.rb +17 -0
- data/lib/statsd/instrument/backends/capture_backend.rb +29 -0
- data/lib/statsd/instrument/backends/logger_backend.rb +20 -0
- data/lib/statsd/instrument/backends/null_backend.rb +7 -0
- data/lib/statsd/instrument/backends/udp_backend.rb +106 -0
- data/lib/statsd/instrument/environment.rb +54 -0
- data/lib/statsd/instrument/helpers.rb +14 -0
- data/lib/statsd/instrument/matchers.rb +96 -0
- data/lib/statsd/instrument/metric.rb +117 -0
- data/lib/statsd/instrument/metric_expectation.rb +67 -0
- data/lib/statsd/instrument/railtie.rb +14 -0
- data/lib/statsd/instrument/version.rb +5 -0
- data/lib/statsd/instrument.rb +407 -0
- data/lib/statsd-instrument.rb +1 -0
- data/shipit.rubygems.yml +1 -0
- data/statsd-instrument.gemspec +27 -0
- data/test/assertions_test.rb +329 -0
- data/test/benchmark/tags.rb +34 -0
- data/test/capture_backend_test.rb +24 -0
- data/test/environment_test.rb +46 -0
- data/test/helpers_test.rb +24 -0
- data/test/integration_test.rb +20 -0
- data/test/logger_backend_test.rb +20 -0
- data/test/matchers_test.rb +102 -0
- data/test/metric_test.rb +45 -0
- data/test/statsd_instrumentation_test.rb +328 -0
- data/test/statsd_test.rb +136 -0
- data/test/test_helper.rb +10 -0
- data/test/udp_backend_test.rb +167 -0
- metadata +182 -0
@@ -0,0 +1,328 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module ActiveMerchant; end
|
4
|
+
class ActiveMerchant::Base
|
5
|
+
def ssl_post(arg)
|
6
|
+
if arg
|
7
|
+
'OK'
|
8
|
+
else
|
9
|
+
raise 'Not OK'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def post_with_block(&block)
|
14
|
+
yield if block_given?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ActiveMerchant::Gateway < ActiveMerchant::Base
|
19
|
+
def purchase(arg)
|
20
|
+
ssl_post(arg)
|
21
|
+
true
|
22
|
+
rescue
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.sync
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.singleton_class
|
31
|
+
class << self; self; end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class ActiveMerchant::UniqueGateway < ActiveMerchant::Base
|
36
|
+
def ssl_post(arg)
|
37
|
+
{:success => arg}
|
38
|
+
end
|
39
|
+
|
40
|
+
def purchase(arg)
|
41
|
+
ssl_post(arg)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class GatewaySubClass < ActiveMerchant::Gateway
|
46
|
+
end
|
47
|
+
|
48
|
+
class InstrumentedClass
|
49
|
+
extend StatsD::Instrument
|
50
|
+
|
51
|
+
def public_and_instrumented
|
52
|
+
end
|
53
|
+
statsd_count :public_and_instrumented, 'InstrumentedClass.public_and_instrumented'
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
def protected_and_instrumented
|
58
|
+
end
|
59
|
+
statsd_count :protected_and_instrumented, 'InstrumentedClass.protected_and_instrumented'
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def private_and_instrumented
|
64
|
+
end
|
65
|
+
statsd_count :private_and_instrumented, 'InstrumentedClass.private_and_instrumented'
|
66
|
+
end
|
67
|
+
|
68
|
+
ActiveMerchant::Base.extend StatsD::Instrument
|
69
|
+
|
70
|
+
class StatsDInstrumentationTest < Minitest::Test
|
71
|
+
include StatsD::Instrument::Assertions
|
72
|
+
|
73
|
+
def test_statsd_count_if
|
74
|
+
ActiveMerchant::Gateway.statsd_count_if :ssl_post, 'ActiveMerchant.Gateway.if'
|
75
|
+
|
76
|
+
assert_statsd_increment('ActiveMerchant.Gateway.if') do
|
77
|
+
ActiveMerchant::Gateway.new.purchase(true)
|
78
|
+
ActiveMerchant::Gateway.new.purchase(false)
|
79
|
+
end
|
80
|
+
ensure
|
81
|
+
ActiveMerchant::Gateway.statsd_remove_count_if :ssl_post, 'ActiveMerchant.Gateway.if'
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_statsd_count_if_with_method_receiving_block
|
85
|
+
ActiveMerchant::Base.statsd_count_if :post_with_block, 'ActiveMerchant.Base.post_with_block' do |result|
|
86
|
+
result == 'true'
|
87
|
+
end
|
88
|
+
|
89
|
+
assert_statsd_increment('ActiveMerchant.Base.post_with_block') do
|
90
|
+
assert_equal 'true', ActiveMerchant::Base.new.post_with_block { 'true' }
|
91
|
+
assert_equal 'false', ActiveMerchant::Base.new.post_with_block { 'false' }
|
92
|
+
end
|
93
|
+
ensure
|
94
|
+
ActiveMerchant::Base.statsd_remove_count_if :post_with_block, 'ActiveMerchant.Base.post_with_block'
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_statsd_count_if_with_block
|
98
|
+
ActiveMerchant::UniqueGateway.statsd_count_if :ssl_post, 'ActiveMerchant.Gateway.block' do |result|
|
99
|
+
result[:success]
|
100
|
+
end
|
101
|
+
|
102
|
+
assert_statsd_increment('ActiveMerchant.Gateway.block', times: 1) do
|
103
|
+
ActiveMerchant::UniqueGateway.new.purchase(true)
|
104
|
+
ActiveMerchant::UniqueGateway.new.purchase(false)
|
105
|
+
end
|
106
|
+
ensure
|
107
|
+
ActiveMerchant::UniqueGateway.statsd_remove_count_if :ssl_post, 'ActiveMerchant.Gateway.block'
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_statsd_count_success
|
111
|
+
ActiveMerchant::Gateway.statsd_count_success :ssl_post, 'ActiveMerchant.Gateway', 0.5
|
112
|
+
|
113
|
+
assert_statsd_increment('ActiveMerchant.Gateway.success', sample_rate: 0.5, times: 1) do
|
114
|
+
ActiveMerchant::Gateway.new.purchase(true)
|
115
|
+
ActiveMerchant::Gateway.new.purchase(false)
|
116
|
+
end
|
117
|
+
|
118
|
+
assert_statsd_increment('ActiveMerchant.Gateway.failure', sample_rate: 0.5, times: 1) do
|
119
|
+
ActiveMerchant::Gateway.new.purchase(false)
|
120
|
+
ActiveMerchant::Gateway.new.purchase(true)
|
121
|
+
end
|
122
|
+
ensure
|
123
|
+
ActiveMerchant::Gateway.statsd_remove_count_success :ssl_post, 'ActiveMerchant.Gateway'
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_statsd_count_success_with_method_receiving_block
|
127
|
+
ActiveMerchant::Base.statsd_count_success :post_with_block, 'ActiveMerchant.Base.post_with_block' do |result|
|
128
|
+
result == 'successful'
|
129
|
+
end
|
130
|
+
|
131
|
+
assert_statsd_increment('ActiveMerchant.Base.post_with_block.success', times: 1) do
|
132
|
+
assert_equal 'successful', ActiveMerchant::Base.new.post_with_block { 'successful' }
|
133
|
+
assert_equal 'not so successful', ActiveMerchant::Base.new.post_with_block { 'not so successful' }
|
134
|
+
end
|
135
|
+
|
136
|
+
assert_statsd_increment('ActiveMerchant.Base.post_with_block.failure', times: 1) do
|
137
|
+
assert_equal 'successful', ActiveMerchant::Base.new.post_with_block { 'successful' }
|
138
|
+
assert_equal 'not so successful', ActiveMerchant::Base.new.post_with_block { 'not so successful' }
|
139
|
+
end
|
140
|
+
ensure
|
141
|
+
ActiveMerchant::Base.statsd_remove_count_success :post_with_block, 'ActiveMerchant.Base.post_with_block'
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_statsd_count_success_with_block
|
145
|
+
ActiveMerchant::UniqueGateway.statsd_count_success :ssl_post, 'ActiveMerchant.Gateway' do |result|
|
146
|
+
result[:success]
|
147
|
+
end
|
148
|
+
|
149
|
+
assert_statsd_increment('ActiveMerchant.Gateway.success') do
|
150
|
+
ActiveMerchant::UniqueGateway.new.purchase(true)
|
151
|
+
end
|
152
|
+
|
153
|
+
assert_statsd_increment('ActiveMerchant.Gateway.failure') do
|
154
|
+
ActiveMerchant::UniqueGateway.new.purchase(false)
|
155
|
+
end
|
156
|
+
ensure
|
157
|
+
ActiveMerchant::UniqueGateway.statsd_remove_count_success :ssl_post, 'ActiveMerchant.Gateway'
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_statsd_count
|
161
|
+
ActiveMerchant::Gateway.statsd_count :ssl_post, 'ActiveMerchant.Gateway.ssl_post'
|
162
|
+
|
163
|
+
assert_statsd_increment('ActiveMerchant.Gateway.ssl_post') do
|
164
|
+
ActiveMerchant::Gateway.new.purchase(true)
|
165
|
+
end
|
166
|
+
ensure
|
167
|
+
ActiveMerchant::Gateway.statsd_remove_count :ssl_post, 'ActiveMerchant.Gateway.ssl_post'
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_statsd_count_with_name_as_lambda
|
171
|
+
metric_namer = lambda { |object, args| object.class.to_s.downcase + ".insert." + args.first.to_s }
|
172
|
+
ActiveMerchant::Gateway.statsd_count(:ssl_post, metric_namer)
|
173
|
+
|
174
|
+
assert_statsd_increment('gatewaysubclass.insert.true') do
|
175
|
+
GatewaySubClass.new.purchase(true)
|
176
|
+
end
|
177
|
+
ensure
|
178
|
+
ActiveMerchant::Gateway.statsd_remove_count(:ssl_post, metric_namer)
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_statsd_count_with_method_receiving_block
|
182
|
+
ActiveMerchant::Base.statsd_count :post_with_block, 'ActiveMerchant.Base.post_with_block'
|
183
|
+
|
184
|
+
assert_statsd_increment('ActiveMerchant.Base.post_with_block') do
|
185
|
+
assert_equal 'block called', ActiveMerchant::Base.new.post_with_block { 'block called' }
|
186
|
+
end
|
187
|
+
ensure
|
188
|
+
ActiveMerchant::Base.statsd_remove_count :post_with_block, 'ActiveMerchant.Base.post_with_block'
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_statsd_measure
|
192
|
+
ActiveMerchant::UniqueGateway.statsd_measure :ssl_post, 'ActiveMerchant.Gateway.ssl_post', sample_rate: 0.3
|
193
|
+
|
194
|
+
assert_statsd_measure('ActiveMerchant.Gateway.ssl_post', sample_rate: 0.3) do
|
195
|
+
ActiveMerchant::UniqueGateway.new.purchase(true)
|
196
|
+
end
|
197
|
+
ensure
|
198
|
+
ActiveMerchant::UniqueGateway.statsd_remove_measure :ssl_post, 'ActiveMerchant.Gateway.ssl_post'
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_statsd_measure_uses_normalized_metric_name
|
202
|
+
ActiveMerchant::UniqueGateway.statsd_measure :ssl_post, 'ActiveMerchant::Gateway.ssl_post'
|
203
|
+
|
204
|
+
assert_statsd_measure('ActiveMerchant.Gateway.ssl_post') do
|
205
|
+
ActiveMerchant::UniqueGateway.new.purchase(true)
|
206
|
+
end
|
207
|
+
ensure
|
208
|
+
ActiveMerchant::UniqueGateway.statsd_remove_measure :ssl_post, 'ActiveMerchant::Gateway.ssl_post'
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_statsd_measure_yells_without_block
|
212
|
+
err = assert_raises(ArgumentError) do
|
213
|
+
assert_statsd_measure('ActiveMerchant.Gateway.ssl_post')
|
214
|
+
end
|
215
|
+
assert_equal "block must be given", err.to_s
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_statsd_measure_with_method_receiving_block
|
219
|
+
ActiveMerchant::Base.statsd_measure :post_with_block, 'ActiveMerchant.Base.post_with_block'
|
220
|
+
|
221
|
+
assert_statsd_measure('ActiveMerchant.Base.post_with_block') do
|
222
|
+
assert_equal 'block called', ActiveMerchant::Base.new.post_with_block { 'block called' }
|
223
|
+
end
|
224
|
+
ensure
|
225
|
+
ActiveMerchant::Base.statsd_remove_measure :post_with_block, 'ActiveMerchant.Base.post_with_block'
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_instrumenting_class_method
|
229
|
+
ActiveMerchant::Gateway.singleton_class.extend StatsD::Instrument
|
230
|
+
ActiveMerchant::Gateway.singleton_class.statsd_count :sync, 'ActiveMerchant.Gateway.sync'
|
231
|
+
|
232
|
+
assert_statsd_increment('ActiveMerchant.Gateway.sync') do
|
233
|
+
ActiveMerchant::Gateway.sync
|
234
|
+
end
|
235
|
+
ensure
|
236
|
+
ActiveMerchant::Gateway.singleton_class.statsd_remove_count :sync, 'ActiveMerchant.Gateway.sync'
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_statsd_count_with_tags
|
240
|
+
ActiveMerchant::Gateway.singleton_class.extend StatsD::Instrument
|
241
|
+
ActiveMerchant::Gateway.singleton_class.statsd_count :sync, 'ActiveMerchant.Gateway.sync', tags: { key: 'value' }
|
242
|
+
|
243
|
+
assert_statsd_increment('ActiveMerchant.Gateway.sync', tags: ['key:value']) do
|
244
|
+
ActiveMerchant::Gateway.sync
|
245
|
+
end
|
246
|
+
ensure
|
247
|
+
ActiveMerchant::Gateway.singleton_class.statsd_remove_count :sync, 'ActiveMerchant.Gateway.sync'
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_statsd_doesnt_change_method_scope_of_public_method
|
251
|
+
assert_scope InstrumentedClass, :public_and_instrumented, :public
|
252
|
+
|
253
|
+
assert_statsd_increment('InstrumentedClass.public_and_instrumented') do
|
254
|
+
InstrumentedClass.new.send(:public_and_instrumented)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_statsd_doesnt_change_method_scope_of_protected_method
|
259
|
+
assert_scope InstrumentedClass, :protected_and_instrumented, :protected
|
260
|
+
|
261
|
+
assert_statsd_increment('InstrumentedClass.protected_and_instrumented') do
|
262
|
+
InstrumentedClass.new.send(:protected_and_instrumented)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def test_statsd_doesnt_change_method_scope_of_private_method
|
267
|
+
assert_scope InstrumentedClass, :private_and_instrumented, :private
|
268
|
+
|
269
|
+
assert_statsd_increment('InstrumentedClass.private_and_instrumented') do
|
270
|
+
InstrumentedClass.new.send(:private_and_instrumented)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_statsd_doesnt_change_method_scope_on_removal_of_public_method
|
275
|
+
assert_scope InstrumentedClass, :public_and_instrumented, :public
|
276
|
+
InstrumentedClass.statsd_remove_count :public_and_instrumented, 'InstrumentedClass.public_and_instrumented'
|
277
|
+
assert_scope InstrumentedClass, :public_and_instrumented, :public
|
278
|
+
|
279
|
+
InstrumentedClass.statsd_count :public_and_instrumented, 'InstrumentedClass.public_and_instrumented'
|
280
|
+
end
|
281
|
+
|
282
|
+
def test_statsd_doesnt_change_method_scope_on_removal_of_protected_method
|
283
|
+
assert_scope InstrumentedClass, :protected_and_instrumented, :protected
|
284
|
+
InstrumentedClass.statsd_remove_count :protected_and_instrumented, 'InstrumentedClass.protected_and_instrumented'
|
285
|
+
assert_scope InstrumentedClass, :protected_and_instrumented, :protected
|
286
|
+
|
287
|
+
InstrumentedClass.statsd_count :protected_and_instrumented, 'InstrumentedClass.protected_and_instrumented'
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_statsd_doesnt_change_method_scope_on_removal_of_private_method
|
291
|
+
assert_scope InstrumentedClass, :private_and_instrumented, :private
|
292
|
+
InstrumentedClass.statsd_remove_count :private_and_instrumented, 'InstrumentedClass.private_and_instrumented'
|
293
|
+
assert_scope InstrumentedClass, :private_and_instrumented, :private
|
294
|
+
|
295
|
+
InstrumentedClass.statsd_count :private_and_instrumented, 'InstrumentedClass.private_and_instrumented'
|
296
|
+
end
|
297
|
+
|
298
|
+
def test_statsd_works_with_prepended_modules
|
299
|
+
mod = Module.new do
|
300
|
+
define_method(:foo) { super() }
|
301
|
+
end
|
302
|
+
klass = Class.new do
|
303
|
+
prepend mod
|
304
|
+
extend StatsD::Instrument
|
305
|
+
define_method(:foo) {}
|
306
|
+
statsd_count :foo, "foo"
|
307
|
+
end
|
308
|
+
|
309
|
+
assert_statsd_increment("foo") do
|
310
|
+
klass.new.foo
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
private
|
315
|
+
|
316
|
+
def assert_scope(klass, method, expected_scope)
|
317
|
+
method_scope = case
|
318
|
+
when klass.private_method_defined?(method)
|
319
|
+
:private
|
320
|
+
when klass.protected_method_defined?(method)
|
321
|
+
:protected
|
322
|
+
else
|
323
|
+
:public
|
324
|
+
end
|
325
|
+
|
326
|
+
assert_equal method_scope, expected_scope, "Expected method to be #{expected_scope}"
|
327
|
+
end
|
328
|
+
end
|
data/test/statsd_test.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class StatsDTest < Minitest::Test
|
4
|
+
include StatsD::Instrument::Assertions
|
5
|
+
|
6
|
+
def test_statsd_passed_collections_to_backend
|
7
|
+
StatsD.backend.expects(:collect_metric).with(instance_of(StatsD::Instrument::Metric))
|
8
|
+
StatsD.increment('test')
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_statsd_measure_with_explicit_value
|
12
|
+
result = nil
|
13
|
+
metric = capture_statsd_call { result = StatsD.measure('values.foobar', 42) }
|
14
|
+
assert_equal metric, result
|
15
|
+
assert_equal 'values.foobar', metric.name
|
16
|
+
assert_equal 42, metric.value
|
17
|
+
assert_equal :ms, metric.type
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_statsd_measure_with_explicit_value_as_keyword_argument
|
21
|
+
result = nil
|
22
|
+
metric = capture_statsd_call { result = StatsD.measure('values.foobar', value: 42) }
|
23
|
+
assert_equal metric, result
|
24
|
+
assert_equal 'values.foobar', metric.name
|
25
|
+
assert_equal 42, metric.value
|
26
|
+
assert_equal :ms, metric.type
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_statsd_measure_without_value_or_block
|
30
|
+
assert_raises(ArgumentError) { StatsD.measure('values.foobar', tags: 123) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_statsd_measure_with_explicit_value_and_sample_rate
|
34
|
+
metric = capture_statsd_call { StatsD.measure('values.foobar', 42, :sample_rate => 0.1) }
|
35
|
+
assert_equal 0.1, metric.sample_rate
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_statsd_measure_with_benchmarked_block_duration
|
39
|
+
StatsD::Instrument.stubs(:duration).returns(1.12)
|
40
|
+
metric = capture_statsd_call do
|
41
|
+
StatsD.measure('values.foobar') { 'foo' }
|
42
|
+
end
|
43
|
+
assert_equal 1120.0, metric.value
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_statsd_measure_returns_return_value_of_block
|
47
|
+
return_value = StatsD.measure('values.foobar') { 'sarah' }
|
48
|
+
assert_equal 'sarah', return_value
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_statsd_increment
|
52
|
+
result = nil
|
53
|
+
metric = capture_statsd_call { result = StatsD.increment('values.foobar', 3) }
|
54
|
+
assert_equal metric, result
|
55
|
+
assert_equal :c, metric.type
|
56
|
+
assert_equal 'values.foobar', metric.name
|
57
|
+
assert_equal 3, metric.value
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_statsd_increment_with_hash_argument
|
61
|
+
metric = capture_statsd_call { StatsD.increment('values.foobar', :tags => ['test']) }
|
62
|
+
assert_equal StatsD.default_sample_rate, metric.sample_rate
|
63
|
+
assert_equal ['test'], metric.tags
|
64
|
+
assert_equal 1, metric.value
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_statsd_increment_with_value_as_keyword_argument
|
68
|
+
metric = capture_statsd_call { StatsD.increment('values.foobar', :value => 2) }
|
69
|
+
assert_equal StatsD.default_sample_rate, metric.sample_rate
|
70
|
+
assert_equal 2, metric.value
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_statsd_increment_with_multiple_arguments
|
74
|
+
metric = capture_statsd_call { StatsD.increment('values.foobar', 12, nil, ['test']) }
|
75
|
+
assert_equal StatsD.default_sample_rate, metric.sample_rate
|
76
|
+
assert_equal ['test'], metric.tags
|
77
|
+
assert_equal 12, metric.value
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_statsd_gauge
|
81
|
+
result = nil
|
82
|
+
metric = capture_statsd_call { result = StatsD.gauge('values.foobar', 12) }
|
83
|
+
assert_equal metric, result
|
84
|
+
assert_equal :g, metric.type
|
85
|
+
assert_equal 'values.foobar', metric.name
|
86
|
+
assert_equal 12, metric.value
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_statsd_gauge_with_keyword_argument
|
90
|
+
result = nil
|
91
|
+
metric = capture_statsd_call { result = StatsD.gauge('values.foobar', value: 13) }
|
92
|
+
assert_equal metric, result
|
93
|
+
assert_equal :g, metric.type
|
94
|
+
assert_equal 'values.foobar', metric.name
|
95
|
+
assert_equal 13, metric.value
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_statsd_gauge_without_value
|
99
|
+
assert_raises(ArgumentError) { StatsD.gauge('values.foobar', tags: 123) }
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_statsd_set
|
103
|
+
result = nil
|
104
|
+
metric = capture_statsd_call { result = StatsD.set('values.foobar', 'unique_identifier') }
|
105
|
+
assert_equal metric, result
|
106
|
+
assert_equal :s, metric.type
|
107
|
+
assert_equal 'values.foobar', metric.name
|
108
|
+
assert_equal 'unique_identifier', metric.value
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_statsd_histogram
|
112
|
+
result = nil
|
113
|
+
metric = capture_statsd_call { result = StatsD.histogram('values.foobar', 42) }
|
114
|
+
assert_equal metric, result
|
115
|
+
assert_equal :h, metric.type
|
116
|
+
assert_equal 'values.foobar', metric.name
|
117
|
+
assert_equal 42, metric.value
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_statsd_key_value
|
121
|
+
result = nil
|
122
|
+
metric = capture_statsd_call { result = StatsD.key_value('values.foobar', 42) }
|
123
|
+
assert_equal metric, result
|
124
|
+
assert_equal :kv, metric.type
|
125
|
+
assert_equal 'values.foobar', metric.name
|
126
|
+
assert_equal 42, metric.value
|
127
|
+
end
|
128
|
+
|
129
|
+
protected
|
130
|
+
|
131
|
+
def capture_statsd_call(&block)
|
132
|
+
metrics = capture_statsd_calls(&block)
|
133
|
+
assert_equal 1, metrics.length
|
134
|
+
metrics.first
|
135
|
+
end
|
136
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class UDPBackendTest < Minitest::Test
|
4
|
+
def setup
|
5
|
+
StatsD.stubs(:backend).returns(@backend = StatsD::Instrument::Backends::UDPBackend.new)
|
6
|
+
@backend.stubs(:rand).returns(0.0)
|
7
|
+
|
8
|
+
UDPSocket.stubs(:new).returns(@socket = mock('socket'))
|
9
|
+
@socket.stubs(:connect)
|
10
|
+
@socket.stubs(:send).returns(1)
|
11
|
+
|
12
|
+
StatsD.stubs(:logger).returns(@logger = mock('logger'))
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_changing_host_or_port_should_create_new_socket
|
16
|
+
@socket.expects(:connect).with('localhost', 1234).once
|
17
|
+
@socket.expects(:connect).with('localhost', 2345).once
|
18
|
+
@socket.expects(:connect).with('127.0.0.1', 2345).once
|
19
|
+
|
20
|
+
@backend.server = "localhost:1234"
|
21
|
+
@backend.socket
|
22
|
+
|
23
|
+
@backend.port = 2345
|
24
|
+
@backend.socket
|
25
|
+
|
26
|
+
@backend.host = '127.0.0.1'
|
27
|
+
@backend.socket
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_collect_respects_sampling_rate
|
31
|
+
@socket.expects(:send).once.returns(1)
|
32
|
+
metric = StatsD::Instrument::Metric.new(type: :c, name: 'test', sample_rate: 0.5)
|
33
|
+
|
34
|
+
@backend.stubs(:rand).returns(0.4)
|
35
|
+
@backend.collect_metric(metric)
|
36
|
+
|
37
|
+
@backend.stubs(:rand).returns(0.6)
|
38
|
+
@backend.collect_metric(metric)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_support_counter_syntax
|
42
|
+
@backend.expects(:write_packet).with('counter:1|c').once
|
43
|
+
StatsD.increment('counter', sample_rate: 1.0)
|
44
|
+
|
45
|
+
@backend.expects(:write_packet).with('counter:1|c|@0.5').once
|
46
|
+
StatsD.increment('counter', sample_rate: 0.5)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_supports_gauge_syntax
|
50
|
+
@backend.expects(:write_packet).with('fooy:1.23|g')
|
51
|
+
StatsD.gauge('fooy', 1.23)
|
52
|
+
|
53
|
+
@backend.expects(:write_packet).with('fooy:42|g|@0.01')
|
54
|
+
StatsD.gauge('fooy', 42, sample_rate: 0.01)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_supports_set_syntax
|
58
|
+
@backend.expects(:write_packet).with('unique:10.0.0.10|s')
|
59
|
+
StatsD.set('unique', '10.0.0.10')
|
60
|
+
|
61
|
+
@backend.expects(:write_packet).with('unique:10.0.0.10|s|@0.01')
|
62
|
+
StatsD.set('unique', '10.0.0.10', sample_rate: 0.01)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_support_measure_syntax
|
66
|
+
@backend.expects(:write_packet).with('duration:1.23|ms')
|
67
|
+
StatsD.measure('duration', 1.23)
|
68
|
+
|
69
|
+
@backend.expects(:write_packet).with('duration:0.42|ms|@0.01')
|
70
|
+
StatsD.measure('duration', 0.42, sample_rate: 0.01)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_histogram_syntax_on_datadog
|
74
|
+
@backend.implementation = :datadog
|
75
|
+
@backend.expects(:write_packet).with('fooh:42.4|h')
|
76
|
+
StatsD.histogram('fooh', 42.4)
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_histogram_warns_if_not_using_datadog
|
80
|
+
@backend.implementation = :other
|
81
|
+
@backend.expects(:write_packet).never
|
82
|
+
@logger.expects(:warn)
|
83
|
+
StatsD.histogram('fooh', 42.4)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_supports_key_value_syntax_on_statsite
|
87
|
+
@backend.implementation = :statsite
|
88
|
+
@backend.expects(:write_packet).with("fooy:42|kv\n")
|
89
|
+
StatsD.key_value('fooy', 42)
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_supports_key_value_with_timestamp_on_statsite
|
93
|
+
@backend.implementation = :statsite
|
94
|
+
@backend.expects(:write_packet).with("fooy:42|kv|@123456\n")
|
95
|
+
StatsD.key_value('fooy', 42, 123456)
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_warn_when_using_key_value_and_not_on_statsite
|
99
|
+
@backend.implementation = :other
|
100
|
+
@backend.expects(:write_packet).never
|
101
|
+
@logger.expects(:warn)
|
102
|
+
StatsD.key_value('fookv', 3.33)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_support_tags_syntax_on_datadog
|
106
|
+
@backend.implementation = :datadog
|
107
|
+
@backend.expects(:write_packet).with("fooc:3|c|#topic:foo,bar")
|
108
|
+
StatsD.increment('fooc', 3, tags: ['topic:foo', 'bar'])
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_support_tags_syntax_on_collectd
|
112
|
+
@backend.implementation = :collectd
|
113
|
+
@backend.expects(:write_packet).with("[topic=foo,bar]fooc:3|g")
|
114
|
+
StatsD.gauge('fooc', 3, tags: ['topic:foo','bar'])
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_warn_when_using_tags_and_not_on_datadog
|
118
|
+
@backend.implementation = :other
|
119
|
+
@backend.expects(:write_packet).with("fooc:1|c")
|
120
|
+
@logger.expects(:warn)
|
121
|
+
StatsD.increment('fooc', tags: ['ignored'])
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_socket_error_should_not_raise_but_log
|
125
|
+
@socket.stubs(:connect).raises(SocketError)
|
126
|
+
@logger.expects(:error)
|
127
|
+
StatsD.increment('fail')
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_system_call_error_should_not_raise_but_log
|
131
|
+
@socket.stubs(:send).raises(Errno::ETIMEDOUT)
|
132
|
+
@logger.expects(:error)
|
133
|
+
StatsD.increment('fail')
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_io_error_should_not_raise_but_log
|
137
|
+
@socket.stubs(:send).raises(IOError)
|
138
|
+
@logger.expects(:error)
|
139
|
+
StatsD.increment('fail')
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_synchronize_in_exit_handler_handles_thread_error_and_exits_cleanly
|
143
|
+
pid = fork do
|
144
|
+
Signal.trap('TERM') do
|
145
|
+
$sent_packet = false
|
146
|
+
|
147
|
+
class << @backend.socket
|
148
|
+
def send(command, *args)
|
149
|
+
$sent_packet = true if command == 'exiting:1|c'
|
150
|
+
command.length
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
StatsD.increment('exiting')
|
155
|
+
Process.exit!($sent_packet)
|
156
|
+
end
|
157
|
+
|
158
|
+
sleep 100
|
159
|
+
end
|
160
|
+
|
161
|
+
Process.kill('TERM', pid)
|
162
|
+
Process.waitpid(pid)
|
163
|
+
|
164
|
+
assert $?.success?, 'socket did not write on exit'
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|