statsd-instrument 3.5.8 → 3.5.10
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.
- 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 +26 -8
- 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 +17 -4
- data/lib/statsd/instrument/udp_sink.rb +5 -3
- data/lib/statsd/instrument/version.rb +1 -1
- data/lib/statsd/instrument.rb +62 -48
- data/test/assertions_test.rb +1 -1
- data/test/client_test.rb +6 -2
- data/test/dogstatsd_datagram_builder_test.rb +24 -7
- data/test/helpers/rubocop_helper.rb +23 -10
- data/test/statsd_instrumentation_test.rb +16 -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: 58bc5f73b44ea7c3ac8268feaeb9defc2da36b9a7a5565cb11d34324f84f5381
|
|
4
|
+
data.tar.gz: 0d781d4945f02d7e1eb1bc89e68d647bac0b7062f7d26371b8aef95821080e06
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 901993924629290a116505b73eea09c84dd422fb1fd96a274733e9b26223b73ec3087599b419e325c1e4728fd45f964bb2a800d881ae207fb90e84c4950e8e02
|
|
7
|
+
data.tar.gz: cdd79db9829b2317795330fba20238a122a04cfa15b65b53d2b910a50bb315d961bbcf1714a479c61adbf4a4a378272e71dd9132afe9607eaa96611b20ce332a
|
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.10
|
|
10
|
+
|
|
11
|
+
- Fix rubocop 1.30 compatibilitty
|
|
12
|
+
|
|
13
|
+
## Version 3.5.9
|
|
14
|
+
|
|
15
|
+
- Fix dynamic tags being evaluated only once.
|
|
16
|
+
|
|
9
17
|
## Version 3.5.8
|
|
10
18
|
|
|
11
19
|
- Allow the `tag_error_class` option for `statsd_count_success` in strict mode.
|
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,9 +365,17 @@ 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
|
|
|
367
381
|
# Instantiates a new StatsD client that uses the settings of the current client,
|
|
@@ -378,9 +392,13 @@ module StatsD
|
|
|
378
392
|
default_tags: nil,
|
|
379
393
|
datagram_builder_class: nil
|
|
380
394
|
)
|
|
381
|
-
client = clone_with_options(
|
|
382
|
-
|
|
383
|
-
|
|
395
|
+
client = clone_with_options(
|
|
396
|
+
sink: sink,
|
|
397
|
+
prefix: prefix,
|
|
398
|
+
default_sample_rate: default_sample_rate,
|
|
399
|
+
default_tags: default_tags,
|
|
400
|
+
datagram_builder_class: datagram_builder_class,
|
|
401
|
+
)
|
|
384
402
|
|
|
385
403
|
yield(client)
|
|
386
404
|
end
|
|
@@ -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
|
|
|
@@ -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.
|
|
@@ -79,8 +81,8 @@ module StatsD
|
|
|
79
81
|
define_method(method) do |*args, &block|
|
|
80
82
|
client ||= StatsD.singleton_client
|
|
81
83
|
key = StatsD::Instrument.generate_metric_name(name, self, *args)
|
|
82
|
-
|
|
83
|
-
client.measure(key, sample_rate: sample_rate, tags:
|
|
84
|
+
generated_tags = StatsD::Instrument.generate_tags(tags, self, *args)
|
|
85
|
+
client.measure(key, sample_rate: sample_rate, tags: generated_tags, no_prefix: no_prefix) do
|
|
84
86
|
super(*args, &block)
|
|
85
87
|
end
|
|
86
88
|
end
|
|
@@ -100,8 +102,8 @@ module StatsD
|
|
|
100
102
|
define_method(method) do |*args, &block|
|
|
101
103
|
client ||= StatsD.singleton_client
|
|
102
104
|
key = StatsD::Instrument.generate_metric_name(name, self, *args)
|
|
103
|
-
|
|
104
|
-
client.distribution(key, sample_rate: sample_rate, tags:
|
|
105
|
+
generated_tags = StatsD::Instrument.generate_tags(tags, self, *args)
|
|
106
|
+
client.distribution(key, sample_rate: sample_rate, tags: generated_tags, no_prefix: no_prefix) do
|
|
105
107
|
super(*args, &block)
|
|
106
108
|
end
|
|
107
109
|
end
|
|
@@ -145,10 +147,10 @@ module StatsD
|
|
|
145
147
|
client ||= StatsD.singleton_client
|
|
146
148
|
suffix = truthiness == false ? "failure" : "success"
|
|
147
149
|
key = StatsD::Instrument.generate_metric_name(name, self, *args)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
+
generated_tags = StatsD::Instrument.generate_tags(tags, self, *args)
|
|
151
|
+
generated_tags = Helpers.add_tag(generated_tags, :error_class, error.class.name) if tag_error_class && error
|
|
150
152
|
|
|
151
|
-
client.increment("#{key}.#{suffix}", sample_rate: sample_rate, tags:
|
|
153
|
+
client.increment("#{key}.#{suffix}", sample_rate: sample_rate, tags: generated_tags, no_prefix: no_prefix)
|
|
152
154
|
end
|
|
153
155
|
end
|
|
154
156
|
end
|
|
@@ -185,8 +187,8 @@ module StatsD
|
|
|
185
187
|
if truthiness
|
|
186
188
|
client ||= StatsD.singleton_client
|
|
187
189
|
key = StatsD::Instrument.generate_metric_name(name, self, *args)
|
|
188
|
-
|
|
189
|
-
client.increment(key, sample_rate: sample_rate, tags:
|
|
190
|
+
generated_tags = StatsD::Instrument.generate_tags(tags, self, *args)
|
|
191
|
+
client.increment(key, sample_rate: sample_rate, tags: generated_tags, no_prefix: no_prefix)
|
|
190
192
|
end
|
|
191
193
|
end
|
|
192
194
|
end
|
|
@@ -206,8 +208,8 @@ module StatsD
|
|
|
206
208
|
define_method(method) do |*args, &block|
|
|
207
209
|
client ||= StatsD.singleton_client
|
|
208
210
|
key = StatsD::Instrument.generate_metric_name(name, self, *args)
|
|
209
|
-
|
|
210
|
-
client.increment(key, sample_rate: sample_rate, tags:
|
|
211
|
+
generated_tags = StatsD::Instrument.generate_tags(tags, self, *args)
|
|
212
|
+
client.increment(key, sample_rate: sample_rate, tags: generated_tags, no_prefix: no_prefix)
|
|
211
213
|
super(*args, &block)
|
|
212
214
|
end
|
|
213
215
|
end
|
|
@@ -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)
|
|
@@ -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
|
|
|
@@ -231,6 +233,9 @@ class StatsDInstrumentationTest < Minitest::Test
|
|
|
231
233
|
assert_statsd_increment("subgateway.foo", tags: { "key": "foo" }) do
|
|
232
234
|
GatewaySubClass.new.purchase("foo")
|
|
233
235
|
end
|
|
236
|
+
assert_statsd_increment("subgateway.bar", tags: { "key": "bar" }) do
|
|
237
|
+
GatewaySubClass.new.purchase("bar")
|
|
238
|
+
end
|
|
234
239
|
ensure
|
|
235
240
|
ActiveMerchant::Gateway.statsd_remove_count(:ssl_post, metric_namer)
|
|
236
241
|
end
|
|
@@ -243,6 +248,9 @@ class StatsDInstrumentationTest < Minitest::Test
|
|
|
243
248
|
assert_statsd_increment("subgateway.foo", tags: { "key": "foo" }) do
|
|
244
249
|
GatewaySubClass.new.purchase("foo")
|
|
245
250
|
end
|
|
251
|
+
assert_statsd_increment("subgateway.bar", tags: { "key": "bar" }) do
|
|
252
|
+
GatewaySubClass.new.purchase("bar")
|
|
253
|
+
end
|
|
246
254
|
ensure
|
|
247
255
|
ActiveMerchant::Gateway.statsd_remove_count(:ssl_post, metric_namer)
|
|
248
256
|
end
|
|
@@ -411,8 +419,12 @@ class StatsDInstrumentationTest < Minitest::Test
|
|
|
411
419
|
def test_statsd_macro_can_disable_prefix
|
|
412
420
|
client = StatsD::Instrument::Client.new(prefix: "foo")
|
|
413
421
|
ActiveMerchant::Gateway.singleton_class.extend(StatsD::Instrument)
|
|
414
|
-
ActiveMerchant::Gateway.singleton_class.statsd_count_success(
|
|
415
|
-
|
|
422
|
+
ActiveMerchant::Gateway.singleton_class.statsd_count_success(
|
|
423
|
+
:sync,
|
|
424
|
+
"ActiveMerchant.Gateway.sync",
|
|
425
|
+
no_prefix: true,
|
|
426
|
+
client: client,
|
|
427
|
+
)
|
|
416
428
|
|
|
417
429
|
datagrams = client.capture { ActiveMerchant::Gateway.sync }
|
|
418
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.10
|
|
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-06-05 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.13
|
|
126
126
|
signing_key:
|
|
127
127
|
specification_version: 4
|
|
128
128
|
summary: A StatsD client for Ruby apps
|