statsd-instrument 2.5.1 → 2.6.0
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/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +1 -1
- data/.rubocop.yml +11 -6
- data/.yardopts +5 -0
- data/CHANGELOG.md +75 -6
- data/README.md +54 -46
- data/benchmark/datagram-client +41 -0
- data/lib/statsd/instrument/assertions.rb +168 -57
- data/lib/statsd/instrument/backends/udp_backend.rb +20 -29
- data/lib/statsd/instrument/capture_sink.rb +27 -0
- data/lib/statsd/instrument/client.rb +313 -0
- data/lib/statsd/instrument/datagram.rb +75 -0
- data/lib/statsd/instrument/datagram_builder.rb +101 -0
- data/lib/statsd/instrument/dogstatsd_datagram_builder.rb +71 -0
- data/lib/statsd/instrument/environment.rb +106 -29
- data/lib/statsd/instrument/log_sink.rb +24 -0
- data/lib/statsd/instrument/null_sink.rb +13 -0
- data/lib/statsd/instrument/rubocop/measure_as_dist_argument.rb +39 -0
- data/lib/statsd/instrument/rubocop/metaprogramming_positional_arguments.rb +6 -10
- data/lib/statsd/instrument/rubocop/metric_prefix_argument.rb +37 -0
- data/lib/statsd/instrument/rubocop/metric_return_value.rb +7 -6
- data/lib/statsd/instrument/rubocop/metric_value_keyword_argument.rb +11 -20
- data/lib/statsd/instrument/rubocop/positional_arguments.rb +13 -13
- data/lib/statsd/instrument/rubocop/splat_arguments.rb +8 -14
- data/lib/statsd/instrument/rubocop.rb +64 -0
- data/lib/statsd/instrument/statsd_datagram_builder.rb +14 -0
- data/lib/statsd/instrument/strict.rb +112 -22
- data/lib/statsd/instrument/udp_sink.rb +62 -0
- data/lib/statsd/instrument/version.rb +1 -1
- data/lib/statsd/instrument.rb +191 -100
- data/test/assertions_test.rb +139 -176
- data/test/capture_sink_test.rb +44 -0
- data/test/client_test.rb +164 -0
- data/test/compatibility/dogstatsd_datagram_compatibility_test.rb +162 -0
- data/test/datagram_builder_test.rb +120 -0
- data/test/deprecations_test.rb +56 -10
- data/test/dogstatsd_datagram_builder_test.rb +32 -0
- data/test/environment_test.rb +73 -7
- data/test/log_sink_test.rb +37 -0
- data/test/null_sink_test.rb +13 -0
- data/test/rubocop/measure_as_dist_argument_test.rb +44 -0
- data/test/rubocop/metaprogramming_positional_arguments_test.rb +1 -1
- data/test/rubocop/metric_prefix_argument_test.rb +38 -0
- data/test/rubocop/metric_return_value_test.rb +1 -1
- data/test/rubocop/metric_value_keyword_argument_test.rb +1 -1
- data/test/rubocop/positional_arguments_test.rb +1 -1
- data/test/rubocop/splat_arguments_test.rb +1 -1
- data/test/statsd_datagram_builder_test.rb +22 -0
- data/test/statsd_instrumentation_test.rb +0 -24
- data/test/statsd_test.rb +0 -23
- data/test/test_helper.rb +0 -2
- data/test/udp_backend_test.rb +25 -8
- data/test/udp_sink_test.rb +85 -0
- metadata +38 -2
data/test/environment_test.rb
CHANGED
@@ -10,22 +10,22 @@ class EnvironmentTest < Minitest::Test
|
|
10
10
|
ENV['IMPLEMENTATION'] = nil
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
13
|
+
def test_default_backend_uses_logger_in_development_environment
|
14
14
|
StatsD::Instrument::Environment.stubs(:environment).returns('development')
|
15
15
|
assert_instance_of StatsD::Instrument::Backends::LoggerBackend, StatsD::Instrument::Environment.default_backend
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def test_default_backend_uses_null_backend_in_test_environment
|
19
19
|
StatsD::Instrument::Environment.stubs(:environment).returns('test')
|
20
20
|
assert_instance_of StatsD::Instrument::Backends::NullBackend, StatsD::Instrument::Environment.default_backend
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
23
|
+
def test_default_backend_uses_udp_backend_in_production_environment
|
24
24
|
StatsD::Instrument::Environment.stubs(:environment).returns('production')
|
25
25
|
assert_instance_of StatsD::Instrument::Backends::UDPBackend, StatsD::Instrument::Environment.default_backend
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
28
|
+
def test_default_backend_uses_environment_variables_in_production_environment
|
29
29
|
StatsD::Instrument::Environment.stubs(:environment).returns('production')
|
30
30
|
ENV['STATSD_ADDR'] = '127.0.0.1:1234'
|
31
31
|
ENV['STATSD_IMPLEMENTATION'] = 'datadog'
|
@@ -36,12 +36,78 @@ class EnvironmentTest < Minitest::Test
|
|
36
36
|
assert_equal :datadog, backend.implementation
|
37
37
|
end
|
38
38
|
|
39
|
-
def
|
40
|
-
|
39
|
+
def test_environment_prefers_statsd_env_if_available
|
40
|
+
env = StatsD::Instrument::Environment.new(
|
41
|
+
'STATSD_ENV' => 'set_from_STATSD_ENV',
|
42
|
+
'RACK_ENV' => 'set_from_RACK_ENV',
|
43
|
+
'ENV' => 'set_from_ENV',
|
44
|
+
)
|
45
|
+
assert_equal 'set_from_STATSD_ENV', env.environment
|
41
46
|
end
|
42
47
|
|
43
|
-
def
|
48
|
+
def test_environment_uses_env_when_rails_does_not_respond_to_env_and_statsd_env_is_not_set
|
49
|
+
env = StatsD::Instrument::Environment.new(
|
50
|
+
'ENV' => 'set_from_ENV',
|
51
|
+
)
|
52
|
+
assert_equal 'set_from_ENV', env.environment
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_environment_uses_rails_env_when_rails_is_available
|
44
56
|
Rails.stubs(:env).returns('production')
|
45
57
|
assert_equal 'production', StatsD::Instrument::Environment.environment
|
46
58
|
end
|
59
|
+
|
60
|
+
def test_environment_defaults_to_development
|
61
|
+
env = StatsD::Instrument::Environment.new({})
|
62
|
+
assert_equal 'development', env.environment
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_default_client_uses_log_sink_in_development_environment
|
66
|
+
env = StatsD::Instrument::Environment.new('STATSD_ENV' => 'development')
|
67
|
+
assert_kind_of StatsD::Instrument::LogSink, env.default_client.sink
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_default_client_uses_null_sink_in_test_environment
|
71
|
+
env = StatsD::Instrument::Environment.new('STATSD_ENV' => 'test')
|
72
|
+
assert_kind_of StatsD::Instrument::NullSink, env.default_client.sink
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_default_client_uses_udp_sink_in_staging_environment
|
76
|
+
env = StatsD::Instrument::Environment.new('STATSD_ENV' => 'staging')
|
77
|
+
assert_kind_of StatsD::Instrument::UDPSink, env.default_client.sink
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_default_client_uses_udp_sink_in_production_environment
|
81
|
+
env = StatsD::Instrument::Environment.new('STATSD_ENV' => 'production')
|
82
|
+
assert_kind_of StatsD::Instrument::UDPSink, env.default_client.sink
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_default_client_respects_statsd_environment_variables
|
86
|
+
env = StatsD::Instrument::Environment.new(
|
87
|
+
'STATSD_ENV' => 'production',
|
88
|
+
'STATSD_IMPLEMENTATION' => 'datadog',
|
89
|
+
'STATSD_ADDR' => 'foo:8125',
|
90
|
+
'STATSD_SAMPLE_RATE' => "0.1",
|
91
|
+
'STATSD_PREFIX' => "foo",
|
92
|
+
'STATSD_DEFAULT_TAGS' => "foo,bar:baz",
|
93
|
+
)
|
94
|
+
|
95
|
+
assert_equal StatsD::Instrument::DogStatsDDatagramBuilder, env.default_client.datagram_builder_class
|
96
|
+
assert_equal 'foo', env.default_client.sink.host
|
97
|
+
assert_equal 8125, env.default_client.sink.port
|
98
|
+
assert_equal 0.1, env.default_client.default_sample_rate
|
99
|
+
assert_equal "foo", env.default_client.prefix
|
100
|
+
assert_equal ["foo", "bar:baz"], env.default_client.default_tags
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_default_client_has_sensible_defaults
|
104
|
+
env = StatsD::Instrument::Environment.new('STATSD_ENV' => 'production')
|
105
|
+
|
106
|
+
assert_equal StatsD::Instrument::StatsDDatagramBuilder, env.default_client.datagram_builder_class
|
107
|
+
assert_equal 'localhost', env.default_client.sink.host
|
108
|
+
assert_equal 8125, env.default_client.sink.port
|
109
|
+
assert_equal 1.0, env.default_client.default_sample_rate
|
110
|
+
assert_nil env.default_client.prefix
|
111
|
+
assert_nil env.default_client.default_tags
|
112
|
+
end
|
47
113
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
require 'statsd/instrument/client'
|
6
|
+
|
7
|
+
class LogSinktest < Minitest::Test
|
8
|
+
def test_log_sink
|
9
|
+
logger = Logger.new(log = StringIO.new)
|
10
|
+
logger.formatter = proc do |severity, _datetime, _progname, msg|
|
11
|
+
"#{severity}: #{msg}\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
log_sink = StatsD::Instrument::LogSink.new(logger)
|
15
|
+
log_sink << 'foo:1|c' << 'bar:1|c'
|
16
|
+
|
17
|
+
assert_equal <<~LOG, log.string
|
18
|
+
DEBUG: [StatsD] foo:1|c
|
19
|
+
DEBUG: [StatsD] bar:1|c
|
20
|
+
LOG
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_log_sink_chomps_trailing_newlines
|
24
|
+
logger = Logger.new(log = StringIO.new)
|
25
|
+
logger.formatter = proc do |severity, _datetime, _progname, msg|
|
26
|
+
"#{severity}: #{msg}\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
log_sink = StatsD::Instrument::LogSink.new(logger)
|
30
|
+
log_sink << "foo:1|c\n" << "bar:1|c\n"
|
31
|
+
|
32
|
+
assert_equal <<~LOG, log.string
|
33
|
+
DEBUG: [StatsD] foo:1|c
|
34
|
+
DEBUG: [StatsD] bar:1|c
|
35
|
+
LOG
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
require 'statsd/instrument/client'
|
6
|
+
|
7
|
+
class NullSinktest < Minitest::Test
|
8
|
+
def test_null_sink
|
9
|
+
null_sink = StatsD::Instrument::NullSink.new
|
10
|
+
null_sink << 'foo:1|c' << 'bar:1|c'
|
11
|
+
pass # We don't have anything to assert, except that no exception was raised
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require 'statsd/instrument/rubocop'
|
5
|
+
|
6
|
+
module Rubocop
|
7
|
+
class MeasureAsDistArgumentTest < Minitest::Test
|
8
|
+
include RubocopHelper
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@cop = RuboCop::Cop::StatsD::MeasureAsDistArgument.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_ok_for_metric_method_without_as_dist_argument
|
15
|
+
assert_no_offenses("StatsD.measure('foo', 123)")
|
16
|
+
assert_no_offenses("StatsD.measure('foo', 123, sample_rate: 3)")
|
17
|
+
assert_no_offenses("StatsD.measure('foo') {}")
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_ok_for_other_metric_methods
|
21
|
+
assert_no_offenses("StatsD.increment('foo', as_dist: true)")
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_ok_for_metaprogramming_method_without_as_dist_argument
|
25
|
+
assert_no_offenses("statsd_measure(:method, 'metric_name', sample_rate: 1) {}")
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_ok_for_other_metaprogramming_methods
|
29
|
+
assert_no_offenses("statsd_distribution(:method, 'metric_name', as_dist: true) {}")
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_offense_when_using_as_dist_with_measure_metric_method
|
33
|
+
assert_offense("StatsD.measure('foo', 123, sample_rate: 1, as_dist: true, tags: ['foo'])")
|
34
|
+
assert_offense("StatsD.measure('foo', 123, as_dist: false)")
|
35
|
+
assert_offense("StatsD.measure('foo', as_dist: true, &block)")
|
36
|
+
assert_offense("StatsD.measure('foo', as_dist: true) { } ")
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_offense_when_using_as_dist_with_measure_metaprogramming_method
|
40
|
+
assert_offense("statsd_measure(:method, 'foo', as_dist: true, &block)")
|
41
|
+
assert_offense("statsd_measure(:method, 'foo', as_dist: false) { } ")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require 'statsd/instrument/rubocop'
|
5
|
+
|
6
|
+
module Rubocop
|
7
|
+
class MetricPrefixArgumentTest < Minitest::Test
|
8
|
+
include RubocopHelper
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@cop = RuboCop::Cop::StatsD::MetricPrefixArgument.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_ok_for_metric_method_without_prefix_argument
|
15
|
+
assert_no_offenses("StatsD.measure('foo', 123) {}")
|
16
|
+
assert_no_offenses("StatsD.increment('foo', 123, sample_rate: 3, no_prefix: true)")
|
17
|
+
assert_no_offenses("StatsD.gauge('foo', 123)")
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_ok_for_metaprogramming_method_without_prefix_argument
|
21
|
+
assert_no_offenses("statsd_measure(:method, 'metric_name')")
|
22
|
+
assert_no_offenses("statsd_count(:method, 'metric_name', sample_rate: 1, no_pefix: true)")
|
23
|
+
assert_no_offenses("statsd_count_if(:method, 'metric_name', sample_rate: 1) {}")
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_offense_when_using_as_dist_with_measure_metric_method
|
27
|
+
assert_offense("StatsD.measure('foo', 123, sample_rate: 1, prefix: 'pre', tags: ['bar'])")
|
28
|
+
assert_offense("StatsD.gauge('foo', 123, prefix: nil)")
|
29
|
+
assert_offense("StatsD.increment('foo', prefix: 'pre', &block)")
|
30
|
+
assert_offense("StatsD.set('foo', prefix: 'pre') { } ")
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_offense_when_using_as_dist_with_measure_metaprogramming_method
|
34
|
+
assert_offense("statsd_measure(:method, 'foo', prefix: 'foo')")
|
35
|
+
assert_offense("statsd_count_if(:method, 'foo', prefix: nil) { } ")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
require 'statsd/instrument/client'
|
6
|
+
|
7
|
+
class StatsDDatagramBuilderTest < Minitest::Test
|
8
|
+
def setup
|
9
|
+
@datagram_builder = StatsD::Instrument::StatsDDatagramBuilder.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_raises_on_unsupported_metrics
|
13
|
+
assert_raises(NotImplementedError) { @datagram_builder.h('fo:o', 10, nil, nil) }
|
14
|
+
assert_raises(NotImplementedError) { @datagram_builder.d('fo:o', 10, nil, nil) }
|
15
|
+
assert_raises(NotImplementedError) { @datagram_builder.kv('fo:o', 10, nil, nil) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_raises_when_using_tags
|
19
|
+
assert_raises(NotImplementedError) { @datagram_builder.c('fo:o', 10, nil, foo: 'bar') }
|
20
|
+
assert_raises(NotImplementedError) { StatsD::Instrument::StatsDDatagramBuilder.new(default_tags: ['foo']) }
|
21
|
+
end
|
22
|
+
end
|
@@ -248,16 +248,6 @@ class StatsDInstrumentationTest < Minitest::Test
|
|
248
248
|
ActiveMerchant::UniqueGateway.statsd_remove_measure :ssl_post, 'ActiveMerchant.Gateway.ssl_post'
|
249
249
|
end
|
250
250
|
|
251
|
-
def test_statsd_measure_as_distribution
|
252
|
-
ActiveMerchant::UniqueGateway.statsd_measure :ssl_post, 'ActiveMerchant.Gateway.ssl_post', as_dist: true
|
253
|
-
|
254
|
-
assert_statsd_distribution('ActiveMerchant.Gateway.ssl_post') do
|
255
|
-
ActiveMerchant::UniqueGateway.new.purchase(true)
|
256
|
-
end
|
257
|
-
ensure
|
258
|
-
ActiveMerchant::UniqueGateway.statsd_remove_measure :ssl_post, 'ActiveMerchant.Gateway.ssl_post'
|
259
|
-
end
|
260
|
-
|
261
251
|
def test_statsd_distribution
|
262
252
|
ActiveMerchant::UniqueGateway.statsd_distribution :ssl_post, 'ActiveMerchant.Gateway.ssl_post', sample_rate: 0.3
|
263
253
|
|
@@ -351,20 +341,6 @@ class StatsDInstrumentationTest < Minitest::Test
|
|
351
341
|
ActiveMerchant::Gateway.singleton_class.statsd_remove_count :sync, 'ActiveMerchant.Gateway.sync'
|
352
342
|
end
|
353
343
|
|
354
|
-
def test_statsd_macro_can_overwrite_prefix
|
355
|
-
StatsD.prefix = 'Foo'
|
356
|
-
ActiveMerchant::Gateway.singleton_class.extend StatsD::Instrument
|
357
|
-
ActiveMerchant::Gateway.singleton_class.statsd_measure :sync, 'ActiveMerchant.Gateway.sync', prefix: 'Bar'
|
358
|
-
StatsD.prefix = 'Quc'
|
359
|
-
|
360
|
-
statsd_calls = capture_statsd_calls { ActiveMerchant::Gateway.sync }
|
361
|
-
assert_equal 1, statsd_calls.length
|
362
|
-
assert_equal "Bar.ActiveMerchant.Gateway.sync", statsd_calls.first.name
|
363
|
-
ensure
|
364
|
-
StatsD.prefix = nil
|
365
|
-
ActiveMerchant::Gateway.singleton_class.statsd_remove_measure :sync, 'ActiveMerchant.Gateway.sync'
|
366
|
-
end
|
367
|
-
|
368
344
|
def test_statsd_macro_can_disable_prefix
|
369
345
|
StatsD.prefix = 'Foo'
|
370
346
|
ActiveMerchant::Gateway.singleton_class.extend StatsD::Instrument
|
data/test/statsd_test.rb
CHANGED
@@ -21,11 +21,6 @@ class StatsDTest < Minitest::Test
|
|
21
21
|
assert_equal :ms, metric.type
|
22
22
|
end
|
23
23
|
|
24
|
-
def test_statsd_measure_with_explicit_value_and_distribution_override
|
25
|
-
metric = capture_statsd_call { StatsD.measure('values.foobar', 42, as_dist: true) }
|
26
|
-
assert_equal :d, metric.type
|
27
|
-
end
|
28
|
-
|
29
24
|
def test_statsd_measure_without_value_or_block
|
30
25
|
assert_raises(ArgumentError) { StatsD.measure('values.foobar', tags: 123) }
|
31
26
|
end
|
@@ -43,23 +38,11 @@ class StatsDTest < Minitest::Test
|
|
43
38
|
assert_equal 1120.0, metric.value
|
44
39
|
end
|
45
40
|
|
46
|
-
def test_statsd_measure_use_distribution_override_for_a_block
|
47
|
-
metric = capture_statsd_call do
|
48
|
-
StatsD.measure('values.foobar', as_dist: true) { 'foo' }
|
49
|
-
end
|
50
|
-
assert_equal :d, metric.type
|
51
|
-
end
|
52
|
-
|
53
41
|
def test_statsd_measure_returns_return_value_of_block
|
54
42
|
return_value = StatsD.measure('values.foobar') { 'sarah' }
|
55
43
|
assert_equal 'sarah', return_value
|
56
44
|
end
|
57
45
|
|
58
|
-
def test_statsd_measure_as_distribution_returns_return_value_of_block_even_if_nil
|
59
|
-
return_value = StatsD.measure('values.foobar', as_dist: true) { nil }
|
60
|
-
assert_nil return_value
|
61
|
-
end
|
62
|
-
|
63
46
|
def test_statsd_measure_with_return_in_block_still_captures
|
64
47
|
Process.stubs(:clock_gettime).returns(5.0, 6.12)
|
65
48
|
result = nil
|
@@ -236,12 +219,6 @@ class StatsDTest < Minitest::Test
|
|
236
219
|
|
237
220
|
m = capture_statsd_call { StatsD.increment('counter', no_prefix: true) }
|
238
221
|
assert_equal 'counter', m.name
|
239
|
-
|
240
|
-
m = capture_statsd_call { StatsD.increment('counter', prefix: "foobar") }
|
241
|
-
assert_equal 'foobar.counter', m.name
|
242
|
-
|
243
|
-
m = capture_statsd_call { StatsD.increment('counter', prefix: "foobar", no_prefix: true) }
|
244
|
-
assert_equal 'counter', m.name
|
245
222
|
end
|
246
223
|
|
247
224
|
protected
|
data/test/test_helper.rb
CHANGED
data/test/udp_backend_test.rb
CHANGED
@@ -86,8 +86,8 @@ class UDPBackendTest < Minitest::Test
|
|
86
86
|
|
87
87
|
def test_event_on_datadog
|
88
88
|
@backend.implementation = :datadog
|
89
|
-
@backend.expects(:write_packet).with('_e{4,3}:fooh|baz|h:localhost
|
90
|
-
StatsD.event('fooh', 'baz', hostname: 'localhost
|
89
|
+
@backend.expects(:write_packet).with('_e{4,3}:fooh|baz|h:localhost|#foo')
|
90
|
+
StatsD.event('fooh', 'baz', hostname: 'localhost', tags: ["foo"])
|
91
91
|
end
|
92
92
|
|
93
93
|
def test_event_on_datadog_escapes_newlines
|
@@ -98,8 +98,13 @@ class UDPBackendTest < Minitest::Test
|
|
98
98
|
|
99
99
|
def test_event_on_datadog_ignores_invalid_metadata
|
100
100
|
@backend.implementation = :datadog
|
101
|
-
|
102
|
-
|
101
|
+
if StatsD::Instrument.strict_mode_enabled?
|
102
|
+
assert_raises(ArgumentError) { StatsD.event('fooh', 'baz', sample_rate: 0.01) }
|
103
|
+
assert_raises(ArgumentError) { StatsD.event('fooh', 'baz', unsupported: 'foo') }
|
104
|
+
else
|
105
|
+
@backend.expects(:write_packet).with('_e{4,3}:fooh|baz')
|
106
|
+
StatsD.event('fooh', 'baz', sample_rate: 0.01, i_am_not_supported: 'not-supported')
|
107
|
+
end
|
103
108
|
end
|
104
109
|
|
105
110
|
def test_event_warns_when_not_using_datadog
|
@@ -111,14 +116,26 @@ class UDPBackendTest < Minitest::Test
|
|
111
116
|
|
112
117
|
def test_service_check_on_datadog
|
113
118
|
@backend.implementation = :datadog
|
114
|
-
@backend.expects(:write_packet).with('_sc|fooh|
|
115
|
-
StatsD.service_check('fooh',
|
119
|
+
@backend.expects(:write_packet).with('_sc|fooh|0|h:localhost|#foo')
|
120
|
+
StatsD.service_check('fooh', 0, hostname: 'localhost', tags: ["foo"])
|
116
121
|
end
|
117
122
|
|
118
123
|
def test_service_check_on_datadog_ignores_invalid_metadata
|
119
124
|
@backend.implementation = :datadog
|
120
|
-
|
121
|
-
|
125
|
+
if StatsD::Instrument.strict_mode_enabled?
|
126
|
+
assert_raises(ArgumentError) { StatsD.service_check('fooh', "warning", sample_rate: 0.01) }
|
127
|
+
assert_raises(ArgumentError) { StatsD.service_check('fooh', "warning", unsupported: 'foo') }
|
128
|
+
else
|
129
|
+
@backend.expects(:write_packet).with('_sc|fooh|1')
|
130
|
+
StatsD.service_check('fooh', "warning", sample_rate: 0.01, i_am_not_supported: 'not-supported')
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_service_check_on_datadog_will_append_message_as_final_metadata_field
|
135
|
+
@backend.implementation = :datadog
|
136
|
+
@backend.expects(:write_packet).with('_sc|fooh|0|d:1230768000|#quc|m:Everything OK')
|
137
|
+
StatsD.service_check('fooh', :ok, message: "Everything OK",
|
138
|
+
timestamp: Time.parse('2009-01-01T00:00:00Z'), tags: ['quc'])
|
122
139
|
end
|
123
140
|
|
124
141
|
def test_service_check_warns_when_not_using_datadog
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
require 'statsd/instrument/client'
|
6
|
+
|
7
|
+
class UDPSinktest < Minitest::Test
|
8
|
+
def setup
|
9
|
+
@receiver = UDPSocket.new
|
10
|
+
@receiver.bind('localhost', 0)
|
11
|
+
@host = @receiver.addr[2]
|
12
|
+
@port = @receiver.addr[1]
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
@receiver.close
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_udp_sink_sends_data_over_udp
|
20
|
+
udp_sink = StatsD::Instrument::UDPSink.new(@host, @port)
|
21
|
+
udp_sink << 'foo:1|c'
|
22
|
+
|
23
|
+
datagram, _source = @receiver.recvfrom(100)
|
24
|
+
assert_equal 'foo:1|c', datagram
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_sample?
|
28
|
+
udp_sink = StatsD::Instrument::UDPSink.new(@host, @port)
|
29
|
+
assert udp_sink.sample?(1)
|
30
|
+
refute udp_sink.sample?(0)
|
31
|
+
|
32
|
+
udp_sink.stubs(:rand).returns(0.3)
|
33
|
+
assert udp_sink.sample?(0.5)
|
34
|
+
|
35
|
+
udp_sink.stubs(:rand).returns(0.7)
|
36
|
+
refute udp_sink.sample?(0.5)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_parallelism
|
40
|
+
udp_sink = StatsD::Instrument::UDPSink.new(@host, @port)
|
41
|
+
50.times { |i| Thread.new { udp_sink << "foo:#{i}|c" << "bar:#{i}|c" } }
|
42
|
+
datagrams = []
|
43
|
+
100.times do
|
44
|
+
datagram, _source = @receiver.recvfrom(100)
|
45
|
+
datagrams << datagram
|
46
|
+
end
|
47
|
+
|
48
|
+
assert_equal 100, datagrams.size
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_socket_error_should_invalidate_socket
|
52
|
+
UDPSocket.stubs(:new).returns(socket = mock('socket'))
|
53
|
+
|
54
|
+
seq = sequence('connect_fail_connect_succeed')
|
55
|
+
socket.expects(:connect).with('localhost', 8125).in_sequence(seq)
|
56
|
+
socket.expects(:send).raises(Errno::EDESTADDRREQ).in_sequence(seq)
|
57
|
+
socket.expects(:connect).with('localhost', 8125).in_sequence(seq)
|
58
|
+
socket.expects(:send).returns(1).in_sequence(seq)
|
59
|
+
|
60
|
+
udp_sink = StatsD::Instrument::UDPSink.new('localhost', 8125)
|
61
|
+
udp_sink << 'foo:1|c'
|
62
|
+
udp_sink << 'bar:1|c'
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_sends_datagram_in_signal_handler
|
66
|
+
udp_sink = StatsD::Instrument::UDPSink.new(@host, @port)
|
67
|
+
pid = fork do
|
68
|
+
Signal.trap('TERM') do
|
69
|
+
udp_sink << "exiting:1|c"
|
70
|
+
Process.exit!(0)
|
71
|
+
end
|
72
|
+
|
73
|
+
sleep(10)
|
74
|
+
end
|
75
|
+
|
76
|
+
Process.kill('TERM', pid)
|
77
|
+
_, exit_status = Process.waitpid2(pid)
|
78
|
+
|
79
|
+
assert_equal 0, exit_status, "The forked process did not exit cleanly"
|
80
|
+
assert_equal "exiting:1|c", @receiver.recvfrom_nonblock(100).first
|
81
|
+
|
82
|
+
rescue NotImplementedError
|
83
|
+
pass("Fork is not implemented on #{RUBY_PLATFORM}")
|
84
|
+
end
|
85
|
+
end
|