statsd-instrument 2.3.2 → 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/.github/CODEOWNERS +1 -0
- data/.github/workflows/benchmark.yml +32 -0
- data/.github/workflows/ci.yml +47 -0
- data/.gitignore +1 -0
- data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +1027 -0
- data/.rubocop.yml +50 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +288 -2
- data/CONTRIBUTING.md +28 -6
- data/Gemfile +5 -0
- data/README.md +54 -46
- data/Rakefile +4 -2
- data/benchmark/README.md +29 -0
- data/benchmark/datagram-client +41 -0
- data/benchmark/send-metrics-to-dev-null-log +47 -0
- data/benchmark/send-metrics-to-local-udp-receiver +57 -0
- data/lib/statsd/instrument/assertions.rb +179 -30
- data/lib/statsd/instrument/backend.rb +3 -2
- data/lib/statsd/instrument/backends/capture_backend.rb +4 -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 +39 -45
- 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 +108 -29
- data/lib/statsd/instrument/helpers.rb +16 -8
- data/lib/statsd/instrument/log_sink.rb +24 -0
- data/lib/statsd/instrument/matchers.rb +14 -11
- data/lib/statsd/instrument/metric.rb +72 -45
- data/lib/statsd/instrument/metric_expectation.rb +32 -18
- data/lib/statsd/instrument/null_sink.rb +13 -0
- data/lib/statsd/instrument/railtie.rb +2 -1
- data/lib/statsd/instrument/rubocop/measure_as_dist_argument.rb +39 -0
- data/lib/statsd/instrument/rubocop/metaprogramming_positional_arguments.rb +42 -0
- data/lib/statsd/instrument/rubocop/metric_prefix_argument.rb +37 -0
- data/lib/statsd/instrument/rubocop/metric_return_value.rb +32 -0
- data/lib/statsd/instrument/rubocop/metric_value_keyword_argument.rb +36 -0
- data/lib/statsd/instrument/rubocop/positional_arguments.rb +99 -0
- data/lib/statsd/instrument/rubocop/splat_arguments.rb +31 -0
- data/lib/statsd/instrument/rubocop.rb +64 -0
- data/lib/statsd/instrument/statsd_datagram_builder.rb +14 -0
- data/lib/statsd/instrument/strict.rb +235 -0
- data/lib/statsd/instrument/udp_sink.rb +62 -0
- data/lib/statsd/instrument/version.rb +3 -1
- data/lib/statsd/instrument.rb +340 -163
- data/lib/statsd-instrument.rb +2 -0
- data/statsd-instrument.gemspec +13 -10
- data/test/assertions_test.rb +167 -156
- data/test/benchmark/clock_gettime.rb +27 -0
- 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/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 +132 -0
- data/test/dogstatsd_datagram_builder_test.rb +32 -0
- data/test/environment_test.rb +75 -8
- data/test/helpers/rubocop_helper.rb +47 -0
- data/test/helpers_test.rb +2 -1
- data/test/integration_test.rb +31 -7
- data/test/log_sink_test.rb +37 -0
- data/test/logger_backend_test.rb +10 -8
- data/test/matchers_test.rb +42 -28
- data/test/metric_test.rb +18 -22
- 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 +58 -0
- data/test/rubocop/metric_prefix_argument_test.rb +38 -0
- data/test/rubocop/metric_return_value_test.rb +78 -0
- data/test/rubocop/metric_value_keyword_argument_test.rb +39 -0
- data/test/rubocop/positional_arguments_test.rb +110 -0
- data/test/rubocop/splat_arguments_test.rb +27 -0
- data/test/statsd_datagram_builder_test.rb +22 -0
- data/test/statsd_instrumentation_test.rb +109 -100
- data/test/statsd_test.rb +113 -79
- data/test/test_helper.rb +12 -1
- data/test/udp_backend_test.rb +38 -36
- data/test/udp_sink_test.rb +85 -0
- metadata +85 -5
- data/.travis.yml +0 -12
data/test/statsd_test.rb
CHANGED
@@ -1,166 +1,177 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'test_helper'
|
2
4
|
|
3
5
|
class StatsDTest < Minitest::Test
|
4
6
|
include StatsD::Instrument::Assertions
|
5
7
|
|
8
|
+
def teardown
|
9
|
+
StatsD.default_tags = nil
|
10
|
+
end
|
11
|
+
|
6
12
|
def test_statsd_passed_collections_to_backend
|
7
13
|
StatsD.backend.expects(:collect_metric).with(instance_of(StatsD::Instrument::Metric))
|
8
14
|
StatsD.increment('test')
|
9
15
|
end
|
10
16
|
|
11
17
|
def test_statsd_measure_with_explicit_value
|
12
|
-
|
13
|
-
metric = capture_statsd_call { result = StatsD.measure('values.foobar', 42) }
|
14
|
-
assert_equal metric, result
|
18
|
+
metric = capture_statsd_call { StatsD.measure('values.foobar', 42) }
|
15
19
|
assert_equal 'values.foobar', metric.name
|
16
20
|
assert_equal 42, metric.value
|
17
21
|
assert_equal :ms, metric.type
|
18
22
|
end
|
19
23
|
|
20
|
-
def test_statsd_measure_with_explicit_value_and_distribution_override
|
21
|
-
metric = capture_statsd_call { result = StatsD.measure('values.foobar', 42, as_dist: true) }
|
22
|
-
assert_equal :d, metric.type
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_statsd_measure_with_explicit_value_as_keyword_argument
|
26
|
-
result = nil
|
27
|
-
metric = capture_statsd_call { result = StatsD.measure('values.foobar', value: 42) }
|
28
|
-
assert_equal metric, result
|
29
|
-
assert_equal 'values.foobar', metric.name
|
30
|
-
assert_equal 42, metric.value
|
31
|
-
assert_equal :ms, metric.type
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_statsd_measure_with_explicit_value_keyword_and_distribution_override
|
35
|
-
metric = capture_statsd_call { result = StatsD.measure('values.foobar', value: 42, as_dist: true) }
|
36
|
-
assert_equal :d, metric.type
|
37
|
-
end
|
38
|
-
|
39
24
|
def test_statsd_measure_without_value_or_block
|
40
25
|
assert_raises(ArgumentError) { StatsD.measure('values.foobar', tags: 123) }
|
41
26
|
end
|
42
27
|
|
43
28
|
def test_statsd_measure_with_explicit_value_and_sample_rate
|
44
|
-
metric = capture_statsd_call { StatsD.measure('values.foobar', 42, :
|
29
|
+
metric = capture_statsd_call { StatsD.measure('values.foobar', 42, sample_rate: 0.1) }
|
45
30
|
assert_equal 0.1, metric.sample_rate
|
46
31
|
end
|
47
32
|
|
48
33
|
def test_statsd_measure_with_benchmarked_block_duration
|
49
|
-
|
34
|
+
Process.stubs(:clock_gettime).returns(5.0, 5.0 + 1.12)
|
50
35
|
metric = capture_statsd_call do
|
51
36
|
StatsD.measure('values.foobar') { 'foo' }
|
52
37
|
end
|
53
38
|
assert_equal 1120.0, metric.value
|
54
39
|
end
|
55
40
|
|
56
|
-
def test_statsd_measure_use_distribution_override_for_a_block
|
57
|
-
metric = capture_statsd_call do
|
58
|
-
StatsD.measure('values.foobar', as_dist: true) { 'foo' }
|
59
|
-
end
|
60
|
-
assert_equal :d, metric.type
|
61
|
-
end
|
62
|
-
|
63
41
|
def test_statsd_measure_returns_return_value_of_block
|
64
42
|
return_value = StatsD.measure('values.foobar') { 'sarah' }
|
65
43
|
assert_equal 'sarah', return_value
|
66
44
|
end
|
67
45
|
|
68
|
-
def
|
69
|
-
|
70
|
-
|
46
|
+
def test_statsd_measure_with_return_in_block_still_captures
|
47
|
+
Process.stubs(:clock_gettime).returns(5.0, 6.12)
|
48
|
+
result = nil
|
49
|
+
metric = capture_statsd_call do
|
50
|
+
lambda = -> do
|
51
|
+
StatsD.measure('values.foobar') { return 'from lambda' }
|
52
|
+
end
|
53
|
+
|
54
|
+
result = lambda.call
|
55
|
+
end
|
56
|
+
|
57
|
+
assert_equal 'from lambda', result
|
58
|
+
assert_equal 1120.0, metric.value
|
71
59
|
end
|
72
60
|
|
73
|
-
def
|
61
|
+
def test_statsd_measure_with_exception_in_block_still_captures
|
62
|
+
Process.stubs(:clock_gettime).returns(5.0, 6.12)
|
74
63
|
result = nil
|
75
|
-
metric = capture_statsd_call
|
76
|
-
|
64
|
+
metric = capture_statsd_call do
|
65
|
+
lambda = -> do
|
66
|
+
StatsD.measure('values.foobar') { raise 'from lambda' }
|
67
|
+
end
|
68
|
+
|
69
|
+
begin
|
70
|
+
result = lambda.call
|
71
|
+
rescue # rubocop:disable Lint/HandleExceptions:
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
assert_nil result
|
76
|
+
assert_equal 1120.0, metric.value
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_statsd_increment
|
80
|
+
metric = capture_statsd_call { StatsD.increment('values.foobar', 3) }
|
77
81
|
assert_equal :c, metric.type
|
78
82
|
assert_equal 'values.foobar', metric.name
|
79
83
|
assert_equal 3, metric.value
|
80
84
|
end
|
81
85
|
|
82
86
|
def test_statsd_increment_with_hash_argument
|
83
|
-
metric = capture_statsd_call { StatsD.increment('values.foobar', :
|
87
|
+
metric = capture_statsd_call { StatsD.increment('values.foobar', tags: ['test']) }
|
84
88
|
assert_equal StatsD.default_sample_rate, metric.sample_rate
|
85
89
|
assert_equal ['test'], metric.tags
|
86
90
|
assert_equal 1, metric.value
|
87
91
|
end
|
88
92
|
|
89
|
-
def test_statsd_increment_with_value_as_keyword_argument
|
90
|
-
metric = capture_statsd_call { StatsD.increment('values.foobar', :value => 2) }
|
91
|
-
assert_equal StatsD.default_sample_rate, metric.sample_rate
|
92
|
-
assert_equal 2, metric.value
|
93
|
-
end
|
94
|
-
|
95
|
-
def test_statsd_increment_with_multiple_arguments
|
96
|
-
metric = capture_statsd_call { StatsD.increment('values.foobar', 12, nil, ['test']) }
|
97
|
-
assert_equal StatsD.default_sample_rate, metric.sample_rate
|
98
|
-
assert_equal ['test'], metric.tags
|
99
|
-
assert_equal 12, metric.value
|
100
|
-
end
|
101
|
-
|
102
93
|
def test_statsd_gauge
|
103
|
-
|
104
|
-
metric = capture_statsd_call { result = StatsD.gauge('values.foobar', 12) }
|
105
|
-
assert_equal metric, result
|
94
|
+
metric = capture_statsd_call { StatsD.gauge('values.foobar', 12) }
|
106
95
|
assert_equal :g, metric.type
|
107
96
|
assert_equal 'values.foobar', metric.name
|
108
97
|
assert_equal 12, metric.value
|
109
98
|
end
|
110
99
|
|
111
|
-
def test_statsd_gauge_with_keyword_argument
|
112
|
-
result = nil
|
113
|
-
metric = capture_statsd_call { result = StatsD.gauge('values.foobar', value: 13) }
|
114
|
-
assert_equal metric, result
|
115
|
-
assert_equal :g, metric.type
|
116
|
-
assert_equal 'values.foobar', metric.name
|
117
|
-
assert_equal 13, metric.value
|
118
|
-
end
|
119
|
-
|
120
100
|
def test_statsd_gauge_without_value
|
121
101
|
assert_raises(ArgumentError) { StatsD.gauge('values.foobar', tags: 123) }
|
122
102
|
end
|
123
103
|
|
124
104
|
def test_statsd_set
|
125
|
-
|
126
|
-
metric = capture_statsd_call { result = StatsD.set('values.foobar', 'unique_identifier') }
|
127
|
-
assert_equal metric, result
|
105
|
+
metric = capture_statsd_call { StatsD.set('values.foobar', 'unique_identifier') }
|
128
106
|
assert_equal :s, metric.type
|
129
107
|
assert_equal 'values.foobar', metric.name
|
130
108
|
assert_equal 'unique_identifier', metric.value
|
131
109
|
end
|
132
110
|
|
133
111
|
def test_statsd_histogram
|
134
|
-
|
135
|
-
metric = capture_statsd_call { result = StatsD.histogram('values.foobar', 42) }
|
136
|
-
assert_equal metric, result
|
112
|
+
metric = capture_statsd_call { StatsD.histogram('values.foobar', 42) }
|
137
113
|
assert_equal :h, metric.type
|
138
114
|
assert_equal 'values.foobar', metric.name
|
139
115
|
assert_equal 42, metric.value
|
140
116
|
end
|
141
117
|
|
142
118
|
def test_statsd_distribution
|
143
|
-
|
144
|
-
metric = capture_statsd_call { result = StatsD.distribution('values.foobar', 42) }
|
145
|
-
assert_equal metric, result
|
119
|
+
metric = capture_statsd_call { StatsD.distribution('values.foobar', 42) }
|
146
120
|
assert_equal :d, metric.type
|
147
121
|
assert_equal 'values.foobar', metric.name
|
148
122
|
assert_equal 42, metric.value
|
149
123
|
end
|
150
124
|
|
151
125
|
def test_statsd_distribution_with_benchmarked_block_duration
|
152
|
-
|
126
|
+
Process.stubs(:clock_gettime).returns(5.0, 5.0 + 1.12)
|
153
127
|
metric = capture_statsd_call do
|
154
|
-
StatsD.distribution('values.foobar') { 'foo' }
|
128
|
+
result = StatsD.distribution('values.foobar') { 'foo' }
|
129
|
+
assert_equal 'foo', result
|
155
130
|
end
|
156
131
|
assert_equal :d, metric.type
|
157
132
|
assert_equal 1120.0, metric.value
|
158
133
|
end
|
159
134
|
|
135
|
+
def test_statsd_distribution_with_return_in_block_still_captures
|
136
|
+
Process.stubs(:clock_gettime).returns(5.0, 5.0 + 1.12)
|
137
|
+
result = nil
|
138
|
+
metric = capture_statsd_call do
|
139
|
+
lambda = -> do
|
140
|
+
StatsD.distribution('values.foobar') { return 'from lambda' }
|
141
|
+
flunk("This code should not be reached")
|
142
|
+
end
|
143
|
+
|
144
|
+
result = lambda.call
|
145
|
+
end
|
146
|
+
|
147
|
+
assert_equal 'from lambda', result
|
148
|
+
assert_equal :d, metric.type
|
149
|
+
assert_equal 1120.0, metric.value
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_statsd_distribution_with_exception_in_block_still_captures
|
153
|
+
Process.stubs(:clock_gettime).returns(5.0, 5.0 + 1.12)
|
154
|
+
result = nil
|
155
|
+
metric = capture_statsd_call do
|
156
|
+
lambda = -> do
|
157
|
+
StatsD.distribution('values.foobar') { raise 'from lambda' }
|
158
|
+
end
|
159
|
+
|
160
|
+
begin
|
161
|
+
result = lambda.call
|
162
|
+
rescue # rubocop:disable Lint/HandleExceptions
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
assert_nil result
|
167
|
+
assert_equal :d, metric.type
|
168
|
+
assert_equal 1120.0, metric.value
|
169
|
+
end
|
170
|
+
|
160
171
|
def test_statsd_distribution_with_block_and_options
|
161
|
-
|
172
|
+
Process.stubs(:clock_gettime).returns(5.0, 5.0 + 1.12)
|
162
173
|
metric = capture_statsd_call do
|
163
|
-
StatsD.distribution('values.foobar', :
|
174
|
+
StatsD.distribution('values.foobar', tags: ['test'], sample_rate: 0.9) { 'foo' }
|
164
175
|
end
|
165
176
|
assert_equal 1120.0, metric.value
|
166
177
|
assert_equal 'values.foobar', metric.name
|
@@ -179,14 +190,37 @@ class StatsDTest < Minitest::Test
|
|
179
190
|
end
|
180
191
|
|
181
192
|
def test_statsd_key_value
|
182
|
-
|
183
|
-
metric = capture_statsd_call { result = StatsD.key_value('values.foobar', 42) }
|
184
|
-
assert_equal metric, result
|
193
|
+
metric = capture_statsd_call { StatsD.key_value('values.foobar', 42) }
|
185
194
|
assert_equal :kv, metric.type
|
186
195
|
assert_equal 'values.foobar', metric.name
|
187
196
|
assert_equal 42, metric.value
|
188
197
|
end
|
189
198
|
|
199
|
+
def test_statsd_durarion_returns_time_in_seconds
|
200
|
+
duration = StatsD::Instrument.duration {}
|
201
|
+
assert_kind_of Float, duration
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_statsd_durarion_does_not_swallow_exceptions
|
205
|
+
assert_raises(RuntimeError) do
|
206
|
+
StatsD::Instrument.duration { raise "Foo" }
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_statsd_default_tags_get_normalized
|
211
|
+
StatsD.default_tags = { first_tag: 'first_value', second_tag: 'second_value' }
|
212
|
+
assert_equal ['first_tag:first_value', 'second_tag:second_value'], StatsD.default_tags
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_name_prefix
|
216
|
+
StatsD.stubs(:prefix).returns('prefix')
|
217
|
+
m = capture_statsd_call { StatsD.increment('counter') }
|
218
|
+
assert_equal 'prefix.counter', m.name
|
219
|
+
|
220
|
+
m = capture_statsd_call { StatsD.increment('counter', no_prefix: true) }
|
221
|
+
assert_equal 'counter', m.name
|
222
|
+
end
|
223
|
+
|
190
224
|
protected
|
191
225
|
|
192
226
|
def capture_statsd_call(&block)
|
data/test/test_helper.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
ENV['ENV'] = 'test'
|
2
4
|
|
3
5
|
require 'minitest/autorun'
|
@@ -7,4 +9,13 @@ require 'set'
|
|
7
9
|
require 'logger'
|
8
10
|
require 'statsd-instrument'
|
9
11
|
|
10
|
-
|
12
|
+
require_relative 'helpers/rubocop_helper'
|
13
|
+
|
14
|
+
module StatsD::Instrument
|
15
|
+
def self.strict_mode_enabled?
|
16
|
+
StatsD::Instrument.const_defined?(:Strict) &&
|
17
|
+
StatsD.singleton_class.ancestors.include?(StatsD::Instrument::Strict)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
StatsD.logger = Logger.new(File::NULL)
|
data/test/udp_backend_test.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'test_helper'
|
2
4
|
|
3
5
|
class UDPBackendTest < Minitest::Test
|
@@ -76,7 +78,7 @@ class UDPBackendTest < Minitest::Test
|
|
76
78
|
StatsD.histogram('fooh', 42.4)
|
77
79
|
end
|
78
80
|
|
79
|
-
|
81
|
+
def test_distribution_syntax_on_datadog
|
80
82
|
@backend.implementation = :datadog
|
81
83
|
@backend.expects(:write_packet).with('fooh:42.4|d')
|
82
84
|
StatsD.distribution('fooh', 42.4)
|
@@ -84,20 +86,25 @@ class UDPBackendTest < Minitest::Test
|
|
84
86
|
|
85
87
|
def test_event_on_datadog
|
86
88
|
@backend.implementation = :datadog
|
87
|
-
@backend.expects(:write_packet).with('_e{4,3}:fooh|baz|h:localhost
|
88
|
-
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"])
|
89
91
|
end
|
90
92
|
|
91
93
|
def test_event_on_datadog_escapes_newlines
|
92
94
|
@backend.implementation = :datadog
|
93
|
-
@backend.expects(:write_packet).with(
|
94
|
-
StatsD.event(
|
95
|
+
@backend.expects(:write_packet).with("_e{8,5}:fooh\\n\\n|baz\\n")
|
96
|
+
StatsD.event("fooh\n\n", "baz\n")
|
95
97
|
end
|
96
98
|
|
97
99
|
def test_event_on_datadog_ignores_invalid_metadata
|
98
100
|
@backend.implementation = :datadog
|
99
|
-
|
100
|
-
|
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
|
101
108
|
end
|
102
109
|
|
103
110
|
def test_event_warns_when_not_using_datadog
|
@@ -109,14 +116,26 @@ class UDPBackendTest < Minitest::Test
|
|
109
116
|
|
110
117
|
def test_service_check_on_datadog
|
111
118
|
@backend.implementation = :datadog
|
112
|
-
@backend.expects(:write_packet).with('_sc|fooh|
|
113
|
-
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"])
|
114
121
|
end
|
115
122
|
|
116
123
|
def test_service_check_on_datadog_ignores_invalid_metadata
|
117
124
|
@backend.implementation = :datadog
|
118
|
-
|
119
|
-
|
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'])
|
120
139
|
end
|
121
140
|
|
122
141
|
def test_service_check_warns_when_not_using_datadog
|
@@ -146,11 +165,19 @@ class UDPBackendTest < Minitest::Test
|
|
146
165
|
StatsD.key_value('fooy', 42)
|
147
166
|
end
|
148
167
|
|
168
|
+
# For key_value metrics (only supported by statsite), the sample rate
|
169
|
+
# part of the datagram format is (ab)used to be set to a timestamp instead.
|
170
|
+
# Changing that to `sample_rate: timestamp` does not make sense, so we
|
171
|
+
# disable the rubocop rule for positional arguments for now,
|
172
|
+
# until we figure out how we want to handle this.
|
173
|
+
|
174
|
+
# rubocop:disable StatsD/PositionalArguments
|
149
175
|
def test_supports_key_value_with_timestamp_on_statsite
|
150
176
|
@backend.implementation = :statsite
|
151
177
|
@backend.expects(:write_packet).with("fooy:42|kv|@123456\n")
|
152
178
|
StatsD.key_value('fooy', 42, 123456)
|
153
179
|
end
|
180
|
+
# rubocop:enable StatsD/PositionalArguments
|
154
181
|
|
155
182
|
def test_warn_when_using_key_value_and_not_on_statsite
|
156
183
|
@backend.implementation = :other
|
@@ -183,31 +210,6 @@ class UDPBackendTest < Minitest::Test
|
|
183
210
|
StatsD.increment('fail')
|
184
211
|
end
|
185
212
|
|
186
|
-
def test_synchronize_in_exit_handler_handles_thread_error_and_exits_cleanly
|
187
|
-
pid = fork do
|
188
|
-
Signal.trap('TERM') do
|
189
|
-
$sent_packet = false
|
190
|
-
|
191
|
-
class << @backend.socket
|
192
|
-
def send(command, *args)
|
193
|
-
$sent_packet = true if command == 'exiting:1|c'
|
194
|
-
command.length
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
StatsD.increment('exiting')
|
199
|
-
Process.exit!($sent_packet)
|
200
|
-
end
|
201
|
-
|
202
|
-
sleep 100
|
203
|
-
end
|
204
|
-
|
205
|
-
Process.kill('TERM', pid)
|
206
|
-
Process.waitpid(pid)
|
207
|
-
|
208
|
-
assert $?.success?, 'socket did not write on exit'
|
209
|
-
end
|
210
|
-
|
211
213
|
def test_socket_error_should_invalidate_socket
|
212
214
|
seq = sequence('fail_then_succeed')
|
213
215
|
|
@@ -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
|