statsd-instrument 2.9.0 → 3.0.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.
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