statsd-instrument 2.9.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +14 -21
  3. data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +15 -15
  4. data/CHANGELOG.md +44 -0
  5. data/benchmark/send-metrics-to-dev-null-log +5 -2
  6. data/benchmark/send-metrics-to-local-udp-receiver +8 -6
  7. data/lib/statsd/instrument.rb +79 -146
  8. data/lib/statsd/instrument/assertions.rb +12 -24
  9. data/lib/statsd/instrument/client.rb +125 -35
  10. data/lib/statsd/instrument/environment.rb +1 -23
  11. data/lib/statsd/instrument/expectation.rb +12 -16
  12. data/lib/statsd/instrument/helpers.rb +1 -30
  13. data/lib/statsd/instrument/matchers.rb +0 -1
  14. data/lib/statsd/instrument/railtie.rb +0 -4
  15. data/lib/statsd/instrument/strict.rb +12 -123
  16. data/lib/statsd/instrument/version.rb +1 -1
  17. data/test/assertions_test.rb +21 -9
  18. data/test/client_test.rb +11 -0
  19. data/test/environment_test.rb +1 -37
  20. data/test/integration_test.rb +9 -24
  21. data/test/statsd_instrumentation_test.rb +25 -50
  22. data/test/statsd_test.rb +6 -31
  23. data/test/test_helper.rb +1 -1
  24. metadata +2 -24
  25. data/benchmark/datagram-client +0 -40
  26. data/lib/statsd/instrument/backend.rb +0 -18
  27. data/lib/statsd/instrument/backends/capture_backend.rb +0 -32
  28. data/lib/statsd/instrument/backends/logger_backend.rb +0 -20
  29. data/lib/statsd/instrument/backends/null_backend.rb +0 -9
  30. data/lib/statsd/instrument/backends/udp_backend.rb +0 -152
  31. data/lib/statsd/instrument/legacy_client.rb +0 -301
  32. data/lib/statsd/instrument/metric.rb +0 -155
  33. data/test/assertions_on_legacy_client_test.rb +0 -344
  34. data/test/capture_backend_test.rb +0 -26
  35. data/test/compatibility/dogstatsd_datagram_compatibility_test.rb +0 -161
  36. data/test/deprecations_test.rb +0 -139
  37. data/test/logger_backend_test.rb +0 -22
  38. data/test/metric_test.rb +0 -47
  39. data/test/udp_backend_test.rb +0 -228
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class CaptureBackendTest < Minitest::Test
6
- def setup
7
- @backend = StatsD::Instrument::Backends::CaptureBackend.new
8
- @metric1 = StatsD::Instrument::Metric.new(type: :c, name: 'mock.counter')
9
- @metric2 = StatsD::Instrument::Metric.new(type: :ms, name: 'mock.measure', value: 123)
10
- end
11
-
12
- def test_collecting_metric
13
- assert @backend.collected_metrics.empty?
14
- @backend.collect_metric(@metric1)
15
- @backend.collect_metric(@metric2)
16
- assert_equal [@metric1, @metric2], @backend.collected_metrics
17
- end
18
-
19
- def test_reset
20
- @backend.collect_metric(@metric1)
21
- @backend.reset
22
- assert @backend.collected_metrics.empty?
23
- @backend.collect_metric(@metric2)
24
- assert_equal [@metric2], @backend.collected_metrics
25
- end
26
- end
@@ -1,161 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- module Compatibility
6
- class DogStatsDDatagramCompatibilityTest < Minitest::Test
7
- def setup
8
- StatsD::Instrument::UDPSink.any_instance.stubs(:sample?).returns(true)
9
- StatsD::Instrument::Backends::UDPBackend.any_instance.stubs(:rand).returns(0)
10
-
11
- @server = UDPSocket.new
12
- @server.bind('localhost', 0)
13
- @host = @server.addr[2]
14
- @port = @server.addr[1]
15
- end
16
-
17
- def teardown
18
- @server.close
19
- end
20
-
21
- def test_increment_compatibility
22
- assert_equal_datagrams { |client| client.increment('counter') }
23
- assert_equal_datagrams { |client| client.increment('counter', no_prefix: true) }
24
- assert_equal_datagrams { |client| client.increment('counter', 12) }
25
- assert_equal_datagrams { |client| client.increment('counter', sample_rate: 0.1) }
26
- assert_equal_datagrams { |client| client.increment('counter', tags: ['foo', 'bar']) }
27
- assert_equal_datagrams { |client| client.increment('counter', tags: { foo: 'bar' }) }
28
- assert_equal_datagrams { |client| client.increment('counter', sample_rate: 0.1, tags: ['quc']) }
29
- end
30
-
31
- def test_measure_compatibility
32
- assert_equal_datagrams { |client| client.measure('timing', 12.34) }
33
- assert_equal_datagrams { |client| client.measure('timing', 0.01, no_prefix: true) }
34
- assert_equal_datagrams { |client| client.measure('timing', 0.12, sample_rate: 0.1) }
35
- assert_equal_datagrams { |client| client.measure('timing', 0.12, tags: ['foo', 'bar']) }
36
- end
37
-
38
- def test_measure_with_block_compatibility
39
- Process.stubs(:clock_gettime).with(Process::CLOCK_MONOTONIC).returns(12.1)
40
- assert_equal_datagrams do |client|
41
- return_value = client.measure('timing', tags: ['foo'], sample_rate: 0.1) { 'foo' }
42
- assert_equal 'foo', return_value
43
- end
44
- end
45
-
46
- def test_gauge_compatibility
47
- assert_equal_datagrams { |client| client.gauge('current', 1234) }
48
- assert_equal_datagrams { |client| client.gauge('current', 1234, no_prefix: true) }
49
- assert_equal_datagrams { |client| client.gauge('current', 1234, sample_rate: 0.1) }
50
- assert_equal_datagrams { |client| client.gauge('current', 1234, tags: ['foo', 'bar']) }
51
- assert_equal_datagrams { |client| client.gauge('current', 1234, tags: { foo: 'bar' }) }
52
- assert_equal_datagrams { |client| client.gauge('current', 1234, sample_rate: 0.1, tags: ['quc']) }
53
- end
54
-
55
- def test_set_compatibility
56
- assert_equal_datagrams { |client| client.set('unique', 'foo') }
57
- assert_equal_datagrams { |client| client.set('unique', 'foo', no_prefix: true) }
58
- assert_equal_datagrams { |client| client.set('unique', 'foo', sample_rate: 0.1) }
59
- assert_equal_datagrams { |client| client.set('unique', '1234', tags: ['foo', 'bar']) }
60
- assert_equal_datagrams { |client| client.set('unique', '1234', tags: { foo: 'bar' }) }
61
- assert_equal_datagrams { |client| client.set('unique', '1234', sample_rate: 0.1, tags: ['quc']) }
62
- end
63
-
64
- def test_histogram_compatibility
65
- assert_equal_datagrams { |client| client.histogram('sample', 12.44) }
66
- assert_equal_datagrams { |client| client.histogram('sample', 12.44, no_prefix: true) }
67
- assert_equal_datagrams { |client| client.histogram('sample', 12.44, sample_rate: 0.1) }
68
- assert_equal_datagrams { |client| client.histogram('sample', 12.44, tags: ['foo', 'bar']) }
69
- assert_equal_datagrams { |client| client.histogram('sample', 12.44, tags: { foo: 'bar' }) }
70
- assert_equal_datagrams { |client| client.histogram('sample', 12.44, sample_rate: 0.1, tags: ['quc']) }
71
- end
72
-
73
- def test_distribution_compatibility
74
- assert_equal_datagrams { |client| client.distribution('sample', 12.44) }
75
- assert_equal_datagrams { |client| client.distribution('sample', 12.44, no_prefix: true) }
76
- assert_equal_datagrams { |client| client.distribution('sample', 12.44, sample_rate: 0.1) }
77
- assert_equal_datagrams { |client| client.distribution('sample', 12.44, tags: ['foo', 'bar']) }
78
- assert_equal_datagrams { |client| client.distribution('sample', 12.44, tags: { foo: 'bar' }) }
79
- assert_equal_datagrams { |client| client.distribution('sample', 12.44, sample_rate: 0.1, tags: ['quc']) }
80
- end
81
-
82
- def test_distribution_with_block_compatibility
83
- Process.stubs(:clock_gettime).with(Process::CLOCK_MONOTONIC).returns(12.1)
84
- assert_equal_datagrams do |client|
85
- return_value = client.distribution('timing', tags: ['foo'], sample_rate: 0.1) { 'foo' }
86
- assert_equal 'foo', return_value
87
- end
88
- end
89
-
90
- def test_service_check_compatibility
91
- assert_equal_datagrams { |client| client.service_check('service', 0) }
92
- assert_equal_datagrams { |client| client.service_check('service', :critical, no_prefix: true) }
93
- assert_equal_datagrams { |client| client.event('foo', "bar\nbaz") }
94
- assert_equal_datagrams do |client|
95
- client.service_check('service', "ok", timestamp: Time.parse('2019-09-09T04:22:17Z'),
96
- hostname: 'localhost', tags: ['foo'], message: 'bar')
97
- end
98
- end
99
-
100
- def test_event_compatibility
101
- assert_equal_datagrams { |client| client.event('foo', "bar\nbaz") }
102
- assert_equal_datagrams { |client| client.event('foo', "bar\nbaz", no_prefix: true) }
103
- assert_equal_datagrams do |client|
104
- client.event('Something happened', "And it's not good", timestamp: Time.parse('2019-09-09T04:22:17Z'),
105
- hostname: 'localhost', tags: ['foo'], alert_type: 'warning', priority: 'low',
106
- aggregation_key: 'foo', source_type_name: 'logs')
107
- end
108
- end
109
-
110
- private
111
-
112
- MODES = [:normal, :with_prefix, :with_default_tags]
113
-
114
- def assert_equal_datagrams(&block)
115
- MODES.each do |mode|
116
- legacy_datagram = with_legacy_client(mode) { |client| read_datagram(client, &block) }
117
- new_datagram = with_new_client(mode) { |client| read_datagram(client, &block) }
118
-
119
- assert_equal legacy_datagram, new_datagram, "The datagrams emitted were not the same in #{mode} mode"
120
- end
121
- end
122
-
123
- def with_legacy_client(mode)
124
- old_prefix = StatsD.prefix
125
- StatsD.prefix = 'prefix' if mode == :with_prefix
126
-
127
- old_default_tags = StatsD.default_tags
128
- StatsD.default_tags = { key: 'value' } if mode == :with_default_tags
129
-
130
- old_backend = StatsD.backend
131
- new_backend = StatsD::Instrument::Backends::UDPBackend.new("#{@host}:#{@port}", :datadog)
132
- StatsD.backend = new_backend
133
-
134
- yield(StatsD)
135
- ensure
136
- new_backend.socket.close if new_backend&.socket
137
- StatsD.backend = old_backend
138
- StatsD.prefix = old_prefix
139
- StatsD.default_tags = old_default_tags
140
- end
141
-
142
- def with_new_client(mode)
143
- prefix = mode == :with_prefix ? 'prefix' : nil
144
- default_tags = mode == :with_default_tags ? { key: 'value' } : nil
145
- client = StatsD::Instrument::Client.new(
146
- sink: StatsD::Instrument::UDPSink.new(@host, @port),
147
- datagram_builder_class: StatsD::Instrument::DogStatsDDatagramBuilder,
148
- prefix: prefix,
149
- default_tags: default_tags
150
- )
151
-
152
- yield(client)
153
- end
154
-
155
- def read_datagram(client)
156
- yield(client)
157
- data, _origin = @server.recvfrom(100)
158
- data
159
- end
160
- end
161
- end
@@ -1,139 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class DeprecationsTest < Minitest::Test
6
- unless StatsD::Instrument.strict_mode_enabled?
7
- class InstrumentedClass
8
- extend StatsD::Instrument
9
- def foo; end
10
- statsd_count :foo, 'frequency', 0.5, ['tag'] # rubocop:disable StatsD/MetaprogrammingPositionalArguments
11
- statsd_measure :foo, 'latency', as_dist: true # rubocop:disable StatsD/MeasureAsDistArgument
12
- statsd_count_success :foo, 'frequency', prefix: 'foo' # rubocop:disable StatsD/MetricPrefixArgument
13
- end
14
- end
15
-
16
- include StatsD::Instrument::Assertions
17
-
18
- def setup
19
- skip("Deprecation are not supported in strict mode") if StatsD::Instrument.strict_mode_enabled?
20
- end
21
-
22
- def test__deprecated__metaprogramming_method_with_positional_arguments
23
- metrics = capture_statsd_calls { InstrumentedClass.new.foo }
24
- metric = metrics[0]
25
- assert_equal :c, metric.type
26
- assert_equal 'frequency', metric.name
27
- assert_equal 1, metric.value
28
- assert_equal 0.5, metric.sample_rate
29
- assert_equal ["tag"], metric.tags
30
- end
31
-
32
- def test__deprecated__metaprogramming_statsd_measure_with_as_dist
33
- metrics = capture_statsd_calls { InstrumentedClass.new.foo }
34
- metric = metrics[1]
35
- assert_equal :d, metric.type
36
- assert_equal 'latency', metric.name
37
- end
38
-
39
- def test__deprecated__metaprogramming_statsd_count_with_prefix
40
- metrics = capture_statsd_calls { InstrumentedClass.new.foo }
41
- metric = metrics[2]
42
- assert_equal :c, metric.type
43
- assert_equal 'foo.frequency.success', metric.name
44
- end
45
-
46
- # rubocop:disable StatsD/MetricValueKeywordArgument
47
- def test__deprecated__statsd_measure_with_explicit_value_as_keyword_argument
48
- metric = capture_statsd_call { StatsD.measure('values.foobar', value: 42) }
49
- assert_equal 'values.foobar', metric.name
50
- assert_equal 42, metric.value
51
- assert_equal :ms, metric.type
52
- end
53
-
54
- # rubocop:disable StatsD/MeasureAsDistArgument
55
- def test__deprecated__statsd_measure_with_explicit_value_keyword_and_distribution_override
56
- metric = capture_statsd_call { StatsD.measure('values.foobar', value: 42, as_dist: true) }
57
- assert_equal 42, metric.value
58
- assert_equal :d, metric.type
59
- end
60
- # rubocop:enable StatsD/MeasureAsDistArgument
61
-
62
- def test__deprecated__statsd_increment_with_value_as_keyword_argument
63
- metric = capture_statsd_call { StatsD.increment('values.foobar', value: 2) }
64
- assert_equal StatsD.default_sample_rate, metric.sample_rate
65
- assert_equal 2, metric.value
66
- end
67
-
68
- def test__deprecated__statsd_gauge_with_keyword_argument
69
- metric = capture_statsd_call { StatsD.gauge('values.foobar', value: 13) }
70
- assert_equal :g, metric.type
71
- assert_equal 'values.foobar', metric.name
72
- assert_equal 13, metric.value
73
- end
74
- # rubocop:enable StatsD/MetricValueKeywordArgument
75
-
76
- # rubocop:disable StatsD/MetricReturnValue
77
- def test__deprecated__statsd_increment_returns_metric_instance
78
- metric = StatsD.increment('key')
79
- assert_kind_of StatsD::Instrument::Metric, metric
80
- assert_equal 'key', metric.name
81
- assert_equal :c, metric.type
82
- assert_equal 1, metric.value
83
- end
84
- # rubocop:enable StatsD/MetricReturnValue
85
-
86
- # rubocop:disable StatsD/PositionalArguments
87
- def test__deprecated__statsd_increment_with_positional_argument_for_tags
88
- metric = capture_statsd_call { StatsD.increment('values.foobar', 12, nil, ['test']) }
89
- assert_equal StatsD.default_sample_rate, metric.sample_rate
90
- assert_equal ['test'], metric.tags
91
- assert_equal 12, metric.value
92
- assert_equal StatsD.default_sample_rate, metric.sample_rate
93
- end
94
- # rubocop:enable StatsD/PositionalArguments
95
-
96
- # rubocop:disable StatsD/MeasureAsDistArgument
97
- def test__deprecated__statsd_measure_with_explicit_value_and_distribution_override
98
- metric = capture_statsd_call { StatsD.measure('values.foobar', 42, as_dist: true) }
99
- assert_equal :d, metric.type
100
- end
101
-
102
- def test__deprecated__statsd_measure_use_distribution_override_for_a_block
103
- metric = capture_statsd_call do
104
- StatsD.measure('values.foobar', as_dist: true) { 'foo' }
105
- end
106
- assert_equal :d, metric.type
107
- end
108
-
109
- def test__deprecated__statsd_measure_as_distribution_returns_return_value_of_block_even_if_nil
110
- return_value = StatsD.measure('values.foobar', as_dist: true) { nil }
111
- assert_nil return_value
112
- end
113
- # rubocop:enable StatsD/MeasureAsDistArgument
114
-
115
- # rubocop:disable StatsD/MetricPrefixArgument
116
- def test__deprecated__override_name_prefix
117
- m = capture_statsd_call { StatsD.increment('counter', prefix: "foobar") }
118
- assert_equal 'foobar.counter', m.name
119
-
120
- m = capture_statsd_call { StatsD.increment('counter', prefix: "foobar", no_prefix: true) }
121
- assert_equal 'counter', m.name
122
- end
123
- # rubocop:enable StatsD/MetricPrefixArgument
124
-
125
- def test__deprecated__statsd_key_value
126
- metric = capture_statsd_call { StatsD.key_value('values.foobar', 42) }
127
- assert_equal :kv, metric.type
128
- assert_equal 'values.foobar', metric.name
129
- assert_equal 42, metric.value
130
- end
131
-
132
- protected
133
-
134
- def capture_statsd_call(&block)
135
- metrics = capture_statsd_calls(&block)
136
- assert_equal 1, metrics.length
137
- metrics.first
138
- end
139
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class LoggerBackendTest < Minitest::Test
6
- def setup
7
- logger = Logger.new(@io = StringIO.new)
8
- logger.formatter = lambda { |_, _, _, msg| "#{msg}\n" }
9
- @backend = StatsD::Instrument::Backends::LoggerBackend.new(logger)
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)
12
- end
13
-
14
- def test_logs_metrics
15
- @backend.collect_metric(@metric1)
16
- @backend.collect_metric(@metric2)
17
- assert_equal <<~LOG, @io.string
18
- [StatsD] mock.counter:1|c|#a:b,c:d
19
- [StatsD] mock.measure:123|ms|@0.3
20
- LOG
21
- end
22
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class MetricTest < Minitest::Test
6
- def test_required_arguments
7
- assert_raises(ArgumentError) { StatsD::Instrument::Metric.new(type: :c) }
8
- assert_raises(ArgumentError) { StatsD::Instrument::Metric.new(name: 'test') }
9
- assert_raises(ArgumentError) { StatsD::Instrument::Metric.new(type: :ms, name: 'test') }
10
- end
11
-
12
- def test_default_values
13
- m = StatsD::Instrument::Metric.new(type: :c, name: 'counter')
14
- assert_equal 1, m.value
15
- assert_equal StatsD.default_sample_rate, m.sample_rate
16
- assert m.tags.nil?
17
- end
18
-
19
- def test_bad_metric_name
20
- m = StatsD::Instrument::Metric.new(type: :c, name: 'my:metric')
21
- assert_equal 'my_metric', m.name
22
- m = StatsD::Instrument::Metric.new(type: :c, name: 'my|metric')
23
- assert_equal 'my_metric', m.name
24
- m = StatsD::Instrument::Metric.new(type: :c, name: 'my@metric')
25
- assert_equal 'my_metric', m.name
26
- end
27
-
28
- def test_handle_bad_tags
29
- assert_equal ['ignored'], StatsD::Instrument::Metric.normalize_tags(['igno|red'])
30
- assert_equal ['lol::class:omg::lol'], StatsD::Instrument::Metric.normalize_tags("lol::class" => "omg::lol")
31
- end
32
-
33
- def test_rewrite_tags_provided_as_hash
34
- assert_equal ['tag:value'], StatsD::Instrument::Metric.normalize_tags(tag: 'value')
35
- assert_equal ['tag1:v1', 'tag2:v2'], StatsD::Instrument::Metric.normalize_tags(tag1: 'v1', tag2: 'v2')
36
- end
37
-
38
- def test_default_tags
39
- StatsD.legacy_singleton_client.stubs(:default_tags).returns(['default_tag:default_value'])
40
- m = StatsD::Instrument::Metric.new(type: :c, name: 'counter', tags: { tag: 'value' })
41
- assert_equal ['tag:value', 'default_tag:default_value'], m.tags
42
-
43
- StatsD.legacy_singleton_client.stubs(:default_tags).returns(['tag:value'])
44
- m = StatsD::Instrument::Metric.new(type: :c, name: 'counter', tags: { tag: 'value' })
45
- assert_equal ['tag:value', 'tag:value'], m.tags # we don't care about duplicates
46
- end
47
- end
@@ -1,228 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class UDPBackendTest < Minitest::Test
6
- def setup
7
- StatsD.legacy_singleton_client.stubs(:backend).returns(@backend = StatsD::Instrument::Backends::UDPBackend.new)
8
- @backend.stubs(:rand).returns(0.0)
9
-
10
- UDPSocket.stubs(:new).returns(@socket = mock('socket'))
11
- @socket.stubs(:connect)
12
- @socket.stubs(:send).returns(1)
13
-
14
- StatsD.stubs(:logger).returns(@logger = mock('logger'))
15
- end
16
-
17
- def test_changing_host_or_port_should_create_new_socket
18
- @socket.expects(:connect).with('localhost', 1234).once
19
- @socket.expects(:connect).with('localhost', 2345).once
20
- @socket.expects(:connect).with('127.0.0.1', 2345).once
21
-
22
- @backend.server = "localhost:1234"
23
- @backend.socket
24
-
25
- @backend.port = 2345
26
- @backend.socket
27
-
28
- @backend.host = '127.0.0.1'
29
- @backend.socket
30
- end
31
-
32
- def test_collect_respects_sampling_rate
33
- @socket.expects(:send).once.returns(1)
34
- metric = StatsD::Instrument::Metric.new(type: :c, name: 'test', sample_rate: 0.5)
35
-
36
- @backend.stubs(:rand).returns(0.4)
37
- @backend.collect_metric(metric)
38
-
39
- @backend.stubs(:rand).returns(0.6)
40
- @backend.collect_metric(metric)
41
- end
42
-
43
- def test_support_counter_syntax
44
- @backend.expects(:write_packet).with('counter:1|c').once
45
- StatsD.increment('counter', sample_rate: 1.0)
46
-
47
- @backend.expects(:write_packet).with('counter:1|c|@0.5').once
48
- StatsD.increment('counter', sample_rate: 0.5)
49
- end
50
-
51
- def test_supports_gauge_syntax
52
- @backend.expects(:write_packet).with('fooy:1.23|g')
53
- StatsD.gauge('fooy', 1.23)
54
-
55
- @backend.expects(:write_packet).with('fooy:42|g|@0.01')
56
- StatsD.gauge('fooy', 42, sample_rate: 0.01)
57
- end
58
-
59
- def test_supports_set_syntax
60
- @backend.expects(:write_packet).with('unique:10.0.0.10|s')
61
- StatsD.set('unique', '10.0.0.10')
62
-
63
- @backend.expects(:write_packet).with('unique:10.0.0.10|s|@0.01')
64
- StatsD.set('unique', '10.0.0.10', sample_rate: 0.01)
65
- end
66
-
67
- def test_support_measure_syntax
68
- @backend.expects(:write_packet).with('duration:1.23|ms')
69
- StatsD.measure('duration', 1.23)
70
-
71
- @backend.expects(:write_packet).with('duration:0.42|ms|@0.01')
72
- StatsD.measure('duration', 0.42, sample_rate: 0.01)
73
- end
74
-
75
- def test_histogram_syntax_on_datadog
76
- @backend.implementation = :datadog
77
- @backend.expects(:write_packet).with('fooh:42.4|h')
78
- StatsD.histogram('fooh', 42.4)
79
- end
80
-
81
- def test_distribution_syntax_on_datadog
82
- @backend.implementation = :datadog
83
- @backend.expects(:write_packet).with('fooh:42.4|d')
84
- StatsD.distribution('fooh', 42.4)
85
- end
86
-
87
- def test_event_on_datadog
88
- @backend.implementation = :datadog
89
- @backend.expects(:write_packet).with('_e{4,3}:fooh|baz|h:localhost|#foo')
90
- StatsD.event('fooh', 'baz', hostname: 'localhost', tags: ["foo"])
91
- end
92
-
93
- def test_event_on_datadog_escapes_newlines
94
- @backend.implementation = :datadog
95
- @backend.expects(:write_packet).with("_e{8,5}:fooh\\n\\n|baz\\n")
96
- StatsD.event("fooh\n\n", "baz\n")
97
- end
98
-
99
- def test_event_on_datadog_ignores_invalid_metadata
100
- @backend.implementation = :datadog
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
108
- end
109
-
110
- def test_event_warns_when_not_using_datadog
111
- @backend.implementation = :other
112
- @backend.expects(:write_packet).never
113
- @logger.expects(:warn)
114
- StatsD.event('fooh', 'bar')
115
- end
116
-
117
- def test_service_check_on_datadog
118
- @backend.implementation = :datadog
119
- @backend.expects(:write_packet).with('_sc|fooh|0|h:localhost|#foo')
120
- StatsD.service_check('fooh', 0, hostname: 'localhost', tags: ["foo"])
121
- end
122
-
123
- def test_service_check_on_datadog_ignores_invalid_metadata
124
- @backend.implementation = :datadog
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'])
139
- end
140
-
141
- def test_service_check_warns_when_not_using_datadog
142
- @backend.implementation = :other
143
- @backend.expects(:write_packet).never
144
- @logger.expects(:warn)
145
- StatsD.service_check('fooh', 'bar')
146
- end
147
-
148
- def test_histogram_warns_if_not_using_datadog
149
- @backend.implementation = :other
150
- @backend.expects(:write_packet).never
151
- @logger.expects(:warn)
152
- StatsD.histogram('fooh', 42.4)
153
- end
154
-
155
- def test_distribution_warns_if_not_using_datadog
156
- @backend.implementation = :other
157
- @backend.expects(:write_packet).never
158
- @logger.expects(:warn)
159
- StatsD.distribution('fooh', 42.4)
160
- end
161
-
162
- def test_supports_key_value_syntax_on_statsite
163
- skip if StatsD::Instrument.strict_mode_enabled?
164
- @backend.implementation = :statsite
165
- @backend.expects(:write_packet).with("fooy:42|kv\n")
166
- StatsD.key_value('fooy', 42)
167
- end
168
-
169
- # For key_value metrics (only supported by statsite), the sample rate
170
- # part of the datagram format is (ab)used to be set to a timestamp instead.
171
- # Changing that to `sample_rate: timestamp` does not make sense, so we
172
- # disable the rubocop rule for positional arguments for now,
173
- # until we figure out how we want to handle this.
174
-
175
- # rubocop:disable StatsD/PositionalArguments
176
- def test_supports_key_value_with_timestamp_on_statsite
177
- skip if StatsD::Instrument.strict_mode_enabled?
178
- @backend.implementation = :statsite
179
- @backend.expects(:write_packet).with("fooy:42|kv|@123456\n")
180
- StatsD.key_value('fooy', 42, 123456)
181
- end
182
- # rubocop:enable StatsD/PositionalArguments
183
-
184
- def test_warn_when_using_key_value_and_not_on_statsite
185
- skip if StatsD::Instrument.strict_mode_enabled?
186
- @backend.implementation = :other
187
- @backend.expects(:write_packet).never
188
- @logger.expects(:warn)
189
- StatsD.key_value('fookv', 3.33)
190
- end
191
-
192
- def test_support_tags_syntax_on_datadog
193
- @backend.implementation = :datadog
194
- @backend.expects(:write_packet).with("fooc:3|c|#topic:foo,bar")
195
- StatsD.increment('fooc', 3, tags: ['topic:foo', 'bar'])
196
- end
197
-
198
- def test_socket_error_should_not_raise_but_log
199
- @socket.stubs(:connect).raises(SocketError)
200
- @logger.expects(:error)
201
- StatsD.increment('fail')
202
- end
203
-
204
- def test_system_call_error_should_not_raise_but_log
205
- @socket.stubs(:send).raises(Errno::ETIMEDOUT)
206
- @logger.expects(:error)
207
- StatsD.increment('fail')
208
- end
209
-
210
- def test_io_error_should_not_raise_but_log
211
- @socket.stubs(:send).raises(IOError)
212
- @logger.expects(:error)
213
- StatsD.increment('fail')
214
- end
215
-
216
- def test_socket_error_should_invalidate_socket
217
- seq = sequence('fail_then_succeed')
218
-
219
- @socket.expects(:connect).with('localhost', 8125)
220
- @socket.expects(:send).raises(Errno::EDESTADDRREQ).in_sequence(seq)
221
-
222
- @socket.expects(:send).returns(1).in_sequence(seq)
223
- @logger.expects(:error)
224
-
225
- StatsD.increment('fail')
226
- StatsD.increment('succeed')
227
- end
228
- end