statsd-instrument 3.5.9 → 3.5.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/lint.yml +1 -1
- data/CHANGELOG.md +8 -0
- data/Gemfile +1 -1
- data/bin/rake +4 -2
- data/bin/rubocop +4 -2
- data/lib/statsd/instrument/batched_udp_sink.rb +6 -6
- data/lib/statsd/instrument/client.rb +44 -23
- data/lib/statsd/instrument/datagram.rb +1 -1
- data/lib/statsd/instrument/datagram_builder.rb +9 -7
- data/lib/statsd/instrument/dogstatsd_datagram_builder.rb +4 -3
- data/lib/statsd/instrument/helpers.rb +24 -22
- data/lib/statsd/instrument/rubocop/measure_as_dist_argument.rb +1 -1
- data/lib/statsd/instrument/rubocop/metaprogramming_positional_arguments.rb +1 -1
- data/lib/statsd/instrument/rubocop/metric_prefix_argument.rb +1 -1
- data/lib/statsd/instrument/rubocop/metric_return_value.rb +1 -1
- data/lib/statsd/instrument/rubocop/metric_value_keyword_argument.rb +1 -1
- data/lib/statsd/instrument/rubocop/positional_arguments.rb +49 -47
- data/lib/statsd/instrument/rubocop/singleton_configuration.rb +1 -1
- data/lib/statsd/instrument/rubocop/splat_arguments.rb +1 -1
- data/lib/statsd/instrument/rubocop.rb +18 -5
- data/lib/statsd/instrument/udp_sink.rb +5 -3
- data/lib/statsd/instrument/version.rb +1 -1
- data/lib/statsd/instrument.rb +51 -37
- data/test/assertions_test.rb +1 -1
- data/test/client_test.rb +20 -2
- data/test/dogstatsd_datagram_builder_test.rb +24 -7
- data/test/helpers/rubocop_helper.rb +23 -10
- data/test/statsd_instrumentation_test.rb +10 -4
- data/test/test_helper.rb +5 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9124bb941a7f03e9d64ea7969fb4b2f47b44bae2ca4ec56fe3f0653bb3df8a4
|
4
|
+
data.tar.gz: a70c8e54c4cbd9e5b24981c613ca674d89deb2ba8b7087447ee0cc56faf4d5d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20a8b1a8308e5dd2862b367e0e3321b9255039c1887d9830a608812eadc2f29e4b6f916b3245293b7d200ac148f89179712492a024fb2bedd3e36887eb20c0bb
|
7
|
+
data.tar.gz: 797ca0e4d0f22ed3cbe87acae0fba3a434c36b8b5059bfb7808c93498c0e028ee9b64af1f4b3e06e796e36ba8053109c66ed4c619de7fb672107818bda7024b5
|
data/.github/workflows/lint.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,14 @@ section below.
|
|
6
6
|
|
7
7
|
## Unreleased changes
|
8
8
|
|
9
|
+
## Version 3.5.11
|
10
|
+
|
11
|
+
- Fix a bug where passing `nil` to `clone_with_options` did not overwrite existing values
|
12
|
+
|
13
|
+
## Version 3.5.10
|
14
|
+
|
15
|
+
- Fix rubocop 1.30 compatibilitty
|
16
|
+
|
9
17
|
## Version 3.5.9
|
10
18
|
|
11
19
|
- Fix dynamic tags being evaluated only once.
|
data/Gemfile
CHANGED
data/bin/rake
CHANGED
@@ -9,8 +9,10 @@
|
|
9
9
|
#
|
10
10
|
|
11
11
|
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
-
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
+
"../../Gemfile",
|
14
|
+
Pathname.new(__FILE__).realpath,
|
15
|
+
)
|
14
16
|
|
15
17
|
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
18
|
|
data/bin/rubocop
CHANGED
@@ -9,8 +9,10 @@
|
|
9
9
|
#
|
10
10
|
|
11
11
|
require "pathname"
|
12
|
-
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
-
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(
|
13
|
+
"../../Gemfile",
|
14
|
+
Pathname.new(__FILE__).realpath,
|
15
|
+
)
|
14
16
|
|
15
17
|
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
18
|
|
@@ -10,14 +10,14 @@ module StatsD
|
|
10
10
|
# https://docs.datadoghq.com/developers/dogstatsd/high_throughput/?code-lang=ruby#ensure-proper-packet-sizes
|
11
11
|
DEFAULT_MAX_PACKET_SIZE = 1472
|
12
12
|
|
13
|
-
def self.for_addr(addr, **kwargs)
|
14
|
-
host, port_as_string = addr.split(":", 2)
|
15
|
-
new(host, Integer(port_as_string), **kwargs)
|
16
|
-
end
|
17
|
-
|
18
13
|
attr_reader :host, :port
|
19
14
|
|
20
15
|
class << self
|
16
|
+
def for_addr(addr, **kwargs)
|
17
|
+
host, port_as_string = addr.split(":", 2)
|
18
|
+
new(host, Integer(port_as_string), **kwargs)
|
19
|
+
end
|
20
|
+
|
21
21
|
def finalize(dispatcher)
|
22
22
|
proc { dispatcher.shutdown }
|
23
23
|
end
|
@@ -122,7 +122,7 @@ module StatsD
|
|
122
122
|
|
123
123
|
packet << next_datagram
|
124
124
|
next_datagram = nil
|
125
|
-
|
125
|
+
if packet.bytesize <= @max_packet_size
|
126
126
|
while (next_datagram = @buffer.pop_nonblock)
|
127
127
|
if @max_packet_size - packet.bytesize - 1 > next_datagram.bytesize
|
128
128
|
packet << NEWLINE << next_datagram
|
@@ -338,8 +338,14 @@ module StatsD
|
|
338
338
|
#
|
339
339
|
# @note Supported by the Datadog implementation only.
|
340
340
|
def service_check(name, status, timestamp: nil, hostname: nil, tags: nil, message: nil, no_prefix: false)
|
341
|
-
emit(datagram_builder(no_prefix: no_prefix)._sc(
|
342
|
-
|
341
|
+
emit(datagram_builder(no_prefix: no_prefix)._sc(
|
342
|
+
name,
|
343
|
+
status,
|
344
|
+
timestamp: timestamp,
|
345
|
+
hostname: hostname,
|
346
|
+
tags: tags,
|
347
|
+
message: message,
|
348
|
+
))
|
343
349
|
end
|
344
350
|
|
345
351
|
# Emits an event. An event represents any record of activity noteworthy for engineers.
|
@@ -359,11 +365,21 @@ module StatsD
|
|
359
365
|
def event(title, text, timestamp: nil, hostname: nil, aggregation_key: nil, priority: nil,
|
360
366
|
source_type_name: nil, alert_type: nil, tags: nil, no_prefix: false)
|
361
367
|
|
362
|
-
emit(datagram_builder(no_prefix: no_prefix)._e(
|
363
|
-
|
364
|
-
|
368
|
+
emit(datagram_builder(no_prefix: no_prefix)._e(
|
369
|
+
title,
|
370
|
+
text,
|
371
|
+
timestamp: timestamp,
|
372
|
+
hostname: hostname,
|
373
|
+
tags: tags,
|
374
|
+
aggregation_key: aggregation_key,
|
375
|
+
priority: priority,
|
376
|
+
source_type_name: source_type_name,
|
377
|
+
alert_type: alert_type,
|
378
|
+
))
|
365
379
|
end
|
366
380
|
|
381
|
+
NO_CHANGE = Object.new
|
382
|
+
|
367
383
|
# Instantiates a new StatsD client that uses the settings of the current client,
|
368
384
|
# except for the provided overrides.
|
369
385
|
#
|
@@ -372,32 +388,37 @@ module StatsD
|
|
372
388
|
# will be disposed after the block returns
|
373
389
|
# @return The return value of the block will be passed on as return value.
|
374
390
|
def with_options(
|
375
|
-
sink:
|
376
|
-
prefix:
|
377
|
-
default_sample_rate:
|
378
|
-
default_tags:
|
379
|
-
datagram_builder_class:
|
391
|
+
sink: NO_CHANGE,
|
392
|
+
prefix: NO_CHANGE,
|
393
|
+
default_sample_rate: NO_CHANGE,
|
394
|
+
default_tags: NO_CHANGE,
|
395
|
+
datagram_builder_class: NO_CHANGE
|
380
396
|
)
|
381
|
-
client = clone_with_options(
|
382
|
-
|
383
|
-
|
397
|
+
client = clone_with_options(
|
398
|
+
sink: sink,
|
399
|
+
prefix: prefix,
|
400
|
+
default_sample_rate: default_sample_rate,
|
401
|
+
default_tags: default_tags,
|
402
|
+
datagram_builder_class: datagram_builder_class,
|
403
|
+
)
|
384
404
|
|
385
405
|
yield(client)
|
386
406
|
end
|
387
407
|
|
388
408
|
def clone_with_options(
|
389
|
-
sink:
|
390
|
-
prefix:
|
391
|
-
default_sample_rate:
|
392
|
-
default_tags:
|
393
|
-
datagram_builder_class:
|
409
|
+
sink: NO_CHANGE,
|
410
|
+
prefix: NO_CHANGE,
|
411
|
+
default_sample_rate: NO_CHANGE,
|
412
|
+
default_tags: NO_CHANGE,
|
413
|
+
datagram_builder_class: NO_CHANGE
|
394
414
|
)
|
395
415
|
self.class.new(
|
396
|
-
sink: sink
|
397
|
-
prefix: prefix
|
398
|
-
default_sample_rate: default_sample_rate
|
399
|
-
default_tags: default_tags
|
400
|
-
datagram_builder_class:
|
416
|
+
sink: sink == NO_CHANGE ? @sink : sink,
|
417
|
+
prefix: prefix == NO_CHANGE ? @prefix : prefix,
|
418
|
+
default_sample_rate: default_sample_rate == NO_CHANGE ? @default_sample_rate : default_sample_rate,
|
419
|
+
default_tags: default_tags == NO_CHANGE ? @default_tags : default_tags,
|
420
|
+
datagram_builder_class:
|
421
|
+
datagram_builder_class == NO_CHANGE ? @datagram_builder_class : datagram_builder_class,
|
401
422
|
)
|
402
423
|
end
|
403
424
|
|
@@ -5,16 +5,18 @@ module StatsD
|
|
5
5
|
# @note This class is part of the new Client implementation that is intended
|
6
6
|
# to become the new default in the next major release of this library.
|
7
7
|
class DatagramBuilder
|
8
|
-
|
9
|
-
types
|
10
|
-
|
11
|
-
|
8
|
+
class << self
|
9
|
+
def unsupported_datagram_types(*types)
|
10
|
+
types.each do |type|
|
11
|
+
define_method(type) do |_, _, _, _|
|
12
|
+
raise NotImplementedError, "Type #{type} metrics are not supported by #{self.class.name}."
|
13
|
+
end
|
12
14
|
end
|
13
15
|
end
|
14
|
-
end
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
def datagram_class
|
18
|
+
StatsD::Instrument::Datagram
|
19
|
+
end
|
18
20
|
end
|
19
21
|
|
20
22
|
def initialize(prefix: nil, default_tags: nil)
|
@@ -7,10 +7,11 @@ module StatsD
|
|
7
7
|
class DogStatsDDatagramBuilder < StatsD::Instrument::DatagramBuilder
|
8
8
|
unsupported_datagram_types :kv
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
class << self
|
11
|
+
def datagram_class
|
12
|
+
StatsD::Instrument::DogStatsDDatagram
|
13
|
+
end
|
12
14
|
end
|
13
|
-
|
14
15
|
def latency_metric_type
|
15
16
|
:d
|
16
17
|
end
|
@@ -11,32 +11,34 @@ module StatsD
|
|
11
11
|
# For backwards compatibility
|
12
12
|
alias_method :capture_statsd_calls, :capture_statsd_datagrams
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
tags
|
21
|
-
|
22
|
-
tags
|
23
|
-
|
24
|
-
|
14
|
+
class << self
|
15
|
+
def add_tag(tags, key, value)
|
16
|
+
tags = tags.dup || {}
|
17
|
+
|
18
|
+
if tags.is_a?(String)
|
19
|
+
tags = tags.empty? ? "#{key}:#{value}" : "#{tags},#{key}:#{value}"
|
20
|
+
elsif tags.is_a?(Array)
|
21
|
+
tags << "#{key}:#{value}"
|
22
|
+
elsif tags.is_a?(Hash)
|
23
|
+
tags[key] = value
|
24
|
+
else
|
25
|
+
raise ArgumentError, "add_tag only supports string, array or hash, #{tags.class} provided"
|
26
|
+
end
|
27
|
+
|
28
|
+
tags
|
25
29
|
end
|
26
30
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
client ||= StatsD.singleton_client
|
32
|
-
client&.prefix ? "#{client.prefix}.#{metric_name}" : metric_name
|
33
|
-
end
|
31
|
+
def prefix_metric(metric_name, client: nil)
|
32
|
+
client ||= StatsD.singleton_client
|
33
|
+
client&.prefix ? "#{client.prefix}.#{metric_name}" : metric_name
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
def prefixed_metric?(metric_name, client: nil)
|
37
|
+
client ||= StatsD.singleton_client
|
38
|
+
return false unless client&.prefix
|
38
39
|
|
39
|
-
|
40
|
+
metric_name =~ /\A#{Regexp.escape(client.prefix)}\./
|
41
|
+
end
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../rubocop" unless defined?(RuboCop::Cop::StatsD)
|
4
4
|
|
@@ -14,7 +14,8 @@ module RuboCop
|
|
14
14
|
# --only StatsD/PositionalArguments
|
15
15
|
#
|
16
16
|
# This cop can autocorrect some offenses it finds, but not all of them.
|
17
|
-
class PositionalArguments <
|
17
|
+
class PositionalArguments < Base
|
18
|
+
extend AutoCorrector
|
18
19
|
include RuboCop::Cop::StatsD
|
19
20
|
|
20
21
|
MSG = "Use keyword arguments for StatsD calls"
|
@@ -31,7 +32,9 @@ module RuboCop
|
|
31
32
|
if metric_method?(node) && node.arguments.length >= 3
|
32
33
|
case node.arguments[2].type
|
33
34
|
when *REFUSED_ARGUMENT_TYPES
|
34
|
-
add_offense(node)
|
35
|
+
add_offense(node) do |corrector|
|
36
|
+
autocorrect(corrector, node)
|
37
|
+
end
|
35
38
|
when *ACCEPTED_ARGUMENT_TYPES
|
36
39
|
nil
|
37
40
|
else
|
@@ -40,57 +43,56 @@ module RuboCop
|
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
43
|
-
def autocorrect(node)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
46
|
+
def autocorrect(corrector, node)
|
47
|
+
positional_arguments = if node.arguments.last.type == :block_pass
|
48
|
+
node.arguments[2...node.arguments.length - 1]
|
49
|
+
else
|
50
|
+
node.arguments[2...node.arguments.length]
|
51
|
+
end
|
50
52
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
53
|
+
case positional_arguments[0].type
|
54
|
+
when *UNKNOWN_ARGUMENT_TYPES
|
55
|
+
# We don't know whether the method returns a hash, in which case it would be interpreted
|
56
|
+
# as keyword arguments. In this case, the fix would be to add a keyword splat:
|
57
|
+
#
|
58
|
+
# `StatsD.instrument('foo', 1, method_call)`
|
59
|
+
# => `StatsD.instrument('foo', 1, **method_call)`
|
60
|
+
#
|
61
|
+
# However, it's also possible this method returns a sample rate, in which case the fix
|
62
|
+
# above will not do the right thing.
|
63
|
+
#
|
64
|
+
# `StatsD.instrument('foo', 1, SAMPLE_RATE_CONSTANT)`
|
65
|
+
# => `StatsD.instrument('foo', 1, sample_rate: SAMPLE_RATE_CONSTANT)`
|
66
|
+
#
|
67
|
+
# Because of this, we will not auto-correct and let the user fix the issue manually.
|
68
|
+
nil
|
67
69
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
70
|
+
when *POSITIONAL_ARGUMENT_TYPES
|
71
|
+
value_argument = node.arguments[1]
|
72
|
+
from = value_argument.source_range.end_pos
|
73
|
+
to = positional_arguments.last.source_range.end_pos
|
74
|
+
range = Parser::Source::Range.new(node.source_range.source_buffer, from, to)
|
75
|
+
corrector.remove(range)
|
74
76
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
keyword_arguments = []
|
78
|
+
sample_rate = positional_arguments[0]
|
79
|
+
if sample_rate && sample_rate.type != :nil
|
80
|
+
keyword_arguments << "sample_rate: #{sample_rate.source}"
|
81
|
+
end
|
80
82
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
83
|
+
tags = positional_arguments[1]
|
84
|
+
if tags && tags.type != :nil
|
85
|
+
keyword_arguments << if tags.type == :hash && tags.source[0] != "{"
|
86
|
+
"tags: { #{tags.source} }"
|
87
|
+
else
|
88
|
+
"tags: #{tags.source}"
|
88
89
|
end
|
90
|
+
end
|
89
91
|
|
90
|
-
|
91
|
-
|
92
|
-
end
|
92
|
+
unless keyword_arguments.empty?
|
93
|
+
corrector.insert_after(value_argument.source_range, ", #{keyword_arguments.join(", ")}")
|
93
94
|
end
|
95
|
+
|
94
96
|
end
|
95
97
|
end
|
96
98
|
end
|
@@ -5,11 +5,24 @@ module RuboCop
|
|
5
5
|
module StatsD
|
6
6
|
METRIC_METHODS = [:increment, :gauge, :measure, :set, :histogram, :distribution, :key_value]
|
7
7
|
|
8
|
-
METAPROGRAMMING_METHODS = [
|
9
|
-
|
8
|
+
METAPROGRAMMING_METHODS = [
|
9
|
+
:statsd_measure,
|
10
|
+
:statsd_distribution,
|
11
|
+
:statsd_count_success,
|
12
|
+
:statsd_count_if,
|
13
|
+
:statsd_count,
|
14
|
+
]
|
10
15
|
|
11
|
-
SINGLETON_CONFIGURATION_METHODS = [
|
12
|
-
|
16
|
+
SINGLETON_CONFIGURATION_METHODS = [
|
17
|
+
:backend,
|
18
|
+
:"backend=",
|
19
|
+
:prefix,
|
20
|
+
:"prefix=",
|
21
|
+
:default_tags,
|
22
|
+
:"default_tags=",
|
23
|
+
:default_sample_rate,
|
24
|
+
:"default_sample_rate=",
|
25
|
+
]
|
13
26
|
|
14
27
|
private
|
15
28
|
|
@@ -38,7 +51,7 @@ module RuboCop
|
|
38
51
|
end
|
39
52
|
|
40
53
|
def keyword_arguments(node)
|
41
|
-
return
|
54
|
+
return if node.arguments.empty?
|
42
55
|
|
43
56
|
last_argument = if node.arguments.last&.type == :block_pass
|
44
57
|
node.arguments[node.arguments.length - 2]
|
@@ -5,9 +5,11 @@ module StatsD
|
|
5
5
|
# @note This class is part of the new Client implementation that is intended
|
6
6
|
# to become the new default in the next major release of this library.
|
7
7
|
class UDPSink
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
class << self
|
9
|
+
def for_addr(addr)
|
10
|
+
host, port_as_string = addr.split(":", 2)
|
11
|
+
new(host, Integer(port_as_string))
|
12
|
+
end
|
11
13
|
end
|
12
14
|
|
13
15
|
attr_reader :host, :port
|
data/lib/statsd/instrument.rb
CHANGED
@@ -27,42 +27,44 @@ module StatsD
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
name
|
35
|
-
|
30
|
+
class << self
|
31
|
+
# Generates a metric name for an instrumented method.
|
32
|
+
# @private
|
33
|
+
# @return [String]
|
34
|
+
def generate_metric_name(name, callee, *args)
|
35
|
+
name.respond_to?(:call) ? name.call(callee, args).gsub("::", ".") : name.gsub("::", ".")
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
# Generates the tags for an instrumented method.
|
39
|
+
# @private
|
40
|
+
# @return [Array[String]]
|
41
|
+
def generate_tags(tags, callee, *args)
|
42
|
+
return if tags.nil?
|
42
43
|
|
43
|
-
|
44
|
-
|
44
|
+
tags.respond_to?(:call) ? tags.call(callee, args) : tags
|
45
|
+
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
47
|
+
# Even though this method is considered private, and is no longer used internally,
|
48
|
+
# applications in the wild rely on it. As a result, we cannot remove this method
|
49
|
+
# until the next major version.
|
50
|
+
#
|
51
|
+
# @deprecated Use Process.clock_gettime(Process::CLOCK_MONOTONIC) instead.
|
52
|
+
def current_timestamp
|
53
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
54
|
+
end
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
56
|
+
# Even though this method is considered private, and is no longer used internally,
|
57
|
+
# applications in the wild rely on it. As a result, we cannot remove this method
|
58
|
+
# until the next major version.
|
59
|
+
#
|
60
|
+
# @deprecated You can implement similar functionality yourself using
|
61
|
+
# `Process.clock_gettime(Process::CLOCK_MONOTONIC)`. Think about what will
|
62
|
+
# happen if an exception happens during the block execution though.
|
63
|
+
def duration
|
64
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
65
|
+
yield
|
66
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
67
|
+
end
|
66
68
|
end
|
67
69
|
|
68
70
|
# Adds execution duration instrumentation to a method as a timing.
|
@@ -294,7 +296,12 @@ module StatsD
|
|
294
296
|
if instrumentation_module.respond_to?(:ruby2_keywords, true)
|
295
297
|
instrumentation_module.send(:ruby2_keywords, method)
|
296
298
|
end
|
297
|
-
|
299
|
+
|
300
|
+
if self < instrumentation_module
|
301
|
+
return
|
302
|
+
end
|
303
|
+
|
304
|
+
prepend(instrumentation_module)
|
298
305
|
end
|
299
306
|
|
300
307
|
def remove_from_method(method, name, action)
|
@@ -358,8 +365,15 @@ module StatsD
|
|
358
365
|
# @!method service_check(name, status, tags: nil, hostname: nil, timestamp: nil, message: nil)
|
359
366
|
# (see StatsD::Instrument::Client#service_check)
|
360
367
|
|
361
|
-
def_delegators :singleton_client,
|
362
|
-
:
|
368
|
+
def_delegators :singleton_client,
|
369
|
+
:increment,
|
370
|
+
:gauge,
|
371
|
+
:set,
|
372
|
+
:measure,
|
373
|
+
:histogram,
|
374
|
+
:distribution,
|
375
|
+
:event,
|
376
|
+
:service_check
|
363
377
|
|
364
378
|
private
|
365
379
|
|
@@ -385,6 +399,6 @@ require "statsd/instrument/environment"
|
|
385
399
|
require "statsd/instrument/helpers"
|
386
400
|
require "statsd/instrument/assertions"
|
387
401
|
require "statsd/instrument/expectation"
|
388
|
-
require "statsd/instrument/matchers" if defined?(
|
389
|
-
require "statsd/instrument/railtie" if defined?(
|
402
|
+
require "statsd/instrument/matchers" if defined?(RSpec)
|
403
|
+
require "statsd/instrument/railtie" if defined?(Rails::Railtie)
|
390
404
|
require "statsd/instrument/strict" if ENV["STATSD_STRICT_MODE"]
|
data/test/assertions_test.rb
CHANGED
@@ -89,7 +89,7 @@ class AssertionsTest < Minitest::Test
|
|
89
89
|
assert_equal(assertion.message, "No StatsD calls for metric prefix.counter expected.")
|
90
90
|
|
91
91
|
@test_case.expects(:warn).with(
|
92
|
-
"`assert_no_statsd_calls` will prefix metrics by default. `prefix.counter` skipped due to existing prefix."
|
92
|
+
"`assert_no_statsd_calls` will prefix metrics by default. `prefix.counter` skipped due to existing prefix.",
|
93
93
|
)
|
94
94
|
assertion = assert_raises(Minitest::Assertion) do
|
95
95
|
@test_case.assert_no_statsd_calls("prefix.counter", client: client) do
|
data/test/client_test.rb
CHANGED
@@ -48,8 +48,12 @@ class ClientTest < Minitest::Test
|
|
48
48
|
"STATSD_IMPLEMENTATION" => "statsd",
|
49
49
|
"STATSD_ADDR" => "1.2.3.4:8125",
|
50
50
|
)
|
51
|
-
client = StatsD::Instrument::Client.from_env(
|
52
|
-
|
51
|
+
client = StatsD::Instrument::Client.from_env(
|
52
|
+
env,
|
53
|
+
prefix: "bar",
|
54
|
+
implementation: "dogstatsd",
|
55
|
+
sink: StatsD::Instrument::NullSink.new,
|
56
|
+
)
|
53
57
|
|
54
58
|
assert_equal(0.1, client.default_sample_rate)
|
55
59
|
assert_equal("bar", client.prefix)
|
@@ -219,4 +223,18 @@ class ClientTest < Minitest::Test
|
|
219
223
|
original_client.increment("metric")
|
220
224
|
client_with_other_options.increment("metric")
|
221
225
|
end
|
226
|
+
|
227
|
+
def test_clone_can_remove_prefix
|
228
|
+
# Both clients will use the same sink.
|
229
|
+
mock_sink = mock("sink")
|
230
|
+
mock_sink.stubs(:sample?).returns(true)
|
231
|
+
mock_sink.expects(:<<).with("foo.metric:1|c").returns(mock_sink)
|
232
|
+
mock_sink.expects(:<<).with("metric:1|c").returns(mock_sink)
|
233
|
+
|
234
|
+
original_client = StatsD::Instrument::Client.new(sink: mock_sink, prefix: "foo")
|
235
|
+
client_with_other_options = original_client.clone_with_options(prefix: nil)
|
236
|
+
|
237
|
+
original_client.increment("metric")
|
238
|
+
client_with_other_options.increment("metric")
|
239
|
+
end
|
222
240
|
end
|
@@ -21,8 +21,14 @@ class DogStatsDDatagramBuilderTest < Minitest::Test
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def test_complex_service_check
|
24
|
-
datagram = @datagram_builder._sc(
|
25
|
-
|
24
|
+
datagram = @datagram_builder._sc(
|
25
|
+
"service",
|
26
|
+
:warning,
|
27
|
+
timestamp: Time.parse("2019-09-30T04:22:12Z"),
|
28
|
+
hostname: "localhost",
|
29
|
+
tags: { foo: "bar|baz" },
|
30
|
+
message: "blah",
|
31
|
+
)
|
26
32
|
assert_equal("_sc|service|1|h:localhost|d:1569817332|#foo:barbaz|m:blah", datagram)
|
27
33
|
|
28
34
|
parsed_datagram = StatsD::Instrument::DogStatsDDatagramBuilder.datagram_class.new(datagram)
|
@@ -46,11 +52,22 @@ class DogStatsDDatagramBuilderTest < Minitest::Test
|
|
46
52
|
end
|
47
53
|
|
48
54
|
def test_complex_event
|
49
|
-
datagram = @datagram_builder._e(
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
55
|
+
datagram = @datagram_builder._e(
|
56
|
+
"testing",
|
57
|
+
"with\nnewline",
|
58
|
+
timestamp: Time.parse("2019-09-30T04:22:12Z"),
|
59
|
+
hostname: "localhost",
|
60
|
+
aggregation_key: "my-key",
|
61
|
+
priority: "low",
|
62
|
+
source_type_name: "source",
|
63
|
+
alert_type: "success",
|
64
|
+
tags: { foo: "bar|baz" },
|
65
|
+
)
|
66
|
+
assert_equal(
|
67
|
+
'_e{7,13}:testing|with\\nnewline|h:localhost|d:1569817332|k:my-key|' \
|
68
|
+
"p:low|s:source|t:success|#foo:barbaz",
|
69
|
+
datagram,
|
70
|
+
)
|
54
71
|
|
55
72
|
parsed_datagram = StatsD::Instrument::DogStatsDDatagramBuilder.datagram_class.new(datagram)
|
56
73
|
assert_equal(:_e, parsed_datagram.type)
|
@@ -12,13 +12,13 @@ module RubocopHelper
|
|
12
12
|
private_constant :RUBY_VERSION
|
13
13
|
|
14
14
|
def assert_no_offenses(source)
|
15
|
-
investigate(RuboCop::ProcessedSource.new(source, RUBY_VERSION, nil))
|
16
|
-
assert_predicate(
|
15
|
+
report = investigate(RuboCop::ProcessedSource.new(source, RUBY_VERSION, nil))
|
16
|
+
assert_predicate(report.offenses, :empty?, "Did not expect Rubocop to find offenses")
|
17
17
|
end
|
18
18
|
|
19
19
|
def assert_offense(source)
|
20
|
-
investigate(RuboCop::ProcessedSource.new(source, RUBY_VERSION, nil))
|
21
|
-
refute_predicate(
|
20
|
+
report = investigate(RuboCop::ProcessedSource.new(source, RUBY_VERSION, nil))
|
21
|
+
refute_predicate(report.offenses, :empty?, "Expected Rubocop to find offenses")
|
22
22
|
end
|
23
23
|
|
24
24
|
def assert_no_autocorrect(source)
|
@@ -29,13 +29,27 @@ module RubocopHelper
|
|
29
29
|
def autocorrect_source(source)
|
30
30
|
RuboCop::Formatter::DisabledConfigFormatter.config_to_allow_offenses = {}
|
31
31
|
RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {}
|
32
|
-
cop.instance_variable_get(:@options)[:
|
32
|
+
cop.instance_variable_get(:@options)[:autocorrect] = true
|
33
|
+
cop.instance_variable_get(:@options)[:raise_error] = true
|
33
34
|
|
34
35
|
processed_source = RuboCop::ProcessedSource.new(source, RUBY_VERSION, nil)
|
35
|
-
investigate(processed_source)
|
36
|
+
report = investigate(processed_source)
|
37
|
+
corrector = RuboCop::Cop::Legacy::Corrector.new(
|
38
|
+
processed_source.buffer,
|
39
|
+
correctors(report),
|
40
|
+
)
|
41
|
+
corrector.process
|
42
|
+
end
|
43
|
+
|
44
|
+
def correctors(report)
|
45
|
+
correctors = report.correctors.reject(&:nil?)
|
46
|
+
if correctors.empty?
|
47
|
+
return []
|
48
|
+
end
|
36
49
|
|
37
|
-
|
38
|
-
|
50
|
+
corrections_proxy = RuboCop::Cop::Legacy::CorrectionsProxy.new(correctors.first)
|
51
|
+
correctors.drop(1).each { |c| corrections_proxy.concat(c) }
|
52
|
+
corrections_proxy
|
39
53
|
end
|
40
54
|
|
41
55
|
def investigate(processed_source)
|
@@ -43,8 +57,7 @@ module RubocopHelper
|
|
43
57
|
instances << klass.new([cop])
|
44
58
|
end
|
45
59
|
|
46
|
-
commissioner = RuboCop::Cop::Commissioner.new([cop], forces
|
60
|
+
commissioner = RuboCop::Cop::Commissioner.new([cop], forces)
|
47
61
|
commissioner.investigate(processed_source)
|
48
|
-
commissioner
|
49
62
|
end
|
50
63
|
end
|
@@ -28,8 +28,10 @@ class StatsDInstrumentationTest < Minitest::Test
|
|
28
28
|
false
|
29
29
|
end
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
class << self
|
32
|
+
def sync
|
33
|
+
true
|
34
|
+
end
|
33
35
|
end
|
34
36
|
end
|
35
37
|
|
@@ -417,8 +419,12 @@ class StatsDInstrumentationTest < Minitest::Test
|
|
417
419
|
def test_statsd_macro_can_disable_prefix
|
418
420
|
client = StatsD::Instrument::Client.new(prefix: "foo")
|
419
421
|
ActiveMerchant::Gateway.singleton_class.extend(StatsD::Instrument)
|
420
|
-
ActiveMerchant::Gateway.singleton_class.statsd_count_success(
|
421
|
-
|
422
|
+
ActiveMerchant::Gateway.singleton_class.statsd_count_success(
|
423
|
+
:sync,
|
424
|
+
"ActiveMerchant.Gateway.sync",
|
425
|
+
no_prefix: true,
|
426
|
+
client: client,
|
427
|
+
)
|
422
428
|
|
423
429
|
datagrams = client.capture { ActiveMerchant::Gateway.sync }
|
424
430
|
assert_equal(1, datagrams.length)
|
data/test/test_helper.rb
CHANGED
@@ -15,9 +15,11 @@ require_relative "helpers/rubocop_helper"
|
|
15
15
|
|
16
16
|
module StatsD
|
17
17
|
module Instrument
|
18
|
-
|
19
|
-
|
20
|
-
StatsD.
|
18
|
+
class << self
|
19
|
+
def strict_mode_enabled?
|
20
|
+
StatsD::Instrument.const_defined?(:Strict) &&
|
21
|
+
StatsD.singleton_class.ancestors.include?(StatsD::Instrument::Strict)
|
22
|
+
end
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
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: 3.5.
|
4
|
+
version: 3.5.11
|
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: 2023-
|
13
|
+
date: 2023-08-02 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: A StatsD client for Ruby apps. Provides metaprogramming methods to inject
|
16
16
|
StatsD instrumentation into your code.
|
@@ -122,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
122
|
- !ruby/object:Gem::Version
|
123
123
|
version: '0'
|
124
124
|
requirements: []
|
125
|
-
rubygems_version: 3.4.
|
125
|
+
rubygems_version: 3.4.17
|
126
126
|
signing_key:
|
127
127
|
specification_version: 4
|
128
128
|
summary: A StatsD client for Ruby apps
|