statsd-instrument 2.3.2 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +1 -0
- data/.github/workflows/benchmark.yml +32 -0
- data/.github/workflows/ci.yml +47 -0
- data/.gitignore +1 -0
- data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +1027 -0
- data/.rubocop.yml +50 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +288 -2
- data/CONTRIBUTING.md +28 -6
- data/Gemfile +5 -0
- data/README.md +54 -46
- data/Rakefile +4 -2
- data/benchmark/README.md +29 -0
- data/benchmark/datagram-client +41 -0
- data/benchmark/send-metrics-to-dev-null-log +47 -0
- data/benchmark/send-metrics-to-local-udp-receiver +57 -0
- data/lib/statsd/instrument/assertions.rb +179 -30
- data/lib/statsd/instrument/backend.rb +3 -2
- data/lib/statsd/instrument/backends/capture_backend.rb +4 -1
- data/lib/statsd/instrument/backends/logger_backend.rb +3 -3
- data/lib/statsd/instrument/backends/null_backend.rb +2 -0
- data/lib/statsd/instrument/backends/udp_backend.rb +39 -45
- data/lib/statsd/instrument/capture_sink.rb +27 -0
- data/lib/statsd/instrument/client.rb +313 -0
- data/lib/statsd/instrument/datagram.rb +75 -0
- data/lib/statsd/instrument/datagram_builder.rb +101 -0
- data/lib/statsd/instrument/dogstatsd_datagram_builder.rb +71 -0
- data/lib/statsd/instrument/environment.rb +108 -29
- data/lib/statsd/instrument/helpers.rb +16 -8
- data/lib/statsd/instrument/log_sink.rb +24 -0
- data/lib/statsd/instrument/matchers.rb +14 -11
- data/lib/statsd/instrument/metric.rb +72 -45
- data/lib/statsd/instrument/metric_expectation.rb +32 -18
- data/lib/statsd/instrument/null_sink.rb +13 -0
- data/lib/statsd/instrument/railtie.rb +2 -1
- data/lib/statsd/instrument/rubocop/measure_as_dist_argument.rb +39 -0
- data/lib/statsd/instrument/rubocop/metaprogramming_positional_arguments.rb +42 -0
- data/lib/statsd/instrument/rubocop/metric_prefix_argument.rb +37 -0
- data/lib/statsd/instrument/rubocop/metric_return_value.rb +32 -0
- data/lib/statsd/instrument/rubocop/metric_value_keyword_argument.rb +36 -0
- data/lib/statsd/instrument/rubocop/positional_arguments.rb +99 -0
- data/lib/statsd/instrument/rubocop/splat_arguments.rb +31 -0
- data/lib/statsd/instrument/rubocop.rb +64 -0
- data/lib/statsd/instrument/statsd_datagram_builder.rb +14 -0
- data/lib/statsd/instrument/strict.rb +235 -0
- data/lib/statsd/instrument/udp_sink.rb +62 -0
- data/lib/statsd/instrument/version.rb +3 -1
- data/lib/statsd/instrument.rb +340 -163
- data/lib/statsd-instrument.rb +2 -0
- data/statsd-instrument.gemspec +13 -10
- data/test/assertions_test.rb +167 -156
- data/test/benchmark/clock_gettime.rb +27 -0
- data/test/benchmark/default_tags.rb +47 -0
- data/test/benchmark/metrics.rb +9 -8
- data/test/benchmark/tags.rb +5 -3
- data/test/capture_backend_test.rb +4 -2
- data/test/capture_sink_test.rb +44 -0
- data/test/client_test.rb +164 -0
- data/test/compatibility/dogstatsd_datagram_compatibility_test.rb +162 -0
- data/test/datagram_builder_test.rb +120 -0
- data/test/deprecations_test.rb +132 -0
- data/test/dogstatsd_datagram_builder_test.rb +32 -0
- data/test/environment_test.rb +75 -8
- data/test/helpers/rubocop_helper.rb +47 -0
- data/test/helpers_test.rb +2 -1
- data/test/integration_test.rb +31 -7
- data/test/log_sink_test.rb +37 -0
- data/test/logger_backend_test.rb +10 -8
- data/test/matchers_test.rb +42 -28
- data/test/metric_test.rb +18 -22
- data/test/null_sink_test.rb +13 -0
- data/test/rubocop/measure_as_dist_argument_test.rb +44 -0
- data/test/rubocop/metaprogramming_positional_arguments_test.rb +58 -0
- data/test/rubocop/metric_prefix_argument_test.rb +38 -0
- data/test/rubocop/metric_return_value_test.rb +78 -0
- data/test/rubocop/metric_value_keyword_argument_test.rb +39 -0
- data/test/rubocop/positional_arguments_test.rb +110 -0
- data/test/rubocop/splat_arguments_test.rb +27 -0
- data/test/statsd_datagram_builder_test.rb +22 -0
- data/test/statsd_instrumentation_test.rb +109 -100
- data/test/statsd_test.rb +113 -79
- data/test/test_helper.rb +12 -1
- data/test/udp_backend_test.rb +38 -36
- data/test/udp_sink_test.rb +85 -0
- metadata +85 -5
- data/.travis.yml +0 -12
data/lib/statsd/instrument.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'socket'
|
2
4
|
require 'logger'
|
3
5
|
|
@@ -27,10 +29,13 @@ require 'logger'
|
|
27
29
|
# @!attribute logger
|
28
30
|
# The logger to use in case of any errors. The logger is also used as default logger
|
29
31
|
# for the LoggerBackend (although this can be overwritten).
|
30
|
-
#
|
31
32
|
# @see StatsD::Instrument::Backends::LoggerBackend
|
32
33
|
# @return [Logger]
|
33
34
|
#
|
35
|
+
# @!attribute default_tags
|
36
|
+
# The tags to apply to all metrics.
|
37
|
+
# @return [Array<String>, Hash<String, String>, nil] The default tags, or <tt>nil</tt> when no default tags is used
|
38
|
+
#
|
34
39
|
# @see StatsD::Instrument <tt>StatsD::Instrument</tt> contains module to instrument
|
35
40
|
# existing methods with StatsD metrics.
|
36
41
|
module StatsD
|
@@ -56,20 +61,26 @@ module StatsD
|
|
56
61
|
metric_name.respond_to?(:call) ? metric_name.call(callee, args).gsub('::', '.') : metric_name.gsub('::', '.')
|
57
62
|
end
|
58
63
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
64
|
+
# Even though this method is considered private, and is no longer used internally,
|
65
|
+
# applications in the wild rely on it. As a result, we cannot remove this method
|
66
|
+
# until the next major version.
|
67
|
+
#
|
68
|
+
# @deprecated Use Process.clock_gettime(Process::CLOCK_MONOTONIC) instead.
|
69
|
+
def self.current_timestamp
|
70
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Even though this method is considered private, and is no longer used internally,
|
74
|
+
# applications in the wild rely on it. As a result, we cannot remove this method
|
75
|
+
# until the next major version.
|
76
|
+
#
|
77
|
+
# @deprecated You can implement similar functionality yourself using
|
78
|
+
# `Process.clock_gettime(Process::CLOCK_MONOTONIC)`. Think about what will
|
79
|
+
# happen if an exception happens during the block execution though.
|
80
|
+
def self.duration
|
81
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
82
|
+
yield
|
83
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
73
84
|
end
|
74
85
|
|
75
86
|
# Adds execution duration instrumentation to a method as a timing.
|
@@ -79,10 +90,18 @@ module StatsD
|
|
79
90
|
# callable to dynamically generate a metric name
|
80
91
|
# @param metric_options (see StatsD#measure)
|
81
92
|
# @return [void]
|
82
|
-
def statsd_measure(method, name,
|
93
|
+
def statsd_measure(method, name, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil, as_dist: false,
|
94
|
+
sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg, prefix: nil, no_prefix: false)
|
95
|
+
|
83
96
|
add_to_method(method, name, :measure) do
|
84
97
|
define_method(method) do |*args, &block|
|
85
|
-
StatsD
|
98
|
+
key = StatsD::Instrument.generate_metric_name(name, self, *args)
|
99
|
+
prefix ||= StatsD.prefix
|
100
|
+
StatsD.measure( # rubocop:disable StatsD/MeasureAsDistArgument, StatsD/MetricPrefixArgument
|
101
|
+
key, sample_rate: sample_rate, tags: tags, prefix: prefix, no_prefix: no_prefix, as_dist: as_dist
|
102
|
+
) do
|
103
|
+
super(*args, &block)
|
104
|
+
end
|
86
105
|
end
|
87
106
|
end
|
88
107
|
end
|
@@ -95,10 +114,18 @@ module StatsD
|
|
95
114
|
# @param metric_options (see StatsD#measure)
|
96
115
|
# @return [void]
|
97
116
|
# @note Supported by the datadog implementation only (in beta)
|
98
|
-
def statsd_distribution(method, name,
|
117
|
+
def statsd_distribution(method, name, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
118
|
+
sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg, prefix: nil, no_prefix: false)
|
119
|
+
|
99
120
|
add_to_method(method, name, :distribution) do
|
100
121
|
define_method(method) do |*args, &block|
|
101
|
-
StatsD
|
122
|
+
key = StatsD::Instrument.generate_metric_name(name, self, *args)
|
123
|
+
prefix ||= StatsD.prefix
|
124
|
+
StatsD.distribution( # rubocop:disable StatsD/MetricPrefixArgument
|
125
|
+
key, sample_rate: sample_rate, tags: tags, prefix: prefix, no_prefix: no_prefix
|
126
|
+
) do
|
127
|
+
super(*args, &block)
|
128
|
+
end
|
102
129
|
end
|
103
130
|
end
|
104
131
|
end
|
@@ -118,7 +145,9 @@ module StatsD
|
|
118
145
|
# @yieldreturn [Boolean] Return true iff the return value is consisered a success, false otherwise.
|
119
146
|
# @return [void]
|
120
147
|
# @see #statsd_count_if
|
121
|
-
def statsd_count_success(method, name,
|
148
|
+
def statsd_count_success(method, name, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
149
|
+
sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg, prefix: nil, no_prefix: false)
|
150
|
+
|
122
151
|
add_to_method(method, name, :count_success) do
|
123
152
|
define_method(method) do |*args, &block|
|
124
153
|
begin
|
@@ -127,30 +156,40 @@ module StatsD
|
|
127
156
|
truthiness = false
|
128
157
|
raise
|
129
158
|
else
|
130
|
-
|
159
|
+
if block_given?
|
160
|
+
begin
|
161
|
+
truthiness = yield(result)
|
162
|
+
rescue
|
163
|
+
truthiness = false
|
164
|
+
end
|
165
|
+
end
|
131
166
|
result
|
132
167
|
ensure
|
133
168
|
suffix = truthiness == false ? 'failure' : 'success'
|
134
|
-
|
169
|
+
key = "#{StatsD::Instrument.generate_metric_name(name, self, *args)}.#{suffix}"
|
170
|
+
prefix ||= StatsD.prefix
|
171
|
+
StatsD.increment(key, prefix: prefix, # rubocop:disable StatsD/MetricPrefixArgument
|
172
|
+
sample_rate: sample_rate, tags: tags, no_prefix: no_prefix)
|
135
173
|
end
|
136
174
|
end
|
137
175
|
end
|
138
176
|
end
|
139
177
|
|
140
|
-
# Adds success
|
178
|
+
# Adds success counter instrumentation to a method.
|
141
179
|
#
|
142
180
|
# A method call will be considered successful if it does not raise an exception, and the result is true-y.
|
143
|
-
# Only for successful calls, the metric will be
|
181
|
+
# Only for successful calls, the metric will be incremented.
|
144
182
|
#
|
145
183
|
# @param method (see #statsd_measure)
|
146
184
|
# @param name (see #statsd_measure)
|
147
|
-
# @param metric_options (see #statsd_measure)
|
148
185
|
# @yield (see #statsd_count_success)
|
149
186
|
# @yieldparam result (see #statsd_count_success)
|
150
187
|
# @yieldreturn (see #statsd_count_success)
|
151
188
|
# @return [void]
|
152
189
|
# @see #statsd_count_success
|
153
|
-
def statsd_count_if(method, name,
|
190
|
+
def statsd_count_if(method, name, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
191
|
+
sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg, prefix: nil, no_prefix: false)
|
192
|
+
|
154
193
|
add_to_method(method, name, :count_if) do
|
155
194
|
define_method(method) do |*args, &block|
|
156
195
|
begin
|
@@ -159,10 +198,21 @@ module StatsD
|
|
159
198
|
truthiness = false
|
160
199
|
raise
|
161
200
|
else
|
162
|
-
|
201
|
+
if block_given?
|
202
|
+
begin
|
203
|
+
truthiness = yield(result)
|
204
|
+
rescue
|
205
|
+
truthiness = false
|
206
|
+
end
|
207
|
+
end
|
163
208
|
result
|
164
209
|
ensure
|
165
|
-
|
210
|
+
if truthiness
|
211
|
+
key = StatsD::Instrument.generate_metric_name(name, self, *args)
|
212
|
+
prefix ||= StatsD.prefix
|
213
|
+
StatsD.increment(key, prefix: prefix, # rubocop:disable StatsD/MetricPrefixArgument
|
214
|
+
sample_rate: sample_rate, tags: tags, no_prefix: no_prefix)
|
215
|
+
end
|
166
216
|
end
|
167
217
|
end
|
168
218
|
end
|
@@ -177,10 +227,15 @@ module StatsD
|
|
177
227
|
# @param name (see #statsd_measure)
|
178
228
|
# @param metric_options (see #statsd_measure)
|
179
229
|
# @return [void]
|
180
|
-
def statsd_count(method, name,
|
230
|
+
def statsd_count(method, name, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
231
|
+
sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg, prefix: nil, no_prefix: false)
|
232
|
+
|
181
233
|
add_to_method(method, name, :count) do
|
182
234
|
define_method(method) do |*args, &block|
|
183
|
-
StatsD
|
235
|
+
key = StatsD::Instrument.generate_metric_name(name, self, *args)
|
236
|
+
prefix ||= StatsD.prefix
|
237
|
+
StatsD.increment(key, prefix: prefix, # rubocop:disable StatsD/MetricPrefixArgument
|
238
|
+
sample_rate: sample_rate, tags: tags, no_prefix: no_prefix)
|
184
239
|
super(*args, &block)
|
185
240
|
end
|
186
241
|
end
|
@@ -248,8 +303,13 @@ module StatsD
|
|
248
303
|
def add_to_method(method, name, action, &block)
|
249
304
|
instrumentation_module = statsd_instrumentation_for(method, name, action)
|
250
305
|
|
251
|
-
|
252
|
-
|
306
|
+
if instrumentation_module.method_defined?(method)
|
307
|
+
raise ArgumentError, "Already instrumented #{method} for #{self.name}"
|
308
|
+
end
|
309
|
+
|
310
|
+
unless method_defined?(method) || private_method_defined?(method)
|
311
|
+
raise ArgumentError, "could not find method #{method} for #{self.name}"
|
312
|
+
end
|
253
313
|
|
254
314
|
method_scope = method_visibility(method)
|
255
315
|
|
@@ -263,10 +323,9 @@ module StatsD
|
|
263
323
|
end
|
264
324
|
|
265
325
|
def method_visibility(method)
|
266
|
-
|
267
|
-
when private_method_defined?(method)
|
326
|
+
if private_method_defined?(method)
|
268
327
|
:private
|
269
|
-
|
328
|
+
elsif protected_method_defined?(method)
|
270
329
|
:protected
|
271
330
|
else
|
272
331
|
:public
|
@@ -275,49 +334,75 @@ module StatsD
|
|
275
334
|
end
|
276
335
|
|
277
336
|
attr_accessor :logger, :default_sample_rate, :prefix
|
278
|
-
attr_writer :backend
|
337
|
+
attr_writer :backend, :client
|
338
|
+
attr_reader :default_tags
|
339
|
+
|
340
|
+
def default_tags=(tags)
|
341
|
+
@default_tags = StatsD::Instrument::Metric.normalize_tags(tags)
|
342
|
+
end
|
279
343
|
|
280
344
|
def backend
|
281
345
|
@backend ||= StatsD::Instrument::Environment.default_backend
|
282
346
|
end
|
283
347
|
|
284
|
-
|
348
|
+
def client
|
349
|
+
@client ||= begin
|
350
|
+
require 'statsd/instrument/client'
|
351
|
+
StatsD::Instrument::Environment.from_env.default_client
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
# @!method measure(name, value = nil, sample_rate: nil, tags: nil, &block)
|
356
|
+
#
|
357
|
+
# Emits a timing metric
|
358
|
+
#
|
359
|
+
# @param [String] key The name of the metric.
|
360
|
+
# @param sample_rate (see #increment)
|
361
|
+
# @param tags (see #increment)
|
285
362
|
#
|
286
|
-
# @
|
287
|
-
#
|
288
|
-
#
|
289
|
-
#
|
290
|
-
#
|
291
|
-
# the key :as_dist will submit the value as a distribution instead of a timing
|
292
|
-
# (only supported by DataDog's implementation)
|
293
|
-
# @return [StatsD::Instrument::Metric] The metric that was sent to the backend.
|
363
|
+
# @example Providing a value directly
|
364
|
+
# start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
365
|
+
# do_something
|
366
|
+
# stop = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
|
367
|
+
# http_response = StatsD.measure('HTTP.call.duration', stop - start)
|
294
368
|
#
|
295
|
-
# @
|
296
|
-
#
|
369
|
+
# @example Providing a block to measure the duration of its execution
|
370
|
+
# http_response = StatsD.measure('HTTP.call.duration') do
|
371
|
+
# Net::HTTP.get(url)
|
372
|
+
# end
|
373
|
+
#
|
374
|
+
# @overload measure(key, value, sample_rate: nil, tags: nil)
|
375
|
+
# Emits a timing metric, by providing a duration in milliseconds.
|
376
|
+
#
|
377
|
+
# @param [Float] value The measured duration in milliseconds
|
378
|
+
# @return [void]
|
379
|
+
#
|
380
|
+
# @overload measure(key, sample_rate: nil, tags: nil, &block)
|
381
|
+
# Emits a timing metric, after measuring the execution duration of the
|
297
382
|
# block passed to this method.
|
298
|
-
#
|
299
|
-
# @
|
300
|
-
#
|
301
|
-
#
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
result = metric unless block_given?
|
317
|
-
result
|
383
|
+
#
|
384
|
+
# @yield `StatsD.measure` will yield the block and measure the duration. After the block
|
385
|
+
# returns, the duration in millisecond will be emitted as metric.
|
386
|
+
# @return The value that was returned by the block passed through.
|
387
|
+
def measure(
|
388
|
+
key, value_arg = nil, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
389
|
+
value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
|
390
|
+
prefix: StatsD.prefix, no_prefix: false, as_dist: false,
|
391
|
+
&block
|
392
|
+
)
|
393
|
+
# TODO: in the next version, hardcode this to :ms when the as_dist argument is dropped.
|
394
|
+
type = as_dist ? :d : :ms
|
395
|
+
prefix = nil if no_prefix
|
396
|
+
if block_given?
|
397
|
+
measure_latency(type, key, sample_rate: sample_rate, tags: tags, prefix: prefix, &block)
|
398
|
+
else
|
399
|
+
collect_metric(type, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
|
400
|
+
end
|
318
401
|
end
|
319
402
|
|
403
|
+
# @!method increment(name, value = 1, sample_rate: nil, tags: nil)
|
320
404
|
# Emits a counter metric.
|
405
|
+
#
|
321
406
|
# @param key [String] The name of the metric.
|
322
407
|
# @param value [Integer] The value to increment the counter by.
|
323
408
|
#
|
@@ -326,135 +411,226 @@ module StatsD
|
|
326
411
|
# The sample rate is part of the packet that is being sent to the server, and the server
|
327
412
|
# should know how to handle it.
|
328
413
|
#
|
329
|
-
# @param
|
330
|
-
#
|
331
|
-
|
332
|
-
|
414
|
+
# @param sample_rate [Float] (default: `StatsD.default_sample_rate`) The rate at which to sample
|
415
|
+
# this metric call. This value should be between 0 and 1. This value can be used to reduce
|
416
|
+
# the amount of network I/O (and CPU cycles) used for very frequent metrics.
|
417
|
+
#
|
418
|
+
# - A value of `0.1` means that only 1 out of 10 calls will be emitted; the other 9 will
|
419
|
+
# be short-circuited.
|
420
|
+
# - When set to `1`, every metric will be emitted.
|
421
|
+
# - If this parameter is not set, the default sample rate for this client will be used.
|
422
|
+
# @param tags [Array<String>, Hash<Symbol, String>] The tags to associate with this measurement.
|
423
|
+
# They can be provided as an array of strings, or a hash of key/value pairs.
|
424
|
+
# _Note:_ Tags are not supported by all implementations.
|
425
|
+
# @return [void]
|
426
|
+
def increment(
|
427
|
+
key, value_arg = 1, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
428
|
+
value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
|
429
|
+
prefix: StatsD.prefix, no_prefix: false
|
430
|
+
)
|
431
|
+
prefix = nil if no_prefix
|
432
|
+
collect_metric(:c, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
|
333
433
|
end
|
334
434
|
|
435
|
+
# @!method gauge(name, value, sample_rate: nil, tags: nil)
|
436
|
+
#
|
335
437
|
# Emits a gauge metric.
|
336
|
-
#
|
438
|
+
#
|
439
|
+
# @param key The name of the metric.
|
337
440
|
# @param value [Numeric] The current value to record.
|
338
|
-
# @param
|
339
|
-
# @
|
340
|
-
|
341
|
-
|
441
|
+
# @param sample_rate (see #increment)
|
442
|
+
# @param tags (see #increment)
|
443
|
+
# @return [void]
|
444
|
+
def gauge(
|
445
|
+
key, value_arg = nil, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
446
|
+
value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
|
447
|
+
prefix: StatsD.prefix, no_prefix: false
|
448
|
+
)
|
449
|
+
prefix = nil if no_prefix
|
450
|
+
collect_metric(:g, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
|
342
451
|
end
|
343
452
|
|
344
|
-
#
|
453
|
+
# @!method set(name, value, sample_rate: nil, tags: nil)
|
454
|
+
#
|
455
|
+
# Emits a set metric, which counts the number of distinct values that have occurred.
|
456
|
+
#
|
457
|
+
# @example Couning the number of unique visitors
|
458
|
+
# StatsD.set('visitors.unique', Current.user.id)
|
459
|
+
#
|
345
460
|
# @param key [String] The name of the metric.
|
346
461
|
# @param value [Numeric] The value to record.
|
347
|
-
# @param
|
462
|
+
# @param sample_rate (see #increment)
|
463
|
+
# @param tags (see #increment)
|
464
|
+
# @return [void]
|
465
|
+
def set(
|
466
|
+
key, value_arg = nil, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
467
|
+
value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
|
468
|
+
prefix: StatsD.prefix, no_prefix: false
|
469
|
+
)
|
470
|
+
prefix = nil if no_prefix
|
471
|
+
collect_metric(:s, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
|
472
|
+
end
|
473
|
+
|
474
|
+
# @!method histogram(name, value, sample_rate: nil, tags: nil)
|
475
|
+
#
|
476
|
+
# Emits a histogram metric.
|
477
|
+
#
|
478
|
+
# @param key The name of the metric.
|
479
|
+
# @param value [Numeric] The value to record.
|
480
|
+
# @param sample_rate (see #increment)
|
481
|
+
# @param tags (see #increment)
|
348
482
|
# @return (see #collect_metric)
|
349
483
|
# @note Supported by the datadog implementation only.
|
350
|
-
def histogram(
|
351
|
-
|
484
|
+
def histogram(
|
485
|
+
key, value_arg = nil, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
486
|
+
value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
|
487
|
+
prefix: StatsD.prefix, no_prefix: false
|
488
|
+
)
|
489
|
+
prefix = nil if no_prefix
|
490
|
+
collect_metric(:h, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
|
352
491
|
end
|
353
492
|
|
493
|
+
# @!method distribution(name, value = nil, sample_rate: nil, tags: nil, &block)
|
494
|
+
#
|
354
495
|
# Emits a distribution metric.
|
355
|
-
#
|
356
|
-
# @param
|
357
|
-
# @param
|
358
|
-
# @
|
359
|
-
#
|
496
|
+
#
|
497
|
+
# @param [String] key The name of the metric.
|
498
|
+
# @param sample_rate (see #increment)
|
499
|
+
# @param tags (see #increment)
|
500
|
+
#
|
501
|
+
# @note Supported by the datadog implementation only.
|
502
|
+
# @example
|
503
|
+
# http_response = StatsD.distribution('HTTP.call.duration') do
|
504
|
+
# Net::HTTP.get(url)
|
505
|
+
# end
|
506
|
+
#
|
507
|
+
# @overload distribution(name, value, sample_rate: nil, tags: nil)
|
508
|
+
#
|
509
|
+
# Emits a distribution metric, given a provided value to record.
|
510
|
+
#
|
511
|
+
# @param [Numeric] value The value to record.
|
512
|
+
# @return [void]
|
360
513
|
#
|
361
514
|
# @overload distribution(key, metric_options = {}, &block)
|
362
|
-
#
|
363
|
-
#
|
364
|
-
#
|
365
|
-
# @
|
366
|
-
#
|
367
|
-
# @return The value that was
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
result
|
515
|
+
#
|
516
|
+
# Emits a distribution metric for the duration of the provided block, in milliseconds.
|
517
|
+
#
|
518
|
+
# @yield `StatsD.distribution` will yield the block and measure the duration. After
|
519
|
+
# the block returns, the duration in millisecond will be emitted as metric.
|
520
|
+
# @return The value that was returned by the block passed through.
|
521
|
+
def distribution(
|
522
|
+
key, value_arg = nil, deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
523
|
+
value: value_arg, sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
|
524
|
+
prefix: StatsD.prefix, no_prefix: false,
|
525
|
+
&block
|
526
|
+
)
|
527
|
+
prefix = nil if no_prefix
|
528
|
+
if block_given?
|
529
|
+
measure_latency(:d, key, sample_rate: sample_rate, tags: tags, prefix: prefix, &block)
|
530
|
+
else
|
531
|
+
collect_metric(:d, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
|
532
|
+
end
|
381
533
|
end
|
382
534
|
|
535
|
+
# @!method key_value(name, value)
|
536
|
+
#
|
383
537
|
# Emits a key/value metric.
|
538
|
+
#
|
384
539
|
# @param key [String] The name of the metric.
|
385
540
|
# @param value [Numeric] The value to record.
|
386
|
-
# @
|
387
|
-
#
|
541
|
+
# @return [void]
|
542
|
+
#
|
388
543
|
# @note Supported by the statsite implementation only.
|
389
|
-
def key_value(
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
# @param value [Numeric] The value to record.
|
396
|
-
# @param metric_options [Hash] (default: {}) Metric options
|
397
|
-
# @return (see #collect_metric)
|
398
|
-
# @note Supported by the datadog implementation only.
|
399
|
-
def set(key, value, *metric_options)
|
400
|
-
collect_metric(:s, key, value, metric_options)
|
544
|
+
def key_value(
|
545
|
+
key, value_arg = nil, deprecated_sample_rate_arg = nil,
|
546
|
+
value: value_arg, sample_rate: deprecated_sample_rate_arg, no_prefix: false
|
547
|
+
)
|
548
|
+
prefix = nil if no_prefix
|
549
|
+
collect_metric(:kv, key, value, sample_rate: sample_rate, prefix: prefix)
|
401
550
|
end
|
402
551
|
|
403
|
-
#
|
404
|
-
#
|
405
|
-
#
|
406
|
-
#
|
407
|
-
# @
|
408
|
-
# @
|
409
|
-
|
410
|
-
|
552
|
+
# @!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
|
553
|
+
#
|
554
|
+
# Emits an event.
|
555
|
+
#
|
556
|
+
# @param title [String] Title of the event. A configured prefix may be applied to this title.
|
557
|
+
# @param text [String] Body of the event. Can contain newlines.
|
558
|
+
# @param [String] hostname The hostname to associate with the event.
|
559
|
+
# @param [Time] timestamp The moment the status of the service was checkes. Defaults to now.
|
560
|
+
# @param [String] aggregation_key A key to aggregate similar events into groups.
|
561
|
+
# @param [String] priority The event's priority, either `"low"` or `"normal"` (default).
|
562
|
+
# @param [String] source_type_name The source type.
|
563
|
+
# @param [String] alert_type The type of alert. Either `"info"` (default), `"warning"`, `"error"`, or `"success"`.
|
564
|
+
# @param tags (see #increment)
|
565
|
+
# @return [void]
|
566
|
+
#
|
567
|
+
# @note Supported by the Datadog implementation only.
|
568
|
+
def event(
|
569
|
+
title, text,
|
570
|
+
deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
571
|
+
sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
|
572
|
+
prefix: StatsD.prefix, no_prefix: false,
|
573
|
+
hostname: nil, date_happened: nil, timestamp: date_happened,
|
574
|
+
aggregation_key: nil, priority: nil, source_type_name: nil, alert_type: nil,
|
575
|
+
**_ignored
|
576
|
+
)
|
577
|
+
prefix = nil if no_prefix
|
578
|
+
collect_metric(:_e, title, text, sample_rate: sample_rate, tags: tags, prefix: prefix, metadata: {
|
579
|
+
hostname: hostname, timestamp: timestamp, aggregation_key: aggregation_key,
|
580
|
+
priority: priority, source_type_name: source_type_name, alert_type: alert_type
|
581
|
+
})
|
411
582
|
end
|
412
583
|
|
413
|
-
#
|
414
|
-
#
|
415
|
-
#
|
416
|
-
#
|
417
|
-
# @
|
418
|
-
# @
|
419
|
-
|
420
|
-
|
584
|
+
# @!method service_check(name, status, tags: nil, hostname: nil, timestamp: nil, message: nil)
|
585
|
+
#
|
586
|
+
# Emits a service check.
|
587
|
+
#
|
588
|
+
# @param [String] name Name of the service. A configured prefix may be applied to this title.
|
589
|
+
# @param [Symbol] status Current status of the service. Either `:ok`, `:warning`, `:critical`, or `:unknown`.
|
590
|
+
# @param [String] hostname The hostname to associate with the event.
|
591
|
+
# @param [Time] timestamp The moment the status of the service was checkes. Defaults to now.
|
592
|
+
# @param [String] message A message that describes the current status.
|
593
|
+
# @param tags (see #increment)
|
594
|
+
# @return [void]
|
595
|
+
#
|
596
|
+
# @note Supported by the Datadog implementation only.
|
597
|
+
def service_check(
|
598
|
+
name, status,
|
599
|
+
deprecated_sample_rate_arg = nil, deprecated_tags_arg = nil,
|
600
|
+
sample_rate: deprecated_sample_rate_arg, tags: deprecated_tags_arg,
|
601
|
+
prefix: StatsD.prefix, no_prefix: false,
|
602
|
+
hostname: nil, timestamp: nil, message: nil, **_ignored
|
603
|
+
)
|
604
|
+
prefix = nil if no_prefix
|
605
|
+
collect_metric(:_sc, name, status, sample_rate: sample_rate, prefix: prefix, tags: tags, metadata: {
|
606
|
+
hostname: hostname, timestamp: timestamp, message: message
|
607
|
+
})
|
421
608
|
end
|
422
609
|
|
423
610
|
private
|
424
611
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
hash = {}
|
434
|
-
args.each_with_index do |value, index|
|
435
|
-
hash[order[index]] = value
|
612
|
+
def measure_latency(type, key, sample_rate:, tags:, prefix:)
|
613
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
614
|
+
begin
|
615
|
+
yield
|
616
|
+
ensure
|
617
|
+
# Ensure catches both a raised exception and a return in the invoked block
|
618
|
+
value = 1000.0 * (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start)
|
619
|
+
collect_metric(type, key, value, sample_rate: sample_rate, tags: tags, prefix: prefix)
|
436
620
|
end
|
437
|
-
|
438
|
-
return hash
|
439
|
-
end
|
440
|
-
|
441
|
-
def parse_options(value, metric_options)
|
442
|
-
if value.is_a?(Hash) && metric_options.empty?
|
443
|
-
metric_options = [value]
|
444
|
-
value = value.fetch(:value, nil)
|
445
|
-
end
|
446
|
-
[value, metric_options]
|
447
621
|
end
|
448
622
|
|
449
623
|
# Instantiates a metric, and sends it to the backend for further processing.
|
450
624
|
# @param options (see StatsD::Instrument::Metric#initialize)
|
451
|
-
# @return [
|
452
|
-
def collect_metric(type, name, value,
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
625
|
+
# @return [void]
|
626
|
+
def collect_metric(type, name, value, sample_rate:, tags: nil, prefix:, metadata: nil)
|
627
|
+
sample_rate ||= default_sample_rate
|
628
|
+
name = "#{prefix}.#{name}" if prefix
|
629
|
+
|
630
|
+
metric = StatsD::Instrument::Metric.new(type: type, name: name, value: value,
|
631
|
+
sample_rate: sample_rate, tags: tags, metadata: metadata)
|
632
|
+
backend.collect_metric(metric)
|
633
|
+
metric # TODO: return `nil` in the next major version
|
458
634
|
end
|
459
635
|
end
|
460
636
|
|
@@ -466,4 +642,5 @@ require 'statsd/instrument/helpers'
|
|
466
642
|
require 'statsd/instrument/assertions'
|
467
643
|
require 'statsd/instrument/metric_expectation'
|
468
644
|
require 'statsd/instrument/matchers' if defined?(::RSpec)
|
469
|
-
require 'statsd/instrument/railtie' if defined?(Rails)
|
645
|
+
require 'statsd/instrument/railtie' if defined?(::Rails::Railtie)
|
646
|
+
require 'statsd/instrument/strict' if ENV['STATSD_STRICT_MODE']
|