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
@@ -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