statsd-instrument 2.9.2 → 3.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +0 -11
  3. data/benchmark/send-metrics-to-dev-null-log +4 -2
  4. data/benchmark/send-metrics-to-local-udp-receiver +7 -6
  5. data/lib/statsd/instrument.rb +35 -69
  6. data/lib/statsd/instrument/assertions.rb +14 -14
  7. data/lib/statsd/instrument/client.rb +0 -10
  8. data/lib/statsd/instrument/environment.rb +1 -23
  9. data/lib/statsd/instrument/expectation.rb +14 -14
  10. data/lib/statsd/instrument/helpers.rb +1 -30
  11. data/lib/statsd/instrument/railtie.rb +0 -4
  12. data/lib/statsd/instrument/strict.rb +12 -118
  13. data/lib/statsd/instrument/version.rb +1 -1
  14. data/test/assertions_test.rb +9 -21
  15. data/test/client_test.rb +11 -0
  16. data/test/environment_test.rb +1 -37
  17. data/test/integration_test.rb +9 -24
  18. data/test/statsd_instrumentation_test.rb +25 -50
  19. data/test/statsd_test.rb +2 -29
  20. metadata +4 -26
  21. data/benchmark/datagram-client +0 -40
  22. data/lib/statsd/instrument/backend.rb +0 -18
  23. data/lib/statsd/instrument/backends/capture_backend.rb +0 -32
  24. data/lib/statsd/instrument/backends/logger_backend.rb +0 -20
  25. data/lib/statsd/instrument/backends/null_backend.rb +0 -9
  26. data/lib/statsd/instrument/backends/udp_backend.rb +0 -152
  27. data/lib/statsd/instrument/legacy_client.rb +0 -301
  28. data/lib/statsd/instrument/metric.rb +0 -155
  29. data/test/assertions_on_legacy_client_test.rb +0 -344
  30. data/test/capture_backend_test.rb +0 -26
  31. data/test/compatibility/dogstatsd_datagram_compatibility_test.rb +0 -161
  32. data/test/deprecations_test.rb +0 -139
  33. data/test/logger_backend_test.rb +0 -22
  34. data/test/metric_test.rb +0 -47
  35. data/test/udp_backend_test.rb +0 -228
@@ -5,15 +5,6 @@ require 'test_helper'
5
5
  class StatsDTest < Minitest::Test
6
6
  include StatsD::Instrument::Assertions
7
7
 
8
- def teardown
9
- StatsD.default_tags = nil
10
- end
11
-
12
- def test_statsd_passed_collections_to_backend
13
- StatsD.backend.expects(:collect_metric).with(instance_of(StatsD::Instrument::Metric))
14
- StatsD.increment('test')
15
- end
16
-
17
8
  def test_statsd_measure_with_explicit_value
18
9
  metric = capture_statsd_call { StatsD.measure('values.foobar', 42) }
19
10
  assert_equal 'values.foobar', metric.name
@@ -21,10 +12,6 @@ class StatsDTest < Minitest::Test
21
12
  assert_equal :ms, metric.type
22
13
  end
23
14
 
24
- def test_statsd_measure_without_value_or_block
25
- assert_raises(ArgumentError) { StatsD.measure('values.foobar', tags: 123) }
26
- end
27
-
28
15
  def test_statsd_measure_with_explicit_value_and_sample_rate
29
16
  metric = capture_statsd_call { StatsD.measure('values.foobar', 42, sample_rate: 0.1) }
30
17
  assert_equal 0.1, metric.sample_rate
@@ -85,7 +72,7 @@ class StatsDTest < Minitest::Test
85
72
 
86
73
  def test_statsd_increment_with_hash_argument
87
74
  metric = capture_statsd_call { StatsD.increment('values.foobar', tags: ['test']) }
88
- assert_equal StatsD.default_sample_rate, metric.sample_rate
75
+ assert_equal StatsD.singleton_client.default_sample_rate, metric.sample_rate
89
76
  assert_equal ['test'], metric.tags
90
77
  assert_equal 1, metric.value
91
78
  end
@@ -98,7 +85,7 @@ class StatsDTest < Minitest::Test
98
85
  end
99
86
 
100
87
  def test_statsd_gauge_without_value
101
- assert_raises(ArgumentError) { StatsD.gauge('values.foobar', tags: 123) }
88
+ assert_raises(ArgumentError) { StatsD.gauge('values.foobar') }
102
89
  end
103
90
 
104
91
  def test_statsd_set
@@ -200,20 +187,6 @@ class StatsDTest < Minitest::Test
200
187
  end
201
188
  end
202
189
 
203
- def test_statsd_default_tags_get_normalized
204
- StatsD.default_tags = { first_tag: 'first_value', second_tag: 'second_value' }
205
- assert_equal ['first_tag:first_value', 'second_tag:second_value'], StatsD.default_tags
206
- end
207
-
208
- def test_name_prefix
209
- StatsD.legacy_singleton_client.stubs(:prefix).returns('prefix')
210
- m = capture_statsd_call { StatsD.increment('counter') }
211
- assert_equal 'prefix.counter', m.name
212
-
213
- m = capture_statsd_call { StatsD.increment('counter', no_prefix: true) }
214
- assert_equal 'counter', m.name
215
- end
216
-
217
190
  protected
218
191
 
219
192
  def capture_statsd_call(&block)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: statsd-instrument
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.2
4
+ version: 3.0.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesse Storimer
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-11-06 00:00:00.000000000 Z
13
+ date: 2019-11-01 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
@@ -133,17 +133,11 @@ files:
133
133
  - README.md
134
134
  - Rakefile
135
135
  - benchmark/README.md
136
- - benchmark/datagram-client
137
136
  - benchmark/send-metrics-to-dev-null-log
138
137
  - benchmark/send-metrics-to-local-udp-receiver
139
138
  - lib/statsd-instrument.rb
140
139
  - lib/statsd/instrument.rb
141
140
  - lib/statsd/instrument/assertions.rb
142
- - lib/statsd/instrument/backend.rb
143
- - lib/statsd/instrument/backends/capture_backend.rb
144
- - lib/statsd/instrument/backends/logger_backend.rb
145
- - lib/statsd/instrument/backends/null_backend.rb
146
- - lib/statsd/instrument/backends/udp_backend.rb
147
141
  - lib/statsd/instrument/capture_sink.rb
148
142
  - lib/statsd/instrument/client.rb
149
143
  - lib/statsd/instrument/datagram.rb
@@ -153,10 +147,8 @@ files:
153
147
  - lib/statsd/instrument/environment.rb
154
148
  - lib/statsd/instrument/expectation.rb
155
149
  - lib/statsd/instrument/helpers.rb
156
- - lib/statsd/instrument/legacy_client.rb
157
150
  - lib/statsd/instrument/log_sink.rb
158
151
  - lib/statsd/instrument/matchers.rb
159
- - lib/statsd/instrument/metric.rb
160
152
  - lib/statsd/instrument/null_sink.rb
161
153
  - lib/statsd/instrument/railtie.rb
162
154
  - lib/statsd/instrument/rubocop.rb
@@ -174,28 +166,22 @@ files:
174
166
  - lib/statsd/instrument/version.rb
175
167
  - shipit.rubygems.yml
176
168
  - statsd-instrument.gemspec
177
- - test/assertions_on_legacy_client_test.rb
178
169
  - test/assertions_test.rb
179
170
  - test/benchmark/clock_gettime.rb
180
171
  - test/benchmark/default_tags.rb
181
172
  - test/benchmark/metrics.rb
182
173
  - test/benchmark/tags.rb
183
- - test/capture_backend_test.rb
184
174
  - test/capture_sink_test.rb
185
175
  - test/client_test.rb
186
- - test/compatibility/dogstatsd_datagram_compatibility_test.rb
187
176
  - test/datagram_builder_test.rb
188
177
  - test/datagram_test.rb
189
- - test/deprecations_test.rb
190
178
  - test/dogstatsd_datagram_builder_test.rb
191
179
  - test/environment_test.rb
192
180
  - test/helpers/rubocop_helper.rb
193
181
  - test/helpers_test.rb
194
182
  - test/integration_test.rb
195
183
  - test/log_sink_test.rb
196
- - test/logger_backend_test.rb
197
184
  - test/matchers_test.rb
198
- - test/metric_test.rb
199
185
  - test/null_sink_test.rb
200
186
  - test/rubocop/measure_as_dist_argument_test.rb
201
187
  - test/rubocop/metaprogramming_positional_arguments_test.rb
@@ -209,7 +195,6 @@ files:
209
195
  - test/statsd_instrumentation_test.rb
210
196
  - test/statsd_test.rb
211
197
  - test/test_helper.rb
212
- - test/udp_backend_test.rb
213
198
  - test/udp_sink_test.rb
214
199
  homepage: https://github.com/Shopify/statsd-instrument
215
200
  licenses:
@@ -226,37 +211,31 @@ required_ruby_version: !ruby/object:Gem::Requirement
226
211
  version: '0'
227
212
  required_rubygems_version: !ruby/object:Gem::Requirement
228
213
  requirements:
229
- - - ">="
214
+ - - ">"
230
215
  - !ruby/object:Gem::Version
231
- version: '0'
216
+ version: 1.3.1
232
217
  requirements: []
233
218
  rubygems_version: 3.0.3
234
219
  signing_key:
235
220
  specification_version: 4
236
221
  summary: A StatsD client for Ruby apps
237
222
  test_files:
238
- - test/assertions_on_legacy_client_test.rb
239
223
  - test/assertions_test.rb
240
224
  - test/benchmark/clock_gettime.rb
241
225
  - test/benchmark/default_tags.rb
242
226
  - test/benchmark/metrics.rb
243
227
  - test/benchmark/tags.rb
244
- - test/capture_backend_test.rb
245
228
  - test/capture_sink_test.rb
246
229
  - test/client_test.rb
247
- - test/compatibility/dogstatsd_datagram_compatibility_test.rb
248
230
  - test/datagram_builder_test.rb
249
231
  - test/datagram_test.rb
250
- - test/deprecations_test.rb
251
232
  - test/dogstatsd_datagram_builder_test.rb
252
233
  - test/environment_test.rb
253
234
  - test/helpers/rubocop_helper.rb
254
235
  - test/helpers_test.rb
255
236
  - test/integration_test.rb
256
237
  - test/log_sink_test.rb
257
- - test/logger_backend_test.rb
258
238
  - test/matchers_test.rb
259
- - test/metric_test.rb
260
239
  - test/null_sink_test.rb
261
240
  - test/rubocop/measure_as_dist_argument_test.rb
262
241
  - test/rubocop/metaprogramming_positional_arguments_test.rb
@@ -270,5 +249,4 @@ test_files:
270
249
  - test/statsd_instrumentation_test.rb
271
250
  - test/statsd_test.rb
272
251
  - test/test_helper.rb
273
- - test/udp_backend_test.rb
274
252
  - test/udp_sink_test.rb
@@ -1,40 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'bundler/setup'
5
- require 'benchmark/ips'
6
- require 'socket'
7
-
8
- # Set up an UDP listener to which we can send StatsD packets
9
- legacy_receiver = UDPSocket.new
10
- legacy_receiver.bind('localhost', 0)
11
-
12
- ENV['ENV'] = "production"
13
- ENV['STATSD_ADDR'] = "#{legacy_receiver.addr[2]}:#{legacy_receiver.addr[1]}"
14
- ENV['STATSD_IMPLEMENTATION'] ||= 'datadog'
15
-
16
- require 'statsd-instrument'
17
-
18
- legacy_client = StatsD
19
-
20
- # Set up an UDP listener to which we can send StatsD packets
21
- new_client_receiver = UDPSocket.new
22
- new_client_receiver.bind('localhost', 0)
23
-
24
- udp_sink = StatsD::Instrument::UDPSink.new(new_client_receiver.addr[2], new_client_receiver.addr[1])
25
- new_client = StatsD::Instrument::Client.new(sink: udp_sink, default_sample_rate: StatsD.default_sample_rate)
26
-
27
- Benchmark.ips do |bench|
28
- bench.report("Legacy client (sample rate: #{StatsD.default_sample_rate})") do
29
- legacy_client.increment('StatsD.increment')
30
- end
31
-
32
- bench.report("New client (sample rate: #{StatsD.default_sample_rate})") do
33
- new_client.increment('StatsD.increment')
34
- end
35
-
36
- bench.compare!
37
- end
38
-
39
- legacy_receiver.close
40
- new_client_receiver.close
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # This abstract class specifies the interface a backend implementation should conform to.
4
- # @abstract
5
- class StatsD::Instrument::Backend
6
- # Collects a metric.
7
- #
8
- # @param metric [StatsD::Instrument::Metric] The metric to collect
9
- # @return [void]
10
- def collect_metric(_metric)
11
- raise NotImplementedError, "Use a concrete backend implementation"
12
- end
13
- end
14
-
15
- require 'statsd/instrument/backends/logger_backend'
16
- require 'statsd/instrument/backends/null_backend'
17
- require 'statsd/instrument/backends/capture_backend'
18
- require 'statsd/instrument/backends/udp_backend'
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StatsD::Instrument::Backends
4
- # The capture backend is used to capture the metrics that are collected, so you can
5
- # run assertions on them.
6
- #
7
- # @!attribute collected_metrics [r]
8
- # @return [Array<StatsD::Instrument::Metric>] The list of metrics that were collected.
9
- # @see StatsD::Instrument::Assertions
10
- class CaptureBackend < StatsD::Instrument::Backend
11
- attr_reader :collected_metrics
12
- attr_accessor :parent
13
-
14
- def initialize
15
- reset
16
- end
17
-
18
- # Adds a metric to the ist of collected metrics.
19
- # @param metric [StatsD::Instrument::Metric] The metric to collect.
20
- # @return [void]
21
- def collect_metric(metric)
22
- parent&.collect_metric(metric)
23
- @collected_metrics << metric
24
- end
25
-
26
- # Resets the list of collected metrics to an empty list.
27
- # @return [void]
28
- def reset
29
- @collected_metrics = []
30
- end
31
- end
32
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StatsD::Instrument::Backends
4
- # The logger backend simply logs every metric to a logger
5
- # @!attribute logger
6
- # @return [Logger]
7
- class LoggerBackend < StatsD::Instrument::Backend
8
- attr_accessor :logger
9
-
10
- def initialize(logger)
11
- @logger = logger
12
- end
13
-
14
- # @param metric [StatsD::Instrument::Metric]
15
- # @return [void]
16
- def collect_metric(metric)
17
- logger.info("[StatsD] #{metric}")
18
- end
19
- end
20
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module StatsD::Instrument::Backends
4
- # The null backend does nothing when receiving a metric, effectively disabling the gem completely.
5
- class NullBackend < StatsD::Instrument::Backend
6
- def collect_metric(metric)
7
- end
8
- end
9
- end
@@ -1,152 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'monitor'
4
-
5
- module StatsD::Instrument::Backends
6
- class UDPBackend < StatsD::Instrument::Backend
7
- BASE_SUPPORTED_METRIC_TYPES = { c: true, ms: true, g: true, s: true }
8
-
9
- class DogStatsDProtocol
10
- SUPPORTED_METRIC_TYPES = BASE_SUPPORTED_METRIC_TYPES.merge(h: true, _e: true, _sc: true, d: true)
11
-
12
- SERVICE_CHECK_STATUSES = { ok: 0, warning: 1, critical: 2, unknown: 3 }
13
-
14
- def generate_packet(metric)
15
- packet = +""
16
-
17
- if metric.type == :_e
18
- escaped_title = metric.name.gsub("\n", "\\n")
19
- escaped_text = metric.value.gsub("\n", "\\n")
20
-
21
- packet << "_e{#{escaped_title.size},#{escaped_text.size}}:#{escaped_title}|#{escaped_text}"
22
- packet << "|h:#{metric.metadata[:hostname]}" if metric.metadata[:hostname]
23
- packet << "|d:#{metric.metadata[:timestamp].to_i}" if metric.metadata[:timestamp]
24
- packet << "|k:#{metric.metadata[:aggregation_key]}" if metric.metadata[:aggregation_key]
25
- packet << "|p:#{metric.metadata[:priority]}" if metric.metadata[:priority]
26
- packet << "|s:#{metric.metadata[:source_type_name]}" if metric.metadata[:source_type_name]
27
- packet << "|t:#{metric.metadata[:alert_type]}" if metric.metadata[:alert_type]
28
- packet << "|##{metric.tags.join(',')}" if metric.tags
29
-
30
- elsif metric.type == :_sc
31
- status = metric.value.is_a?(Integer) ? metric.value : SERVICE_CHECK_STATUSES.fetch(metric.value.to_sym)
32
-
33
- packet << "_sc|#{metric.name}|#{status}"
34
- packet << "|h:#{metric.metadata[:hostname]}" if metric.metadata[:hostname]
35
- packet << "|d:#{metric.metadata[:timestamp].to_i}" if metric.metadata[:timestamp]
36
- packet << "|##{metric.tags.join(',')}" if metric.tags
37
- packet << "|m:#{metric.metadata[:message]}" if metric.metadata[:message]
38
-
39
- else
40
- packet << "#{metric.name}:#{metric.value}|#{metric.type}"
41
- packet << "|@#{metric.sample_rate}" if metric.sample_rate < 1
42
- packet << "|##{metric.tags.join(',')}" if metric.tags
43
- end
44
-
45
- packet
46
- end
47
- end
48
-
49
- class StatsiteStatsDProtocol
50
- SUPPORTED_METRIC_TYPES = BASE_SUPPORTED_METRIC_TYPES.merge(kv: true)
51
-
52
- def generate_packet(metric)
53
- packet = +"#{metric.name}:#{metric.value}|#{metric.type}"
54
- packet << "|@#{metric.sample_rate}" unless metric.sample_rate == 1
55
- packet << "\n"
56
- packet
57
- end
58
- end
59
-
60
- class StatsDProtocol
61
- SUPPORTED_METRIC_TYPES = BASE_SUPPORTED_METRIC_TYPES
62
-
63
- def generate_packet(metric)
64
- packet = +"#{metric.name}:#{metric.value}|#{metric.type}"
65
- packet << "|@#{metric.sample_rate}" if metric.sample_rate < 1
66
- packet
67
- end
68
- end
69
-
70
- DEFAULT_IMPLEMENTATION = :statsd
71
-
72
- include MonitorMixin
73
-
74
- attr_reader :host, :port, :implementation
75
-
76
- def initialize(server = nil, implementation = nil)
77
- super()
78
- self.server = server || "localhost:8125"
79
- self.implementation = (implementation || DEFAULT_IMPLEMENTATION).to_sym
80
- end
81
-
82
- def implementation=(value)
83
- @packet_factory = case value
84
- when :datadog
85
- DogStatsDProtocol.new
86
- when :statsite
87
- StatsiteStatsDProtocol.new
88
- else
89
- StatsDProtocol.new
90
- end
91
- @implementation = value
92
- end
93
-
94
- def collect_metric(metric)
95
- unless @packet_factory.class::SUPPORTED_METRIC_TYPES[metric.type]
96
- StatsD.logger.warn("[StatsD] Metric type #{metric.type.inspect} is not supported " \
97
- "on #{implementation} implementation.")
98
- return false
99
- end
100
-
101
- if metric.sample_rate < 1.0 && rand > metric.sample_rate
102
- return false
103
- end
104
-
105
- write_packet(@packet_factory.generate_packet(metric))
106
- end
107
-
108
- def server=(connection_string)
109
- @host, @port = connection_string.split(':', 2)
110
- @port = @port.to_i
111
- invalidate_socket
112
- end
113
-
114
- def host=(host)
115
- @host = host
116
- invalidate_socket
117
- end
118
-
119
- def port=(port)
120
- @port = port
121
- invalidate_socket
122
- end
123
-
124
- def socket
125
- if @socket.nil?
126
- @socket = UDPSocket.new
127
- @socket.connect(host, port)
128
- end
129
- @socket
130
- end
131
-
132
- def write_packet(command)
133
- synchronize do
134
- socket.send(command, 0) > 0
135
- end
136
- rescue ThreadError
137
- # In cases where a TERM or KILL signal has been sent, and we send stats as
138
- # part of a signal handler, locks cannot be acquired, so we do our best
139
- # to try and send the command without a lock.
140
- socket.send(command, 0) > 0
141
- rescue SocketError, IOError, SystemCallError => e
142
- StatsD.logger.error("[StatsD] #{e.class.name}: #{e.message}")
143
- invalidate_socket
144
- end
145
-
146
- def invalidate_socket
147
- synchronize do
148
- @socket = nil
149
- end
150
- end
151
- end
152
- end