statsd-instrument 2.9.2 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +16 -23
  3. data/.rubocop.yml +3 -13
  4. data/CHANGELOG.md +33 -0
  5. data/Gemfile +8 -0
  6. data/README.md +3 -3
  7. data/Rakefile +1 -1
  8. data/benchmark/send-metrics-to-dev-null-log +5 -2
  9. data/benchmark/send-metrics-to-local-udp-receiver +8 -6
  10. data/bin/rake +29 -0
  11. data/bin/rubocop +29 -0
  12. data/lib/statsd/instrument.rb +80 -144
  13. data/lib/statsd/instrument/assertions.rb +200 -208
  14. data/lib/statsd/instrument/capture_sink.rb +23 -19
  15. data/lib/statsd/instrument/client.rb +414 -320
  16. data/lib/statsd/instrument/datagram.rb +69 -65
  17. data/lib/statsd/instrument/datagram_builder.rb +81 -77
  18. data/lib/statsd/instrument/dogstatsd_datagram.rb +76 -72
  19. data/lib/statsd/instrument/dogstatsd_datagram_builder.rb +68 -64
  20. data/lib/statsd/instrument/environment.rb +79 -98
  21. data/lib/statsd/instrument/expectation.rb +96 -96
  22. data/lib/statsd/instrument/helpers.rb +10 -35
  23. data/lib/statsd/instrument/log_sink.rb +20 -16
  24. data/lib/statsd/instrument/matchers.rb +86 -71
  25. data/lib/statsd/instrument/null_sink.rb +12 -8
  26. data/lib/statsd/instrument/railtie.rb +11 -11
  27. data/lib/statsd/instrument/statsd_datagram_builder.rb +12 -8
  28. data/lib/statsd/instrument/strict.rb +12 -123
  29. data/lib/statsd/instrument/udp_sink.rb +50 -46
  30. data/lib/statsd/instrument/version.rb +1 -1
  31. data/statsd-instrument.gemspec +2 -8
  32. data/test/assertions_test.rb +46 -12
  33. data/test/capture_sink_test.rb +8 -8
  34. data/test/client_test.rb +62 -51
  35. data/test/datagram_builder_test.rb +29 -29
  36. data/test/datagram_test.rb +1 -1
  37. data/test/dogstatsd_datagram_builder_test.rb +28 -28
  38. data/test/environment_test.rb +10 -46
  39. data/test/helpers/rubocop_helper.rb +11 -8
  40. data/test/helpers_test.rb +5 -5
  41. data/test/integration_test.rb +10 -25
  42. data/test/log_sink_test.rb +2 -2
  43. data/test/matchers_test.rb +36 -36
  44. data/test/null_sink_test.rb +2 -2
  45. data/test/rubocop/metric_return_value_test.rb +3 -3
  46. data/test/rubocop/metric_value_keyword_argument_test.rb +1 -1
  47. data/test/rubocop/positional_arguments_test.rb +10 -10
  48. data/test/statsd_instrumentation_test.rb +97 -122
  49. data/test/statsd_test.rb +50 -75
  50. data/test/test_helper.rb +7 -5
  51. data/test/udp_sink_test.rb +8 -8
  52. metadata +7 -125
  53. data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +0 -1027
  54. data/benchmark/datagram-client +0 -40
  55. data/lib/statsd/instrument/backend.rb +0 -18
  56. data/lib/statsd/instrument/backends/capture_backend.rb +0 -32
  57. data/lib/statsd/instrument/backends/logger_backend.rb +0 -20
  58. data/lib/statsd/instrument/backends/null_backend.rb +0 -9
  59. data/lib/statsd/instrument/backends/udp_backend.rb +0 -152
  60. data/lib/statsd/instrument/legacy_client.rb +0 -301
  61. data/lib/statsd/instrument/metric.rb +0 -155
  62. data/test/assertions_on_legacy_client_test.rb +0 -344
  63. data/test/capture_backend_test.rb +0 -26
  64. data/test/compatibility/dogstatsd_datagram_compatibility_test.rb +0 -161
  65. data/test/deprecations_test.rb +0 -139
  66. data/test/logger_backend_test.rb +0 -22
  67. data/test/metric_test.rb +0 -47
  68. data/test/udp_backend_test.rb +0 -228
@@ -1,75 +1,79 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # @note This class is part of the new Client implementation that is intended
4
- # to become the new default in the next major release of this library.
5
- class StatsD::Instrument::DogStatsDDatagramBuilder < StatsD::Instrument::DatagramBuilder
6
- unsupported_datagram_types :kv
3
+ module StatsD
4
+ module Instrument
5
+ # @note This class is part of the new Client implementation that is intended
6
+ # to become the new default in the next major release of this library.
7
+ class DogStatsDDatagramBuilder < StatsD::Instrument::DatagramBuilder
8
+ unsupported_datagram_types :kv
7
9
 
8
- def self.datagram_class
9
- StatsD::Instrument::DogStatsDDatagram
10
- end
10
+ def self.datagram_class
11
+ StatsD::Instrument::DogStatsDDatagram
12
+ end
11
13
 
12
- def latency_metric_type
13
- :d
14
- end
14
+ def latency_metric_type
15
+ :d
16
+ end
15
17
 
16
- # Constricts an event datagram.
17
- #
18
- # @param [String] title Event title.
19
- # @param [String] text Event description. Newlines are allowed.
20
- # @param [Time] timestamp The of the event. If not provided,
21
- # Datadog will interpret it as the current timestamp.
22
- # @param [String] hostname A hostname to associate with the event.
23
- # @param [String] aggregation_key An aggregation key to group events with the same key.
24
- # @param [String] priority Priority of the event. Either "normal" (default) or "low".
25
- # @param [String] source_type_name The source type of the event.
26
- # @param [String] alert_type Either "error", "warning", "info" (default) or "success".
27
- # @param [Array, Hash] tags Tags to associate with the event.
28
- # @return [String] The correctly formatted service check datagram
29
- #
30
- # @see https://docs.datadoghq.com/developers/dogstatsd/datagram_shell/#events
31
- def _e(title, text, timestamp: nil, hostname: nil, aggregation_key: nil, priority: nil,
32
- source_type_name: nil, alert_type: nil, tags: nil)
18
+ # Constricts an event datagram.
19
+ #
20
+ # @param [String] title Event title.
21
+ # @param [String] text Event description. Newlines are allowed.
22
+ # @param [Time] timestamp The of the event. If not provided,
23
+ # Datadog will interpret it as the current timestamp.
24
+ # @param [String] hostname A hostname to associate with the event.
25
+ # @param [String] aggregation_key An aggregation key to group events with the same key.
26
+ # @param [String] priority Priority of the event. Either "normal" (default) or "low".
27
+ # @param [String] source_type_name The source type of the event.
28
+ # @param [String] alert_type Either "error", "warning", "info" (default) or "success".
29
+ # @param [Array, Hash] tags Tags to associate with the event.
30
+ # @return [String] The correctly formatted service check datagram
31
+ #
32
+ # @see https://docs.datadoghq.com/developers/dogstatsd/datagram_shell/#events
33
+ def _e(title, text, timestamp: nil, hostname: nil, aggregation_key: nil, priority: nil,
34
+ source_type_name: nil, alert_type: nil, tags: nil)
33
35
 
34
- escaped_title = "#{@prefix}#{title}".gsub("\n", '\n')
35
- escaped_text = text.gsub("\n", '\n')
36
- tags = normalize_tags(tags) + default_tags
36
+ escaped_title = "#{@prefix}#{title}".gsub("\n", '\n')
37
+ escaped_text = text.gsub("\n", '\n')
38
+ tags = normalize_tags(tags) + default_tags
37
39
 
38
- datagram = +"_e{#{escaped_title.length},#{escaped_text.length}}:#{escaped_title}|#{escaped_text}"
39
- datagram << "|h:#{hostname}" if hostname
40
- datagram << "|d:#{timestamp.to_i}" if timestamp
41
- datagram << "|k:#{aggregation_key}" if aggregation_key
42
- datagram << "|p:#{priority}" if priority
43
- datagram << "|s:#{source_type_name}" if source_type_name
44
- datagram << "|t:#{alert_type}" if alert_type
45
- datagram << "|##{tags.join(',')}" unless tags.empty?
46
- datagram
47
- end
40
+ datagram = +"_e{#{escaped_title.length},#{escaped_text.length}}:#{escaped_title}|#{escaped_text}"
41
+ datagram << "|h:#{hostname}" if hostname
42
+ datagram << "|d:#{timestamp.to_i}" if timestamp
43
+ datagram << "|k:#{aggregation_key}" if aggregation_key
44
+ datagram << "|p:#{priority}" if priority
45
+ datagram << "|s:#{source_type_name}" if source_type_name
46
+ datagram << "|t:#{alert_type}" if alert_type
47
+ datagram << "|##{tags.join(',')}" unless tags.empty?
48
+ datagram
49
+ end
48
50
 
49
- # Constricts a service check datagram.
50
- #
51
- # @param [String] name Name of the service
52
- # @param [Symbol] status Either `:ok`, `:warning`, `:critical` or `:unknown`
53
- # @param [Time] timestamp The moment when the service was checked. If not provided,
54
- # Datadog will interpret it as the current timestamp.
55
- # @param [String] hostname A hostname to associate with the check.
56
- # @param [Array, Hash] tags Tags to associate with the check.
57
- # @param [String] message A message describing the current state of the service check.
58
- # @return [String] The correctly formatted service check datagram
59
- #
60
- # @see https://docs.datadoghq.com/developers/dogstatsd/datagram_shell/#service-checks
61
- def _sc(name, status, timestamp: nil, hostname: nil, tags: nil, message: nil)
62
- status_number = status.is_a?(Integer) ? status : SERVICE_CHECK_STATUS_VALUES.fetch(status.to_sym)
63
- tags = normalize_tags(tags) + default_tags
51
+ # Constricts a service check datagram.
52
+ #
53
+ # @param [String] name Name of the service
54
+ # @param [Symbol] status Either `:ok`, `:warning`, `:critical` or `:unknown`
55
+ # @param [Time] timestamp The moment when the service was checked. If not provided,
56
+ # Datadog will interpret it as the current timestamp.
57
+ # @param [String] hostname A hostname to associate with the check.
58
+ # @param [Array, Hash] tags Tags to associate with the check.
59
+ # @param [String] message A message describing the current state of the service check.
60
+ # @return [String] The correctly formatted service check datagram
61
+ #
62
+ # @see https://docs.datadoghq.com/developers/dogstatsd/datagram_shell/#service-checks
63
+ def _sc(name, status, timestamp: nil, hostname: nil, tags: nil, message: nil)
64
+ status_number = status.is_a?(Integer) ? status : SERVICE_CHECK_STATUS_VALUES.fetch(status.to_sym)
65
+ tags = normalize_tags(tags) + default_tags
64
66
 
65
- datagram = +"_sc|#{@prefix}#{normalize_name(name)}|#{status_number}"
66
- datagram << "|h:#{hostname}" if hostname
67
- datagram << "|d:#{timestamp.to_i}" if timestamp
68
- datagram << "|##{tags.join(',')}" unless tags.empty?
69
- datagram << "|m:#{normalize_name(message)}" if message
70
- datagram
71
- end
67
+ datagram = +"_sc|#{@prefix}#{normalize_name(name)}|#{status_number}"
68
+ datagram << "|h:#{hostname}" if hostname
69
+ datagram << "|d:#{timestamp.to_i}" if timestamp
70
+ datagram << "|##{tags.join(',')}" unless tags.empty?
71
+ datagram << "|m:#{normalize_name(message)}" if message
72
+ datagram
73
+ end
72
74
 
73
- SERVICE_CHECK_STATUS_VALUES = { ok: 0, warning: 1, critical: 2, unknown: 3 }.freeze
74
- private_constant :SERVICE_CHECK_STATUS_VALUES
75
+ SERVICE_CHECK_STATUS_VALUES = { ok: 0, warning: 1, critical: 2, unknown: 3 }.freeze
76
+ private_constant :SERVICE_CHECK_STATUS_VALUES
77
+ end
78
+ end
75
79
  end
@@ -1,116 +1,97 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # The environment module is used to detect, and initialize the environment in
4
- # which this library is active. It will use different default values based on the environment.
5
- class StatsD::Instrument::Environment
6
- class << self
7
- def current
8
- @current ||= StatsD::Instrument::Environment.new(ENV)
9
- end
3
+ module StatsD
4
+ module Instrument
5
+ # The environment module is used to detect, and initialize the environment in
6
+ # which this library is active. It will use different default values based on the environment.
7
+ class Environment
8
+ class << self
9
+ def current
10
+ @current ||= StatsD::Instrument::Environment.new(ENV)
11
+ end
10
12
 
11
- # Detects the current environment, either by asking Rails, or by inspecting environment variables.
12
- #
13
- # - Within a Rails application, <tt>Rails.env</tt> is used.
14
- # - It will check the following environment variables in order: <tt>RAILS_ENV</tt>, <tt>RACK_ENV</tt>, <tt>ENV</tt>.
15
- # - If none of these are set, it will return <tt>development</tt>
16
- #
17
- # @return [String] The detected environment.
18
- def environment
19
- current.environment
20
- end
13
+ # @deprecated For backwards compatibility only. Use {StatsD::Instrument::Environment#environment}
14
+ # through {StatsD::Instrument::Environment.current} instead.
15
+ def environment
16
+ current.environment
17
+ end
21
18
 
22
- # Instantiates a default backend for the current environment.
23
- #
24
- # @return [StatsD::Instrument::Backend]
25
- # @see #environment
26
- def default_backend
27
- case environment
28
- when 'production', 'staging'
29
- StatsD::Instrument::Backends::UDPBackend.new(current.statsd_addr, current.statsd_implementation)
30
- when 'test'
31
- StatsD::Instrument::Backends::NullBackend.new
32
- else
33
- StatsD::Instrument::Backends::LoggerBackend.new(StatsD.logger)
19
+ # Sets default values for sample rate and logger.
20
+ #
21
+ # - Default sample rate is set to the value in the STATSD_SAMPLE_RATE environment variable,
22
+ # or 1.0 otherwise. See {StatsD#default_sample_rate}
23
+ # - {StatsD#logger} is set to a logger that send output to stderr.
24
+ #
25
+ # If you are including this library inside a Rails environment, additional initialization will
26
+ # be done as part of the {StatsD::Instrument::Railtie}.
27
+ #
28
+ # @return [void]
29
+ def setup
30
+ StatsD.logger = Logger.new($stderr)
31
+ end
34
32
  end
35
- end
36
33
 
37
- # Sets default values for sample rate and logger.
38
- #
39
- # - Default sample rate is set to the value in the STATSD_SAMPLE_RATE environment variable,
40
- # or 1.0 otherwise. See {StatsD#default_sample_rate}
41
- # - {StatsD#logger} is set to a logger that send output to stderr.
42
- #
43
- # If you are including this library inside a Rails environment, additional initialization will
44
- # be done as part of the {StatsD::Instrument::Railtie}.
45
- #
46
- # @return [void]
47
- def setup
48
- StatsD.prefix = current.statsd_prefix
49
- StatsD.default_tags = current.statsd_default_tags
50
- StatsD.default_sample_rate = current.statsd_sample_rate
51
- StatsD.logger = Logger.new($stderr)
52
- end
53
- end
54
-
55
- attr_reader :env
34
+ attr_reader :env
56
35
 
57
- def initialize(env)
58
- @env = env
59
- end
36
+ def initialize(env)
37
+ @env = env
38
+ end
60
39
 
61
- # Detects the current environment, either by asking Rails, or by inspecting environment variables.
62
- #
63
- # - Within a Rails application, <tt>Rails.env</tt> is used.
64
- # - It will check the following environment variables in order: <tt>RAILS_ENV</tt>, <tt>RACK_ENV</tt>, <tt>ENV</tt>.
65
- # - If none of these are set, it will return <tt>development</tt>
66
- #
67
- # @return [String] The detected environment.
68
- def environment
69
- if env['STATSD_ENV']
70
- env['STATSD_ENV']
71
- elsif defined?(Rails) && Rails.respond_to?(:env)
72
- Rails.env.to_s
73
- else
74
- env['RAILS_ENV'] || env['RACK_ENV'] || env['ENV'] || 'development'
75
- end
76
- end
40
+ # Detects the current environment, either by asking Rails, or by inspecting environment variables.
41
+ #
42
+ # - It will prefer the value set in <tt>ENV['STATSD_ENV']</tt>
43
+ # - Within a Rails application, <tt>Rails.env</tt> is used.
44
+ # - It will check the following environment variables in order:
45
+ # - <tt>RAILS_ENV</tt>,
46
+ # - <tt>RACK_ENV</tt>
47
+ # - <tt>ENV</tt>.
48
+ # - If none of these are set, it will return <tt>development</tt>
49
+ #
50
+ # @return [String] The detected environment.
51
+ def environment
52
+ if env['STATSD_ENV']
53
+ env['STATSD_ENV']
54
+ elsif defined?(Rails) && Rails.respond_to?(:env)
55
+ Rails.env.to_s
56
+ else
57
+ env['RAILS_ENV'] || env['RACK_ENV'] || env['ENV'] || 'development'
58
+ end
59
+ end
77
60
 
78
- def statsd_implementation
79
- env.fetch('STATSD_IMPLEMENTATION', 'datadog')
80
- end
61
+ def statsd_implementation
62
+ env.fetch('STATSD_IMPLEMENTATION', 'datadog')
63
+ end
81
64
 
82
- def statsd_sample_rate
83
- env.fetch('STATSD_SAMPLE_RATE', 1.0).to_f
84
- end
65
+ def statsd_sample_rate
66
+ env.fetch('STATSD_SAMPLE_RATE', 1.0).to_f
67
+ end
85
68
 
86
- def statsd_prefix
87
- env.fetch('STATSD_PREFIX', nil)
88
- end
69
+ def statsd_prefix
70
+ env.fetch('STATSD_PREFIX', nil)
71
+ end
89
72
 
90
- def statsd_addr
91
- env.fetch('STATSD_ADDR', 'localhost:8125')
92
- end
73
+ def statsd_addr
74
+ env.fetch('STATSD_ADDR', 'localhost:8125')
75
+ end
93
76
 
94
- def statsd_default_tags
95
- env.key?('STATSD_DEFAULT_TAGS') ? env.fetch('STATSD_DEFAULT_TAGS').split(',') : nil
96
- end
77
+ def statsd_default_tags
78
+ env.key?('STATSD_DEFAULT_TAGS') ? env.fetch('STATSD_DEFAULT_TAGS').split(',') : nil
79
+ end
97
80
 
98
- def client
99
- if env.key?('STATSD_USE_NEW_CLIENT')
100
- StatsD::Instrument::Client.from_env(self)
101
- else
102
- StatsD::Instrument::LegacyClient.singleton
103
- end
104
- end
81
+ def client
82
+ StatsD::Instrument::Client.from_env(self)
83
+ end
105
84
 
106
- def default_sink_for_environment
107
- case environment
108
- when 'production', 'staging'
109
- StatsD::Instrument::UDPSink.for_addr(statsd_addr)
110
- when 'test'
111
- StatsD::Instrument::NullSink.new
112
- else
113
- StatsD::Instrument::LogSink.new(StatsD.logger)
85
+ def default_sink_for_environment
86
+ case environment
87
+ when 'production', 'staging'
88
+ StatsD::Instrument::UDPSink.for_addr(statsd_addr)
89
+ when 'test'
90
+ StatsD::Instrument::NullSink.new
91
+ else
92
+ StatsD::Instrument::LogSink.new(StatsD.logger)
93
+ end
94
+ end
114
95
  end
115
96
  end
116
97
  end
@@ -1,119 +1,119 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # @private
4
- class StatsD::Instrument::Expectation
5
- class << self
6
- def increment(name, value = nil, **options)
7
- new(type: :c, name: name, value: value, **options)
8
- end
9
-
10
- def measure(name, value = nil, **options)
11
- new(type: :ms, name: name, value: value, **options)
12
- end
3
+ module StatsD
4
+ module Instrument
5
+ # @private
6
+ class Expectation
7
+ class << self
8
+ def increment(name, value = nil, **options)
9
+ new(type: :c, name: name, value: value, **options)
10
+ end
13
11
 
14
- def gauge(name, value = nil, **options)
15
- new(type: :g, name: name, value: value, **options)
16
- end
12
+ def measure(name, value = nil, **options)
13
+ new(type: :ms, name: name, value: value, **options)
14
+ end
17
15
 
18
- def set(name, value = nil, **options)
19
- new(type: :s, name: name, value: value, **options)
20
- end
16
+ def gauge(name, value = nil, **options)
17
+ new(type: :g, name: name, value: value, **options)
18
+ end
21
19
 
22
- def key_value(name, value = nil, **options)
23
- new(type: :kv, name: name, value: value, **options)
24
- end
20
+ def set(name, value = nil, **options)
21
+ new(type: :s, name: name, value: value, **options)
22
+ end
25
23
 
26
- def distribution(name, value = nil, **options)
27
- new(type: :d, name: name, value: value, **options)
28
- end
24
+ def distribution(name, value = nil, **options)
25
+ new(type: :d, name: name, value: value, **options)
26
+ end
29
27
 
30
- def histogram(name, value = nil, **options)
31
- new(type: :h, name: name, value: value, **options)
32
- end
33
- end
28
+ def histogram(name, value = nil, **options)
29
+ new(type: :h, name: name, value: value, **options)
30
+ end
31
+ end
34
32
 
35
- attr_accessor :times, :type, :name, :value, :sample_rate, :tags
33
+ attr_accessor :times, :type, :name, :value, :sample_rate, :tags
36
34
 
37
- def initialize(client: StatsD.singleton_client, type:, name:, value: nil,
38
- sample_rate: nil, tags: nil, no_prefix: false, times: 1)
35
+ def initialize(client: StatsD.singleton_client, type:, name:, value: nil,
36
+ sample_rate: nil, tags: nil, no_prefix: false, times: 1)
39
37
 
40
- @type = type
41
- @name = client.prefix ? "#{client.prefix}.#{name}" : name unless no_prefix
42
- @value = normalized_value_for_type(type, value) if value
43
- @sample_rate = sample_rate
44
- @tags = normalize_tags(tags)
45
- @times = times
46
- end
38
+ @type = type
39
+ @name = no_prefix || !client.prefix ? name : "#{client.prefix}.#{name}"
40
+ @value = normalized_value_for_type(type, value) if value
41
+ @sample_rate = sample_rate
42
+ @tags = normalize_tags(tags)
43
+ @times = times
44
+ end
47
45
 
48
- def normalized_value_for_type(type, value)
49
- case type
50
- when :c then Integer(value)
51
- when :g, :h, :d, :kv, :ms then Float(value)
52
- when :s then String(value)
53
- else value
54
- end
55
- end
46
+ def normalized_value_for_type(type, value)
47
+ case type
48
+ when :c then Integer(value)
49
+ when :g, :h, :d, :kv, :ms then Float(value)
50
+ when :s then String(value)
51
+ else value
52
+ end
53
+ end
56
54
 
57
- def matches(actual_metric)
58
- return false if sample_rate && sample_rate != actual_metric.sample_rate
59
- return false if value && value != normalized_value_for_type(actual_metric.type, actual_metric.value)
55
+ def matches(actual_metric)
56
+ return false if sample_rate && sample_rate != actual_metric.sample_rate
57
+ return false if value && value != normalized_value_for_type(actual_metric.type, actual_metric.value)
60
58
 
61
- if tags
62
- expected_tags = Set.new(tags)
63
- actual_tags = Set.new(actual_metric.tags)
64
- return expected_tags.subset?(actual_tags)
65
- end
66
- true
67
- end
59
+ if tags
60
+ expected_tags = Set.new(tags)
61
+ actual_tags = Set.new(actual_metric.tags)
62
+ return expected_tags.subset?(actual_tags)
63
+ end
64
+ true
65
+ end
68
66
 
69
- def to_s
70
- str = +"#{name}:#{value || '<anything>'}|#{type}"
71
- str << "|@#{sample_rate}" if sample_rate
72
- str << "|#" << tags.join(',') if tags
73
- str << " (expected #{times} times)" if times > 1
74
- str
75
- end
67
+ def to_s
68
+ str = +"#{name}:#{value || '<anything>'}|#{type}"
69
+ str << "|@#{sample_rate}" if sample_rate
70
+ str << "|#" << tags.join(',') if tags
71
+ str << " (expected #{times} times)" if times > 1
72
+ str
73
+ end
76
74
 
77
- def inspect
78
- "#<StatsD::Instrument::Expectation:\"#{self}\">"
79
- end
75
+ def inspect
76
+ "#<StatsD::Instrument::Expectation:\"#{self}\">"
77
+ end
80
78
 
81
- private
79
+ private
82
80
 
83
- # Needed for normalize_tags
84
- unless Regexp.method_defined?(:match?) # for ruby 2.3
85
- module RubyBackports
86
- refine Regexp do
87
- def match?(str)
88
- (self =~ str) != nil
81
+ # Needed for normalize_tags
82
+ unless Regexp.method_defined?(:match?) # for ruby 2.3
83
+ module RubyBackports
84
+ refine Regexp do
85
+ def match?(str)
86
+ (self =~ str) != nil
87
+ end
88
+ end
89
89
  end
90
+
91
+ using(RubyBackports)
90
92
  end
91
- end
92
93
 
93
- using RubyBackports
94
- end
94
+ # @private
95
+ #
96
+ # Utility function to convert tags to the canonical form.
97
+ #
98
+ # - Tags specified as key value pairs will be converted into an array
99
+ # - Tags are normalized to remove unsupported characters
100
+ #
101
+ # @param tags [Array<String>, Hash<String, String>, nil] Tags specified in any form.
102
+ # @return [Array<String>, nil] the list of tags in canonical form.
103
+ #
104
+ # @todo We should delegate this to thje datagram builder of the current client,
105
+ # to ensure that this logic matches the logic of the active datagram builder.
106
+ def normalize_tags(tags)
107
+ return [] unless tags
108
+ tags = tags.map { |k, v| "#{k}:#{v}" } if tags.is_a?(Hash)
109
+
110
+ # Fast path when no string replacement is needed
111
+ return tags unless tags.any? { |tag| /[|,]/.match?(tag) }
112
+ tags.map { |tag| tag.tr('|,', '') }
113
+ end
114
+ end
95
115
 
96
- # @private
97
- #
98
- # Utility function to convert tags to the canonical form.
99
- #
100
- # - Tags specified as key value pairs will be converted into an array
101
- # - Tags are normalized to remove unsupported characters
102
- #
103
- # @param tags [Array<String>, Hash<String, String>, nil] Tags specified in any form.
104
- # @return [Array<String>, nil] the list of tags in canonical form.
105
- #
106
- # @todo We should delegate this to thje datagram builder of the current client,
107
- # to ensure that this logic matches the logic of the active datagram builder.
108
- def normalize_tags(tags)
109
- return [] unless tags
110
- tags = tags.map { |k, v| "#{k}:#{v}" } if tags.is_a?(Hash)
111
-
112
- # Fast path when no string replacement is needed
113
- return tags unless tags.any? { |tag| /[|,]/.match?(tag) }
114
- tags.map { |tag| tag.tr('|,', '') }
116
+ # For backwards compatibility
117
+ MetricExpectation = Expectation
115
118
  end
116
119
  end
117
-
118
- # For backwards compatibility
119
- StatsD::Instrument::MetricExpectation = StatsD::Instrument::Expectation