statsd-instrument 3.0.0.pre2 → 3.1.1

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint.yml +22 -0
  3. data/.github/workflows/tests.yml +31 -0
  4. data/.rubocop.yml +3 -13
  5. data/CHANGELOG.md +43 -0
  6. data/Gemfile +8 -2
  7. data/README.md +6 -3
  8. data/Rakefile +7 -7
  9. data/benchmark/send-metrics-to-dev-null-log +12 -11
  10. data/benchmark/send-metrics-to-local-udp-receiver +16 -15
  11. data/bin/rake +29 -0
  12. data/bin/rubocop +29 -0
  13. data/lib/statsd-instrument.rb +1 -1
  14. data/lib/statsd/instrument.rb +112 -145
  15. data/lib/statsd/instrument/assertions.rb +200 -208
  16. data/lib/statsd/instrument/batched_udp_sink.rb +159 -0
  17. data/lib/statsd/instrument/capture_sink.rb +23 -19
  18. data/lib/statsd/instrument/client.rb +410 -306
  19. data/lib/statsd/instrument/datagram.rb +69 -65
  20. data/lib/statsd/instrument/datagram_builder.rb +81 -77
  21. data/lib/statsd/instrument/dogstatsd_datagram.rb +76 -72
  22. data/lib/statsd/instrument/dogstatsd_datagram_builder.rb +68 -64
  23. data/lib/statsd/instrument/environment.rb +88 -77
  24. data/lib/statsd/instrument/expectation.rb +96 -96
  25. data/lib/statsd/instrument/helpers.rb +11 -7
  26. data/lib/statsd/instrument/log_sink.rb +20 -16
  27. data/lib/statsd/instrument/matchers.rb +93 -74
  28. data/lib/statsd/instrument/null_sink.rb +12 -8
  29. data/lib/statsd/instrument/railtie.rb +11 -7
  30. data/lib/statsd/instrument/rubocop.rb +8 -8
  31. data/lib/statsd/instrument/rubocop/measure_as_dist_argument.rb +1 -1
  32. data/lib/statsd/instrument/rubocop/metaprogramming_positional_arguments.rb +2 -2
  33. data/lib/statsd/instrument/rubocop/metric_prefix_argument.rb +1 -1
  34. data/lib/statsd/instrument/rubocop/metric_return_value.rb +2 -2
  35. data/lib/statsd/instrument/rubocop/metric_value_keyword_argument.rb +1 -1
  36. data/lib/statsd/instrument/rubocop/positional_arguments.rb +4 -4
  37. data/lib/statsd/instrument/rubocop/singleton_configuration.rb +1 -1
  38. data/lib/statsd/instrument/rubocop/splat_arguments.rb +2 -2
  39. data/lib/statsd/instrument/statsd_datagram_builder.rb +12 -8
  40. data/lib/statsd/instrument/strict.rb +1 -6
  41. data/lib/statsd/instrument/udp_sink.rb +49 -47
  42. data/lib/statsd/instrument/version.rb +1 -1
  43. data/statsd-instrument.gemspec +4 -8
  44. data/test/assertions_test.rb +199 -167
  45. data/test/benchmark/clock_gettime.rb +1 -1
  46. data/test/benchmark/default_tags.rb +9 -9
  47. data/test/benchmark/metrics.rb +8 -8
  48. data/test/benchmark/tags.rb +4 -4
  49. data/test/capture_sink_test.rb +14 -14
  50. data/test/client_test.rb +96 -96
  51. data/test/datagram_builder_test.rb +55 -55
  52. data/test/datagram_test.rb +5 -5
  53. data/test/dogstatsd_datagram_builder_test.rb +37 -37
  54. data/test/environment_test.rb +30 -21
  55. data/test/helpers/rubocop_helper.rb +12 -9
  56. data/test/helpers_test.rb +15 -15
  57. data/test/integration_test.rb +7 -7
  58. data/test/log_sink_test.rb +4 -4
  59. data/test/matchers_test.rb +54 -54
  60. data/test/null_sink_test.rb +4 -4
  61. data/test/rubocop/measure_as_dist_argument_test.rb +2 -2
  62. data/test/rubocop/metaprogramming_positional_arguments_test.rb +2 -2
  63. data/test/rubocop/metric_prefix_argument_test.rb +2 -2
  64. data/test/rubocop/metric_return_value_test.rb +6 -6
  65. data/test/rubocop/metric_value_keyword_argument_test.rb +3 -3
  66. data/test/rubocop/positional_arguments_test.rb +12 -12
  67. data/test/rubocop/singleton_configuration_test.rb +8 -8
  68. data/test/rubocop/splat_arguments_test.rb +2 -2
  69. data/test/statsd_datagram_builder_test.rb +6 -6
  70. data/test/statsd_instrumentation_test.rb +122 -122
  71. data/test/statsd_test.rb +69 -67
  72. data/test/test_helper.rb +19 -10
  73. data/test/udp_sink_test.rb +147 -49
  74. metadata +12 -92
  75. data/.github/workflows/ci.yml +0 -49
  76. data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +0 -1027
@@ -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,94 +1,105 @@
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
- # Sets default values for sample rate and logger.
23
- #
24
- # - Default sample rate is set to the value in the STATSD_SAMPLE_RATE environment variable,
25
- # or 1.0 otherwise. See {StatsD#default_sample_rate}
26
- # - {StatsD#logger} is set to a logger that send output to stderr.
27
- #
28
- # If you are including this library inside a Rails environment, additional initialization will
29
- # be done as part of the {StatsD::Instrument::Railtie}.
30
- #
31
- # @return [void]
32
- def setup
33
- StatsD.logger = Logger.new($stderr)
34
- end
35
- end
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
32
+ end
36
33
 
37
- attr_reader :env
34
+ attr_reader :env
38
35
 
39
- def initialize(env)
40
- @env = env
41
- end
36
+ def initialize(env)
37
+ @env = env
38
+ end
42
39
 
43
- # Detects the current environment, either by asking Rails, or by inspecting environment variables.
44
- #
45
- # - Within a Rails application, <tt>Rails.env</tt> is used.
46
- # - It will check the following environment variables in order: <tt>RAILS_ENV</tt>, <tt>RACK_ENV</tt>, <tt>ENV</tt>.
47
- # - If none of these are set, it will return <tt>development</tt>
48
- #
49
- # @return [String] The detected environment.
50
- def environment
51
- if env['STATSD_ENV']
52
- env['STATSD_ENV']
53
- elsif defined?(Rails) && Rails.respond_to?(:env)
54
- Rails.env.to_s
55
- else
56
- env['RAILS_ENV'] || env['RACK_ENV'] || env['ENV'] || 'development'
57
- end
58
- 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
59
60
 
60
- def statsd_implementation
61
- env.fetch('STATSD_IMPLEMENTATION', 'datadog')
62
- end
61
+ def statsd_implementation
62
+ env.fetch("STATSD_IMPLEMENTATION", "datadog")
63
+ end
63
64
 
64
- def statsd_sample_rate
65
- env.fetch('STATSD_SAMPLE_RATE', 1.0).to_f
66
- end
65
+ def statsd_sample_rate
66
+ env.fetch("STATSD_SAMPLE_RATE", 1.0).to_f
67
+ end
67
68
 
68
- def statsd_prefix
69
- env.fetch('STATSD_PREFIX', nil)
70
- end
69
+ def statsd_prefix
70
+ env.fetch("STATSD_PREFIX", nil)
71
+ end
71
72
 
72
- def statsd_addr
73
- env.fetch('STATSD_ADDR', 'localhost:8125')
74
- end
73
+ def statsd_addr
74
+ env.fetch("STATSD_ADDR", "localhost:8125")
75
+ end
75
76
 
76
- def statsd_default_tags
77
- env.key?('STATSD_DEFAULT_TAGS') ? env.fetch('STATSD_DEFAULT_TAGS').split(',') : nil
78
- end
77
+ def statsd_default_tags
78
+ env.key?("STATSD_DEFAULT_TAGS") ? env.fetch("STATSD_DEFAULT_TAGS").split(",") : nil
79
+ end
79
80
 
80
- def client
81
- StatsD::Instrument::Client.from_env(self)
82
- end
81
+ def statsd_flush_interval
82
+ Float(env.fetch("STATSD_FLUSH_INTERVAL", 1.0))
83
+ end
84
+
85
+ def client
86
+ StatsD::Instrument::Client.from_env(self)
87
+ end
83
88
 
84
- def default_sink_for_environment
85
- case environment
86
- when 'production', 'staging'
87
- StatsD::Instrument::UDPSink.for_addr(statsd_addr)
88
- when 'test'
89
- StatsD::Instrument::NullSink.new
90
- else
91
- StatsD::Instrument::LogSink.new(StatsD.logger)
89
+ def default_sink_for_environment
90
+ case environment
91
+ when "production", "staging"
92
+ if statsd_flush_interval > 0.0
93
+ StatsD::Instrument::BatchedUDPSink.for_addr(statsd_addr, flush_interval: statsd_flush_interval)
94
+ else
95
+ StatsD::Instrument::UDPSink.for_addr(statsd_addr)
96
+ end
97
+ when "test"
98
+ StatsD::Instrument::NullSink.new
99
+ else
100
+ StatsD::Instrument::LogSink.new(StatsD.logger)
101
+ end
102
+ end
92
103
  end
93
104
  end
94
105
  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