statsd-instrument 2.9.2 → 3.0.0.pre1

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 (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
@@ -1,301 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class StatsD::Instrument::LegacyClient
4
- def self.singleton
5
- @singleton ||= new
6
- end
7
-
8
- attr_accessor :default_sample_rate, :prefix
9
- attr_writer :backend
10
- attr_reader :default_tags
11
-
12
- def default_tags=(tags)
13
- @default_tags = StatsD::Instrument::Metric.normalize_tags(tags)
14
- end
15
-
16
- def backend
17
- @backend ||= StatsD::Instrument::Environment.default_backend
18
- end
19
-
20
- # @!method measure(name, value = nil, sample_rate: nil, tags: nil, &block)
21
- #
22
- # Emits a timing metric
23
- #
24
- # @param [String] key The name of the metric.
25
- # @param sample_rate (see #increment)
26
- # @param tags (see #increment)
27
- #
28
- # @example Providing a value directly
29
- # start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
30
- # do_something
31
- # stop = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
32
- # http_response = StatsD.measure('HTTP.call.duration', stop - start)
33
- #
34
- # @example Providing a block to measure the duration of its execution
35
- # http_response = StatsD.measure('HTTP.call.duration') do
36
- # Net::HTTP.get(url)
37
- # end
38
- #
39
- # @overload measure(key, value, sample_rate: nil, tags: nil)
40
- # Emits a timing metric, by providing a duration in milliseconds.
41
- #
42
- # @param [Float] value The measured duration in milliseconds
43
- # @return [void]
44
- #
45
- # @overload measure(key, sample_rate: nil, tags: nil, &block)
46
- # Emits a timing metric, after measuring the execution duration of the
47
- # block passed to this method.
48
- #
49
- # @yield `StatsD.measure` will yield the block and measure the duration. After the block
50
- # returns, the duration in millisecond will be emitted as metric.
51
- # @return The value that was returned by the block passed through.
52
- def measure(
53
- key, value_arg = nil, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
54
- value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
55
- prefix: self.prefix, no_prefix: false, as_dist: false,
56
- &block
57
- )
58
- # TODO: in the next version, hardcode this to :ms when the as_dist argument is dropped.
59
- type = as_dist ? :d : :ms
60
- prefix = nil if no_prefix
61
- if block_given?
62
- measure_latency(type, key, sample_rate: sample_rate, tags: tags, prefix: prefix, &block)
63
- else
64
- collect_metric(type, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
65
- end
66
- end
67
-
68
- # @!method increment(name, value = 1, sample_rate: nil, tags: nil)
69
- #
70
- # Emits a counter metric.
71
- #
72
- # @param key [String] The name of the metric.
73
- # @param value [Integer] The value to increment the counter by.
74
- #
75
- # You should not compensate for the sample rate using the counter increment. E.g., if
76
- # your sample rate is 0.01, you should <b>not</b> use 100 as increment to compensate for it.
77
- # The sample rate is part of the packet that is being sent to the server, and the server
78
- # should know how to handle it.
79
- #
80
- # @param sample_rate [Float] (default: `StatsD.default_sample_rate`) The rate at which to sample
81
- # this metric call. This value should be between 0 and 1. This value can be used to reduce
82
- # the amount of network I/O (and CPU cycles) used for very frequent metrics.
83
- #
84
- # - A value of `0.1` means that only 1 out of 10 calls will be emitted; the other 9 will
85
- # be short-circuited.
86
- # - When set to `1`, every metric will be emitted.
87
- # - If this parameter is not set, the default sample rate for this client will be used.
88
- # @param tags [Array<String>, Hash<Symbol, String>] The tags to associate with this measurement.
89
- # They can be provided as an array of strings, or a hash of key/value pairs.
90
- # _Note:_ Tags are not supported by all implementations.
91
- # @return [void]
92
- def increment(
93
- key, value_arg = 1, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
94
- value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
95
- prefix: self.prefix, no_prefix: false
96
- )
97
- prefix = nil if no_prefix
98
- collect_metric(:c, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
99
- end
100
-
101
- # @!method gauge(name, value, sample_rate: nil, tags: nil)
102
- #
103
- # Emits a gauge metric.
104
- #
105
- # @param key The name of the metric.
106
- # @param value [Numeric] The current value to record.
107
- # @param sample_rate (see #increment)
108
- # @param tags (see #increment)
109
- # @return [void]
110
- def gauge(
111
- key, value_arg = nil, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
112
- value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
113
- prefix: self.prefix, no_prefix: false
114
- )
115
- prefix = nil if no_prefix
116
- collect_metric(:g, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
117
- end
118
-
119
- # @!method set(name, value, sample_rate: nil, tags: nil)
120
- #
121
- # Emits a set metric, which counts the number of distinct values that have occurred.
122
- #
123
- # @example Counting the number of unique visitors
124
- # StatsD.set('visitors.unique', Current.user.id)
125
- #
126
- # @param key [String] The name of the metric.
127
- # @param value [Numeric] The value to record.
128
- # @param sample_rate (see #increment)
129
- # @param tags (see #increment)
130
- # @return [void]
131
- def set(
132
- key, value_arg = nil, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
133
- value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
134
- prefix: self.prefix, no_prefix: false
135
- )
136
- prefix = nil if no_prefix
137
- collect_metric(:s, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
138
- end
139
-
140
- # @!method histogram(name, value, sample_rate: nil, tags: nil)
141
- #
142
- # Emits a histogram metric.
143
- #
144
- # @param key The name of the metric.
145
- # @param value [Numeric] The value to record.
146
- # @param sample_rate (see #increment)
147
- # @param tags (see #increment)
148
- # @return (see #collect_metric)
149
- # @note Supported by the datadog implementation only.
150
- def histogram(
151
- key, value_arg = nil, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
152
- value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
153
- prefix: self.prefix, no_prefix: false
154
- )
155
- prefix = nil if no_prefix
156
- collect_metric(:h, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
157
- end
158
-
159
- # @!method distribution(name, value = nil, sample_rate: nil, tags: nil, &block)
160
- #
161
- # Emits a distribution metric.
162
- #
163
- # @param [String] key The name of the metric.
164
- # @param sample_rate (see #increment)
165
- # @param tags (see #increment)
166
- #
167
- # @note Supported by the datadog implementation only.
168
- # @example
169
- # http_response = StatsD.distribution('HTTP.call.duration') do
170
- # Net::HTTP.get(url)
171
- # end
172
- #
173
- # @overload distribution(name, value, sample_rate: nil, tags: nil)
174
- #
175
- # Emits a distribution metric, given a provided value to record.
176
- #
177
- # @param [Numeric] value The value to record.
178
- # @return [void]
179
- #
180
- # @overload distribution(key, metric_options = {}, &block)
181
- #
182
- # Emits a distribution metric for the duration of the provided block, in milliseconds.
183
- #
184
- # @yield `StatsD.distribution` will yield the block and measure the duration. After
185
- # the block returns, the duration in millisecond will be emitted as metric.
186
- # @return The value that was returned by the block passed through.
187
- def distribution(
188
- key, value_arg = nil, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
189
- value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
190
- prefix: self.prefix, no_prefix: false,
191
- &block
192
- )
193
- prefix = nil if no_prefix
194
- if block_given?
195
- measure_latency(:d, key, sample_rate: sample_rate, tags: tags, prefix: prefix, &block)
196
- else
197
- collect_metric(:d, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
198
- end
199
- end
200
-
201
- # @!method key_value(name, value)
202
- #
203
- # Emits a key/value metric.
204
- #
205
- # @param key [String] The name of the metric.
206
- # @param value [Numeric] The value to record.
207
- # @return [void]
208
- #
209
- # @note Supported by the statsite implementation only.
210
- def key_value(
211
- key, value_arg = nil, deprecated_sample_rate_arg = nil,
212
- value: value_arg, sample_rate: deprecated_sample_rate_arg, no_prefix: false
213
- )
214
- prefix = nil if no_prefix
215
- collect_metric(:kv, key, value, sample_rate: sample_rate, prefix: prefix)
216
- end
217
-
218
- # @!method event(title, text, tags: nil, hostname: nil, timestamp: nil, aggregation_key: nil, priority: nil, source_type_name: nil, alert_type: nil) # rubocop:disable Metrics/LineLength
219
- #
220
- # Emits an event.
221
- #
222
- # @param title [String] Title of the event. A configured prefix may be applied to this title.
223
- # @param text [String] Body of the event. Can contain newlines.
224
- # @param [String] hostname The hostname to associate with the event.
225
- # @param [Time] timestamp The moment the status of the service was checked. Defaults to now.
226
- # @param [String] aggregation_key A key to aggregate similar events into groups.
227
- # @param [String] priority The event's priority, either `"low"` or `"normal"` (default).
228
- # @param [String] source_type_name The source type.
229
- # @param [String] alert_type The type of alert. Either `"info"` (default), `"warning"`, `"error"`, or `"success"`.
230
- # @param tags (see #increment)
231
- # @return [void]
232
- #
233
- # @note Supported by the Datadog implementation only.
234
- def event(
235
- title, text,
236
- deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
237
- sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
238
- prefix: self.prefix, no_prefix: false,
239
- hostname: nil, date_happened: nil, timestamp: date_happened,
240
- aggregation_key: nil, priority: nil, source_type_name: nil, alert_type: nil,
241
- **_ignored
242
- )
243
- prefix = nil if no_prefix
244
- collect_metric(:_e, title, text, sample_rate: sample_rate, tags: tags, prefix: prefix, metadata: {
245
- hostname: hostname, timestamp: timestamp, aggregation_key: aggregation_key,
246
- priority: priority, source_type_name: source_type_name, alert_type: alert_type
247
- })
248
- end
249
-
250
- # @!method service_check(name, status, tags: nil, hostname: nil, timestamp: nil, message: nil)
251
- #
252
- # Emits a service check.
253
- #
254
- # @param [String] name Name of the service. A configured prefix may be applied to this title.
255
- # @param [Symbol] status Current status of the service. Either `:ok`, `:warning`, `:critical`, or `:unknown`.
256
- # @param [String] hostname The hostname to associate with the event.
257
- # @param [Time] timestamp The moment the status of the service was checked. Defaults to now.
258
- # @param [String] message A message that describes the current status.
259
- # @param tags (see #increment)
260
- # @return [void]
261
- #
262
- # @note Supported by the Datadog implementation only.
263
- def service_check(
264
- name, status,
265
- deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
266
- sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
267
- prefix: self.prefix, no_prefix: false,
268
- hostname: nil, timestamp: nil, message: nil, **_ignored
269
- )
270
- prefix = nil if no_prefix
271
- collect_metric(:_sc, name, status, sample_rate: sample_rate, prefix: prefix, tags: tags, metadata: {
272
- hostname: hostname, timestamp: timestamp, message: message
273
- })
274
- end
275
-
276
- protected
277
-
278
- def measure_latency(type, key, sample_rate:, tags:, prefix:)
279
- start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
280
- begin
281
- yield
282
- ensure
283
- # Ensure catches both a raised exception and a return in the invoked block
284
- value = 1000.0 * (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start)
285
- collect_metric(type, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
286
- end
287
- end
288
-
289
- # Instantiates a metric, and sends it to the backend for further processing.
290
- # @param options (see StatsD::Instrument::Metric#initialize)
291
- # @return [void]
292
- def collect_metric(type, name, value, sample_rate:, tags: nil, prefix:, metadata: nil)
293
- sample_rate ||= default_sample_rate
294
- name = "#{prefix}.#{name}" if prefix
295
-
296
- metric = StatsD::Instrument::Metric.new(type: type, name: name, value: value,
297
- sample_rate: sample_rate, tags: tags, metadata: metadata)
298
- backend.collect_metric(metric)
299
- metric
300
- end
301
- end
@@ -1,155 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # The Metric class represents a metric sample to be send by a backend.
4
- #
5
- # @!attribute type
6
- # @return [Symbol] The metric type. Must be one of {StatsD::Instrument::Metric::TYPES}
7
- # @!attribute name
8
- # @return [String] The name of the metric. {StatsD#prefix} will automatically be applied
9
- # to the metric in the constructor, unless the <tt>:no_prefix</tt> option is set or is
10
- # overridden by the <tt>:prefix</tt> option. Note that <tt>:no_prefix</tt> has greater
11
- # precedence than <tt>:prefix</tt>.
12
- # @!attribute value
13
- # @see #default_value
14
- # @return [Numeric, String] The value to collect for the metric. Depending on the metric
15
- # type, <tt>value</tt> can be a string, integer, or float.
16
- # @!attribute sample_rate
17
- # The sample rate to use for the metric. How the sample rate is handled differs per backend.
18
- # The UDP backend will actually sample metric submissions based on the sample rate, while
19
- # the logger backend will just include the sample rate in its output for debugging purposes.
20
- # @see StatsD#default_sample_rate
21
- # @return [Float] The sample rate to use for this metric. This should be a value between
22
- # 0 and 1. If not set, it will use the default sample rate set to {StatsD#default_sample_rate}.
23
- # @!attribute tags
24
- # The tags to associate with the metric.
25
- # @note Only the Datadog implementation supports tags.
26
- # @see .normalize_tags
27
- # @return [Array<String>, Hash<String, String>, nil] the tags to associate with the metric.
28
- # You can either specify the tags as an array of strings, or a Hash of key/value pairs.
29
- #
30
- # @see StatsD The StatsD module contains methods that generate metric instances.
31
- # @see StatsD::Instrument::Backend A StatsD::Instrument::Backend is used to collect metrics.
32
- #
33
- class StatsD::Instrument::Metric
34
- unless Regexp.method_defined?(:match?) # for ruby 2.3
35
- module RubyBackports
36
- refine Regexp do
37
- def match?(str)
38
- (self =~ str) != nil
39
- end
40
- end
41
- end
42
-
43
- using RubyBackports
44
- end
45
-
46
- def self.new(type:, name:, value: default_value(type), tags: nil, metadata: nil,
47
- sample_rate: StatsD.legacy_singleton_client.default_sample_rate)
48
-
49
- # pass keyword arguments as positional arguments for performance reasons,
50
- # since MRI's C implementation of new turns keyword arguments into a hash
51
- super(type, name, value, sample_rate, tags, metadata)
52
- end
53
-
54
- # The default value for this metric, which will be used if it is not set.
55
- #
56
- # A default value is only defined for counter metrics (<tt>1</tt>). For all other
57
- # metric types, this method will raise an <tt>ArgumentError</tt>.
58
- #
59
- #
60
- # A default value is only defined for counter metrics (<tt>1</tt>). For all other
61
- # metric types, this method will raise an <tt>ArgumentError</tt>.
62
- #
63
- # @return [Numeric, String] The default value for this metric.
64
- # @raise ArgumentError if the metric type doesn't have a default value
65
- def self.default_value(type)
66
- case type
67
- when :c then 1
68
- else raise ArgumentError, "A value is required for metric type #{type.inspect}."
69
- end
70
- end
71
-
72
- attr_accessor :type, :name, :value, :sample_rate, :tags, :metadata
73
-
74
- # Initializes a new metric instance.
75
- # Normally, you don't want to call this method directly, but use one of the metric collection
76
- # methods on the {StatsD} module.
77
- #
78
- # @param type [Symbol] The type of the metric.
79
- # @option name [String] :name The name of the metric without prefix.
80
- # @option value [Numeric, String, nil] The value to collect for the metric.
81
- # @option sample_rate [Numeric, nil] The sample rate to use. If not set, it will use
82
- # {StatsD#default_sample_rate}.
83
- # @option tags [Array<String>, Hash<String, String>, nil] :tags The tags to apply to this metric.
84
- # See {.normalize_tags} for more information.
85
- def initialize(type, name, value, sample_rate, tags, metadata) # rubocop:disable Metrics/ParameterLists
86
- raise ArgumentError, "Metric :type is required." unless type
87
- raise ArgumentError, "Metric :name is required." unless name
88
- raise ArgumentError, "Metric :value is required." unless value
89
-
90
- @type = type
91
- @name = normalize_name(name)
92
- @value = value
93
- @sample_rate = sample_rate
94
- @tags = StatsD::Instrument::Metric.normalize_tags(tags)
95
- if StatsD.legacy_singleton_client.default_tags
96
- @tags = Array(@tags) + StatsD.legacy_singleton_client.default_tags
97
- end
98
- @metadata = metadata
99
- end
100
-
101
- # @private
102
- # @return [String]
103
- def to_s
104
- str = +"#{name}:#{value}|#{type}"
105
- str << "|@#{sample_rate}" if sample_rate && sample_rate != 1.0
106
- str << "|#" << tags.join(',') if tags && !tags.empty?
107
- str
108
- end
109
-
110
- # @private
111
- # @return [String]
112
- def inspect
113
- "#<StatsD::Instrument::Metric #{self}>"
114
- end
115
-
116
- # The metric types that are supported by this library. Note that every StatsD server
117
- # implementation only supports a subset of them.
118
- TYPES = {
119
- c: 'increment',
120
- ms: 'measure',
121
- g: 'gauge',
122
- h: 'histogram',
123
- d: 'distribution',
124
- kv: 'key/value',
125
- s: 'set',
126
- }
127
-
128
- # Strip metric names of special characters used by StatsD line protocol, replace with underscore
129
- #
130
- # @param name [String]
131
- # @return [String]
132
- def normalize_name(name)
133
- # fast path when no normalization is needed to avoid copying the string
134
- return name unless /[:|@]/.match?(name)
135
-
136
- name.tr(':|@', '_')
137
- end
138
-
139
- # Utility function to convert tags to the canonical form.
140
- #
141
- # - Tags specified as key value pairs will be converted into an array
142
- # - Tags are normalized to only use word characters and underscores.
143
- #
144
- # @param tags [Array<String>, Hash<String, String>, nil] Tags specified in any form.
145
- # @return [Array<String>, nil] the list of tags in canonical form.
146
- def self.normalize_tags(tags)
147
- return unless tags
148
- tags = tags.map { |k, v| k.to_s + ":" + v.to_s } if tags.is_a?(Hash)
149
-
150
- # fast path when no string replacement is needed
151
- return tags unless tags.any? { |tag| /[|,]/.match?(tag) }
152
-
153
- tags.map { |tag| tag.tr('|,', '') }
154
- end
155
- end