statsd-instrument 2.3.2 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +1 -0
- data/.github/workflows/ci.yml +31 -0
- data/.gitignore +1 -0
- data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +1027 -0
- data/.rubocop.yml +21 -0
- data/CHANGELOG.md +41 -0
- data/CONTRIBUTING.md +26 -6
- data/Gemfile +2 -0
- data/Rakefile +3 -1
- data/lib/statsd/instrument/assertions.rb +24 -18
- data/lib/statsd/instrument/backend.rb +3 -2
- data/lib/statsd/instrument/backends/capture_backend.rb +2 -1
- data/lib/statsd/instrument/backends/logger_backend.rb +3 -3
- data/lib/statsd/instrument/backends/null_backend.rb +2 -0
- data/lib/statsd/instrument/backends/udp_backend.rb +20 -17
- data/lib/statsd/instrument/environment.rb +2 -0
- data/lib/statsd/instrument/helpers.rb +6 -2
- data/lib/statsd/instrument/matchers.rb +14 -11
- data/lib/statsd/instrument/metric.rb +34 -21
- data/lib/statsd/instrument/metric_expectation.rb +32 -18
- data/lib/statsd/instrument/railtie.rb +2 -1
- data/lib/statsd/instrument/version.rb +3 -1
- data/lib/statsd/instrument.rb +85 -36
- data/lib/statsd-instrument.rb +2 -0
- data/statsd-instrument.gemspec +13 -10
- data/test/assertions_test.rb +15 -4
- data/test/benchmark/default_tags.rb +47 -0
- data/test/benchmark/metrics.rb +9 -8
- data/test/benchmark/tags.rb +5 -3
- data/test/capture_backend_test.rb +4 -2
- data/test/environment_test.rb +2 -1
- data/test/helpers_test.rb +2 -1
- data/test/integration_test.rb +27 -7
- data/test/logger_backend_test.rb +10 -8
- data/test/matchers_test.rb +34 -20
- data/test/metric_test.rb +15 -4
- data/test/statsd_instrumentation_test.rb +7 -7
- data/test/statsd_test.rb +100 -10
- data/test/test_helper.rb +2 -0
- data/test/udp_backend_test.rb +5 -28
- metadata +23 -5
- data/.travis.yml +0 -12
@@ -1,9 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This Railtie runs some initializers that will set the logger to <tt>Rails#logger</tt>,
|
2
4
|
# and will initialize the {StatsD#backend} based on the Rails environment.
|
3
5
|
#
|
4
6
|
# @see StatsD::Instrument::Environment
|
5
7
|
class StatsD::Instrument::Railtie < Rails::Railtie
|
6
|
-
|
7
8
|
initializer 'statsd-instrument.use_rails_logger' do
|
8
9
|
::StatsD.logger = Rails.logger
|
9
10
|
end
|
data/lib/statsd/instrument.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'socket'
|
2
4
|
require 'logger'
|
3
5
|
|
@@ -28,6 +30,10 @@ require 'logger'
|
|
28
30
|
# The logger to use in case of any errors. The logger is also used as default logger
|
29
31
|
# for the LoggerBackend (although this can be overwritten).
|
30
32
|
#
|
33
|
+
# @!attribute default_tags
|
34
|
+
# The tags to apply to all metrics.
|
35
|
+
# @return [Array<String>, Hash<String, String>, nil] The default tags, or <tt>nil</tt> when no default tags is used
|
36
|
+
#
|
31
37
|
# @see StatsD::Instrument::Backends::LoggerBackend
|
32
38
|
# @return [Logger]
|
33
39
|
#
|
@@ -58,20 +64,26 @@ module StatsD
|
|
58
64
|
|
59
65
|
if Process.respond_to?(:clock_gettime)
|
60
66
|
# @private
|
61
|
-
def self.
|
62
|
-
|
63
|
-
yield
|
64
|
-
Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
67
|
+
def self.current_timestamp
|
68
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
65
69
|
end
|
66
70
|
else
|
67
71
|
# @private
|
68
|
-
def self.
|
69
|
-
|
70
|
-
yield
|
71
|
-
Time.now - start
|
72
|
+
def self.current_timestamp
|
73
|
+
Time.now
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
77
|
+
# Even though this method is considered private, and is no longer used internally,
|
78
|
+
# applications in the wild rely on it. As a result, we cannot remove this method
|
79
|
+
# until the next major version.
|
80
|
+
# @private
|
81
|
+
def self.duration
|
82
|
+
start = current_timestamp
|
83
|
+
yield
|
84
|
+
current_timestamp - start
|
85
|
+
end
|
86
|
+
|
75
87
|
# Adds execution duration instrumentation to a method as a timing.
|
76
88
|
#
|
77
89
|
# @param method [Symbol] The name of the method to instrument.
|
@@ -82,7 +94,8 @@ module StatsD
|
|
82
94
|
def statsd_measure(method, name, *metric_options)
|
83
95
|
add_to_method(method, name, :measure) do
|
84
96
|
define_method(method) do |*args, &block|
|
85
|
-
StatsD
|
97
|
+
metric_name = StatsD::Instrument.generate_metric_name(name, self, *args)
|
98
|
+
StatsD.measure(metric_name, *metric_options) { super(*args, &block) }
|
86
99
|
end
|
87
100
|
end
|
88
101
|
end
|
@@ -98,7 +111,8 @@ module StatsD
|
|
98
111
|
def statsd_distribution(method, name, *metric_options)
|
99
112
|
add_to_method(method, name, :distribution) do
|
100
113
|
define_method(method) do |*args, &block|
|
101
|
-
StatsD
|
114
|
+
metric_name = StatsD::Instrument.generate_metric_name(name, self, *args)
|
115
|
+
StatsD.distribution(metric_name, *metric_options) { super(*args, &block) }
|
102
116
|
end
|
103
117
|
end
|
104
118
|
end
|
@@ -127,20 +141,27 @@ module StatsD
|
|
127
141
|
truthiness = false
|
128
142
|
raise
|
129
143
|
else
|
130
|
-
|
144
|
+
if block_given?
|
145
|
+
begin
|
146
|
+
truthiness = yield(result)
|
147
|
+
rescue
|
148
|
+
truthiness = false
|
149
|
+
end
|
150
|
+
end
|
131
151
|
result
|
132
152
|
ensure
|
133
153
|
suffix = truthiness == false ? 'failure' : 'success'
|
134
|
-
|
154
|
+
metric_name = "#{StatsD::Instrument.generate_metric_name(name, self, *args)}.#{suffix}"
|
155
|
+
StatsD.increment(metric_name, 1, *metric_options)
|
135
156
|
end
|
136
157
|
end
|
137
158
|
end
|
138
159
|
end
|
139
160
|
|
140
|
-
# Adds success
|
161
|
+
# Adds success counter instrumentation to a method.
|
141
162
|
#
|
142
163
|
# A method call will be considered successful if it does not raise an exception, and the result is true-y.
|
143
|
-
# Only for successful calls, the metric will be
|
164
|
+
# Only for successful calls, the metric will be incremented.
|
144
165
|
#
|
145
166
|
# @param method (see #statsd_measure)
|
146
167
|
# @param name (see #statsd_measure)
|
@@ -159,10 +180,19 @@ module StatsD
|
|
159
180
|
truthiness = false
|
160
181
|
raise
|
161
182
|
else
|
162
|
-
|
183
|
+
if block_given?
|
184
|
+
begin
|
185
|
+
truthiness = yield(result)
|
186
|
+
rescue
|
187
|
+
truthiness = false
|
188
|
+
end
|
189
|
+
end
|
163
190
|
result
|
164
191
|
ensure
|
165
|
-
|
192
|
+
if truthiness
|
193
|
+
metric_name = StatsD::Instrument.generate_metric_name(name, self, *args)
|
194
|
+
StatsD.increment(metric_name, *metric_options)
|
195
|
+
end
|
166
196
|
end
|
167
197
|
end
|
168
198
|
end
|
@@ -180,7 +210,8 @@ module StatsD
|
|
180
210
|
def statsd_count(method, name, *metric_options)
|
181
211
|
add_to_method(method, name, :count) do
|
182
212
|
define_method(method) do |*args, &block|
|
183
|
-
StatsD
|
213
|
+
metric_name = StatsD::Instrument.generate_metric_name(name, self, *args)
|
214
|
+
StatsD.increment(metric_name, 1, *metric_options)
|
184
215
|
super(*args, &block)
|
185
216
|
end
|
186
217
|
end
|
@@ -248,8 +279,13 @@ module StatsD
|
|
248
279
|
def add_to_method(method, name, action, &block)
|
249
280
|
instrumentation_module = statsd_instrumentation_for(method, name, action)
|
250
281
|
|
251
|
-
|
252
|
-
|
282
|
+
if instrumentation_module.method_defined?(method)
|
283
|
+
raise ArgumentError, "Already instrumented #{method} for #{self.name}"
|
284
|
+
end
|
285
|
+
|
286
|
+
unless method_defined?(method) || private_method_defined?(method)
|
287
|
+
raise ArgumentError, "could not find method #{method} for #{self.name}"
|
288
|
+
end
|
253
289
|
|
254
290
|
method_scope = method_visibility(method)
|
255
291
|
|
@@ -263,10 +299,9 @@ module StatsD
|
|
263
299
|
end
|
264
300
|
|
265
301
|
def method_visibility(method)
|
266
|
-
|
267
|
-
when private_method_defined?(method)
|
302
|
+
if private_method_defined?(method)
|
268
303
|
:private
|
269
|
-
|
304
|
+
elsif protected_method_defined?(method)
|
270
305
|
:protected
|
271
306
|
else
|
272
307
|
:public
|
@@ -276,6 +311,11 @@ module StatsD
|
|
276
311
|
|
277
312
|
attr_accessor :logger, :default_sample_rate, :prefix
|
278
313
|
attr_writer :backend
|
314
|
+
attr_reader :default_tags
|
315
|
+
|
316
|
+
def default_tags=(tags)
|
317
|
+
@default_tags = StatsD::Instrument::Metric.normalize_tags(tags)
|
318
|
+
end
|
279
319
|
|
280
320
|
def backend
|
281
321
|
@backend ||= StatsD::Instrument::Environment.default_backend
|
@@ -310,11 +350,16 @@ module StatsD
|
|
310
350
|
value, metric_options = parse_options(value, metric_options)
|
311
351
|
type = (!metric_options.empty? && metric_options.first[:as_dist] ? :d : :ms)
|
312
352
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
353
|
+
return collect_metric(type, key, value, metric_options) unless block_given?
|
354
|
+
|
355
|
+
start = StatsD::Instrument.current_timestamp
|
356
|
+
begin
|
357
|
+
block.call
|
358
|
+
ensure
|
359
|
+
# Ensure catches both a raised exception and a return in the invoked block
|
360
|
+
value = 1000 * (StatsD::Instrument.current_timestamp - start)
|
361
|
+
collect_metric(type, key, value, metric_options)
|
362
|
+
end
|
318
363
|
end
|
319
364
|
|
320
365
|
# Emits a counter metric.
|
@@ -371,13 +416,18 @@ module StatsD
|
|
371
416
|
# http_response = StatsD.distribution('HTTP.call.duration') do
|
372
417
|
# HTTP.get(url)
|
373
418
|
# end
|
374
|
-
def distribution(key, value=nil, *metric_options, &block)
|
419
|
+
def distribution(key, value = nil, *metric_options, &block)
|
375
420
|
value, metric_options = parse_options(value, metric_options)
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
421
|
+
|
422
|
+
return collect_metric(:d, key, value, metric_options) unless block_given?
|
423
|
+
|
424
|
+
start = StatsD::Instrument.current_timestamp
|
425
|
+
begin
|
426
|
+
block.call
|
427
|
+
ensure
|
428
|
+
value = 1000 * (StatsD::Instrument.current_timestamp - start)
|
429
|
+
collect_metric(:d, key, value, metric_options)
|
430
|
+
end
|
381
431
|
end
|
382
432
|
|
383
433
|
# Emits a key/value metric.
|
@@ -426,7 +476,7 @@ module StatsD
|
|
426
476
|
# @param args [Array] The list of non-required arguments.
|
427
477
|
# @return [Hash] The hash of optional arguments.
|
428
478
|
def hash_argument(args)
|
429
|
-
return {} if args.
|
479
|
+
return {} if args.empty?
|
430
480
|
return args.first if args.length == 1 && args.first.is_a?(Hash)
|
431
481
|
|
432
482
|
order = [:sample_rate, :tags]
|
@@ -434,8 +484,7 @@ module StatsD
|
|
434
484
|
args.each_with_index do |value, index|
|
435
485
|
hash[order[index]] = value
|
436
486
|
end
|
437
|
-
|
438
|
-
return hash
|
487
|
+
hash
|
439
488
|
end
|
440
489
|
|
441
490
|
def parse_options(value, metric_options)
|
data/lib/statsd-instrument.rb
CHANGED
data/statsd-instrument.gemspec
CHANGED
@@ -1,21 +1,23 @@
|
|
1
|
+
# frozen-string-literal: true
|
1
2
|
# encoding: utf-8
|
3
|
+
|
2
4
|
lib = File.expand_path('../lib', __FILE__)
|
3
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
6
|
require 'statsd/instrument/version'
|
5
7
|
|
6
8
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name
|
8
|
-
spec.version
|
9
|
-
spec.authors
|
10
|
-
spec.email
|
11
|
-
spec.homepage
|
12
|
-
spec.summary
|
9
|
+
spec.name = "statsd-instrument"
|
10
|
+
spec.version = StatsD::Instrument::VERSION
|
11
|
+
spec.authors = ["Jesse Storimer", "Tobias Lutke", "Willem van Bergen"]
|
12
|
+
spec.email = ["jesse@shopify.com"]
|
13
|
+
spec.homepage = "https://github.com/Shopify/statsd-instrument"
|
14
|
+
spec.summary = %q{A StatsD client for Ruby apps}
|
13
15
|
spec.description = %q{A StatsD client for Ruby apps. Provides metaprogramming methods to inject StatsD instrumentation into your code.}
|
14
|
-
spec.license
|
16
|
+
spec.license = "MIT"
|
15
17
|
|
16
|
-
spec.files
|
17
|
-
spec.executables
|
18
|
-
spec.test_files
|
18
|
+
spec.files = `git ls-files`.split($/)
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
21
|
spec.require_paths = ["lib"]
|
20
22
|
|
21
23
|
spec.add_development_dependency 'rake'
|
@@ -23,5 +25,6 @@ Gem::Specification.new do |spec|
|
|
23
25
|
spec.add_development_dependency 'rspec'
|
24
26
|
spec.add_development_dependency 'mocha'
|
25
27
|
spec.add_development_dependency 'yard'
|
28
|
+
spec.add_development_dependency 'rubocop'
|
26
29
|
spec.add_development_dependency 'benchmark-ips'
|
27
30
|
end
|
data/test/assertions_test.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'test_helper'
|
2
4
|
|
3
5
|
class AssertionsTest < Minitest::Test
|
@@ -163,6 +165,15 @@ class AssertionsTest < Minitest::Test
|
|
163
165
|
end
|
164
166
|
end
|
165
167
|
|
168
|
+
def test_tags_friendly_error
|
169
|
+
@test_case.assert_statsd_increment('counter', tags: { class: "AnotherJob" }) do
|
170
|
+
StatsD.increment('counter', tags: { class: "MyJob" })
|
171
|
+
end
|
172
|
+
rescue MiniTest::Assertion => assertion
|
173
|
+
assert_match(/Captured metrics with the same key/, assertion.message)
|
174
|
+
assert_match(/MyJob/, assertion.message)
|
175
|
+
end
|
176
|
+
|
166
177
|
def test_multiple_metrics_are_not_order_dependent
|
167
178
|
assert_no_assertion_triggered do
|
168
179
|
foo_1_metric = StatsD::Instrument::MetricExpectation.new(type: :c, name: 'counter', times: 1, tags: ['foo:1'])
|
@@ -262,7 +273,7 @@ class AssertionsTest < Minitest::Test
|
|
262
273
|
def test_assert_statsd_call_with_wrong_sample_rate_type
|
263
274
|
assert_assertion_triggered "Unexpected sample rate type for metric counter, must be numeric" do
|
264
275
|
@test_case.assert_statsd_increment('counter', tags: ['a', 'b']) do
|
265
|
-
StatsD.increment('counter', sample_rate: 'abc', tags:
|
276
|
+
StatsD.increment('counter', sample_rate: 'abc', tags: ['a', 'b'])
|
266
277
|
end
|
267
278
|
end
|
268
279
|
end
|
@@ -309,7 +320,7 @@ class AssertionsTest < Minitest::Test
|
|
309
320
|
def assert_no_assertion_triggered(&block)
|
310
321
|
block.call
|
311
322
|
rescue MiniTest::Assertion => assertion
|
312
|
-
flunk
|
323
|
+
flunk("No assertion trigger expected, but one was triggered with message #{assertion.message}.")
|
313
324
|
else
|
314
325
|
pass
|
315
326
|
end
|
@@ -318,12 +329,12 @@ class AssertionsTest < Minitest::Test
|
|
318
329
|
block.call
|
319
330
|
rescue MiniTest::Assertion => assertion
|
320
331
|
if message
|
321
|
-
assert_equal
|
332
|
+
assert_equal(message, assertion.message, "Assertion triggered, but message was not what was expected.")
|
322
333
|
else
|
323
334
|
pass
|
324
335
|
end
|
325
336
|
assertion
|
326
337
|
else
|
327
|
-
flunk
|
338
|
+
flunk("No assertion was triggered, but one was expected.")
|
328
339
|
end
|
329
340
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'statsd-instrument'
|
4
|
+
require 'benchmark/ips'
|
5
|
+
|
6
|
+
StatsD.logger = Logger.new('/dev/null')
|
7
|
+
|
8
|
+
class Suite
|
9
|
+
def warming(*args)
|
10
|
+
StatsD.default_tags = if args[0] == "with default tags"
|
11
|
+
{ first_tag: 'first_value', second_tag: 'second_value' }
|
12
|
+
end
|
13
|
+
puts "warming with default tags: #{StatsD.default_tags}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def running(*args)
|
17
|
+
StatsD.default_tags = if args[0] == "with default tags"
|
18
|
+
{ first_tag: 'first_value', second_tag: 'second_value' }
|
19
|
+
end
|
20
|
+
puts "running with default tags: #{StatsD.default_tags}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def warmup_stats(*)
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_report(*)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
suite = Suite.new
|
31
|
+
|
32
|
+
Benchmark.ips do |bench|
|
33
|
+
bench.config(suite: suite)
|
34
|
+
bench.report("without default tags") do
|
35
|
+
StatsD.increment('GoogleBase.insert', tags: {
|
36
|
+
first_tag: 'first_value',
|
37
|
+
second_tag: 'second_value',
|
38
|
+
third_tag: 'third_value',
|
39
|
+
})
|
40
|
+
end
|
41
|
+
|
42
|
+
bench.report("with default tags") do
|
43
|
+
StatsD.increment('GoogleBase.insert', tags: { third_tag: 'third_value' })
|
44
|
+
end
|
45
|
+
|
46
|
+
bench.compare!
|
47
|
+
end
|
data/test/benchmark/metrics.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'statsd-instrument'
|
2
4
|
require 'benchmark/ips'
|
3
5
|
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def helper_function
|
7
|
+
a = 10
|
8
|
+
a += a
|
9
|
+
a -= a
|
10
|
+
a * a
|
9
11
|
end
|
10
12
|
|
11
13
|
Benchmark.ips do |bench|
|
@@ -14,8 +16,8 @@ Benchmark.ips do |bench|
|
|
14
16
|
end
|
15
17
|
|
16
18
|
bench.report("measure metric benchmark") do
|
17
|
-
StatsD.measure('
|
18
|
-
|
19
|
+
StatsD.measure('helper_function') do
|
20
|
+
helper_function
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
@@ -34,5 +36,4 @@ Benchmark.ips do |bench|
|
|
34
36
|
bench.report("service check metric benchmark") do
|
35
37
|
StatsD.service_check('shipit.redis_connection', 'ok')
|
36
38
|
end
|
37
|
-
|
38
39
|
end
|
data/test/benchmark/tags.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'statsd-instrument'
|
2
4
|
require 'benchmark/ips'
|
3
5
|
|
4
6
|
Benchmark.ips do |bench|
|
5
7
|
bench.report("normalized tags with simple hash") do
|
6
|
-
StatsD::Instrument::Metric.normalize_tags(:
|
8
|
+
StatsD::Instrument::Metric.normalize_tags(tag: 'value')
|
7
9
|
end
|
8
10
|
|
9
11
|
bench.report("normalized tags with simple array") do
|
@@ -11,14 +13,14 @@ Benchmark.ips do |bench|
|
|
11
13
|
end
|
12
14
|
|
13
15
|
bench.report("normalized tags with large hash") do
|
14
|
-
StatsD::Instrument::Metric.normalize_tags(
|
16
|
+
StatsD::Instrument::Metric.normalize_tags(
|
15
17
|
mobile: true,
|
16
18
|
pod: "1",
|
17
19
|
protocol: "https",
|
18
20
|
country: "Langbortistan",
|
19
21
|
complete: true,
|
20
22
|
shop: "omg shop that has a longer name",
|
21
|
-
|
23
|
+
)
|
22
24
|
end
|
23
25
|
|
24
26
|
bench.report("normalized tags with large array") do
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'test_helper'
|
2
4
|
|
3
5
|
class CaptureBackendTest < Minitest::Test
|
4
6
|
def setup
|
5
7
|
@backend = StatsD::Instrument::Backends::CaptureBackend.new
|
6
|
-
@metric1 = StatsD::Instrument::Metric
|
7
|
-
@metric2 = StatsD::Instrument::Metric
|
8
|
+
@metric1 = StatsD::Instrument::Metric.new(type: :c, name: 'mock.counter')
|
9
|
+
@metric2 = StatsD::Instrument::Metric.new(type: :ms, name: 'mock.measure', value: 123)
|
8
10
|
end
|
9
11
|
|
10
12
|
def test_collecting_metric
|
data/test/environment_test.rb
CHANGED
data/test/helpers_test.rb
CHANGED
data/test/integration_test.rb
CHANGED
@@ -1,20 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'test_helper'
|
2
4
|
|
3
5
|
class IntegrationTest < Minitest::Test
|
4
|
-
|
5
6
|
def setup
|
6
|
-
@
|
7
|
+
@server = UDPSocket.new
|
8
|
+
@server.bind('localhost', 0)
|
9
|
+
port = @server.addr[1]
|
10
|
+
|
11
|
+
@old_backend = StatsD.backend
|
12
|
+
StatsD.backend = StatsD::Instrument::Backends::UDPBackend.new("localhost:#{port}")
|
7
13
|
end
|
8
|
-
|
14
|
+
|
9
15
|
def teardown
|
16
|
+
@server.close
|
10
17
|
StatsD.backend = @old_backend
|
11
18
|
end
|
12
19
|
|
13
20
|
def test_live_local_udp_socket
|
14
|
-
server = UDPSocket.new
|
15
|
-
server.bind('localhost', 31798)
|
16
|
-
|
17
21
|
StatsD.increment('counter')
|
18
|
-
assert_equal "counter:1|c", server.recvfrom(100).first
|
22
|
+
assert_equal "counter:1|c", @server.recvfrom(100).first
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_synchronize_in_exit_handler_handles_thread_error_and_exits_cleanly
|
26
|
+
pid = fork do
|
27
|
+
Signal.trap('TERM') do
|
28
|
+
StatsD.increment('exiting')
|
29
|
+
Process.exit!(0)
|
30
|
+
end
|
31
|
+
|
32
|
+
sleep 100
|
33
|
+
end
|
34
|
+
|
35
|
+
Process.kill('TERM', pid)
|
36
|
+
Process.waitpid(pid)
|
37
|
+
|
38
|
+
assert_equal "exiting:1|c", @server.recvfrom(100).first
|
19
39
|
end
|
20
40
|
end
|
data/test/logger_backend_test.rb
CHANGED
@@ -1,20 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'test_helper'
|
2
4
|
|
3
5
|
class LoggerBackendTest < Minitest::Test
|
4
6
|
def setup
|
5
7
|
logger = Logger.new(@io = StringIO.new)
|
6
|
-
logger.formatter = lambda { |_,_,_, msg| "#{msg}\n" }
|
8
|
+
logger.formatter = lambda { |_, _, _, msg| "#{msg}\n" }
|
7
9
|
@backend = StatsD::Instrument::Backends::LoggerBackend.new(logger)
|
8
|
-
@metric1 = StatsD::Instrument::Metric
|
9
|
-
@metric2 = StatsD::Instrument::Metric
|
10
|
+
@metric1 = StatsD::Instrument::Metric.new(type: :c, name: 'mock.counter', tags: { a: 'b', c: 'd' })
|
11
|
+
@metric2 = StatsD::Instrument::Metric.new(type: :ms, name: 'mock.measure', value: 123, sample_rate: 0.3)
|
10
12
|
end
|
11
13
|
|
12
14
|
def test_logs_metrics
|
13
15
|
@backend.collect_metric(@metric1)
|
14
|
-
assert_equal @io.string, "[StatsD] increment mock.counter:1 #a:b #c:d\n"
|
15
|
-
@io.string = ""
|
16
|
-
|
17
16
|
@backend.collect_metric(@metric2)
|
18
|
-
assert_equal @io.string
|
17
|
+
assert_equal <<~LOG, @io.string
|
18
|
+
[StatsD] increment mock.counter:1 #a:b #c:d
|
19
|
+
[StatsD] measure mock.measure:123 @0.3
|
20
|
+
LOG
|
19
21
|
end
|
20
|
-
end
|
22
|
+
end
|