statsd-instrument 3.0.0.pre2 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
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,27 +1,31 @@
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::CaptureSink
6
- attr_reader :parent, :datagrams, :datagram_class
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 CaptureSink
8
+ attr_reader :parent, :datagrams, :datagram_class
7
9
 
8
- def initialize(parent:, datagram_class: StatsD::Instrument::Datagram)
9
- @parent = parent
10
- @datagram_class = datagram_class
11
- @datagrams = []
12
- end
10
+ def initialize(parent:, datagram_class: StatsD::Instrument::Datagram)
11
+ @parent = parent
12
+ @datagram_class = datagram_class
13
+ @datagrams = []
14
+ end
13
15
 
14
- def sample?(_sample_rate)
15
- true
16
- end
16
+ def sample?(_sample_rate)
17
+ true
18
+ end
17
19
 
18
- def <<(datagram)
19
- @datagrams << datagram_class.new(datagram)
20
- parent << datagram
21
- self
22
- end
20
+ def <<(datagram)
21
+ @datagrams << datagram_class.new(datagram)
22
+ parent << datagram
23
+ self
24
+ end
23
25
 
24
- def clear
25
- @datagrams.clear
26
+ def clear
27
+ @datagrams.clear
28
+ end
29
+ end
26
30
  end
27
31
  end
@@ -1,338 +1,442 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # The Client is the main interface for using StatsD.
4
- #
5
- # @note This new Client implementation is intended to become the new default in the
6
- # next major release of this library. While this class may already be functional,
7
- # we provide no guarantees about the API and the behavior may change.
8
- class StatsD::Instrument::Client
9
- class << self
10
- def from_env(
11
- env = StatsD::Instrument::Environment.current,
12
- prefix: env.statsd_prefix,
13
- default_sample_rate: env.statsd_sample_rate,
14
- default_tags: env.statsd_default_tags,
15
- implementation: env.statsd_implementation,
16
- sink: env.default_sink_for_environment,
17
- datagram_builder_class: datagram_builder_class_for_implementation(implementation)
18
- )
19
- new(
20
- prefix: prefix,
21
- default_sample_rate: default_sample_rate,
22
- default_tags: default_tags,
23
- implementation: implementation,
24
- sink: sink,
25
- datagram_builder_class: datagram_builder_class,
3
+ module StatsD
4
+ module Instrument
5
+ # The Client is the main interface for using StatsD. It defines the metric
6
+ # methods that you would normally call from your application.
7
+ #
8
+ # The client set to {StatsD.singleton_client} will handle all metric calls made
9
+ # against the StatsD singleton, e.g. `StatsD.increment`.
10
+ #
11
+ # We recommend that the configuration of the StatsD setup is provided through
12
+ # environment variables
13
+ #
14
+ # You are encouraged to instantiate multiple clients, and instantiate variants
15
+ # of an existing clients using {#clone_with_options}. We recommend instantiating
16
+ # a separate client for every logical component of your application using
17
+ # `clone_with_options`, and setting a different metric `prefix`.
18
+ #
19
+ # @see StatsD.singleton_client
20
+ # @see #clone_with_options
21
+ class Client
22
+ class << self
23
+ # Instantiates a StatsD::Instrument::Client using configuration values provided in
24
+ # environment variables.
25
+ #
26
+ # @see StatsD::Instrument::Environment
27
+ def from_env(
28
+ env = StatsD::Instrument::Environment.current,
29
+ prefix: env.statsd_prefix,
30
+ default_sample_rate: env.statsd_sample_rate,
31
+ default_tags: env.statsd_default_tags,
32
+ implementation: env.statsd_implementation,
33
+ sink: env.default_sink_for_environment,
34
+ datagram_builder_class: datagram_builder_class_for_implementation(implementation)
35
+ )
36
+ new(
37
+ prefix: prefix,
38
+ default_sample_rate: default_sample_rate,
39
+ default_tags: default_tags,
40
+ implementation: implementation,
41
+ sink: sink,
42
+ datagram_builder_class: datagram_builder_class,
43
+ )
44
+ end
45
+
46
+ # Finds the right DatagramBuilder class for a given implementation.
47
+ # @private
48
+ # @param [Symbol, String] implementation The name of the implementation, e.g.
49
+ # `"statsd"` or `:datadog`.
50
+ # @return [Class] The subclass of {StatsD::Instrument::DatagramBuilder}
51
+ # builder to use to generate UDP datagrams for the given implementation.
52
+ # @raise `NotImplementedError` if the implementation is not recognized or
53
+ # supported.
54
+ def datagram_builder_class_for_implementation(implementation)
55
+ case implementation.to_s
56
+ when "statsd"
57
+ StatsD::Instrument::StatsDDatagramBuilder
58
+ when "datadog", "dogstatsd"
59
+ StatsD::Instrument::DogStatsDDatagramBuilder
60
+ else
61
+ raise NotImplementedError, "Implementation named #{implementation} could not be found"
62
+ end
63
+ end
64
+ end
65
+
66
+ # The class to use to build StatsD datagrams. To build the actual datagrams,
67
+ # the class will be instantiated, potentially multiple times, by the client.
68
+ #
69
+ # @return [Class] A subclass of {StatsD::Instrument::DatagramBuilder}
70
+ # @see .datagram_builder_class_for_implementation
71
+ attr_reader :datagram_builder_class
72
+
73
+ # The sink to send UDP datagrams to.
74
+ #
75
+ # This can be set to any object that responds to the following methods:
76
+ #
77
+ # - `sample?` which should return true if the metric should be sampled, i.e.
78
+ # actually sent to the sink.
79
+ # - `#<<` which takes a UDP datagram as string to emit the datagram. This
80
+ # method will only be called if `sample?` returned `true`.
81
+ #
82
+ # Generally, you should use an instance of one of the following classes that
83
+ # ship with this library:
84
+ #
85
+ # - {StatsD::Instrument::UDPSink} A sink that will actually emit the provided
86
+ # datagrams over UDP.
87
+ # - {StatsD::Instrument::NullSink} A sink that will simply swallow every
88
+ # datagram. This sink is for use when testing your application.
89
+ # - {StatsD::Instrument::LogSink} A sink that log all provided datagrams to
90
+ # a Logger, normally {StatsD.logger}.
91
+ #
92
+ # @return [#sample?, #<<]
93
+ attr_reader :sink
94
+
95
+ # The prefix to prepend to the metric names that are emitted through this
96
+ # client, using a dot (`.`) as namespace separator. E.g. when the prefix is
97
+ # set to `foo`, and you emit a metric named `bar`, the metric name will be
98
+ # `foo.bar`.
99
+ #
100
+ # Generally all the metrics you emit to the same StatsD server will share a
101
+ # single, global namespace. If you are emitting metrics from multiple
102
+ # applications, using a prefix is recommended to prevent metric name
103
+ # collisions.
104
+ #
105
+ # You can also leave this value to be `nil` if you don't want to prefix your
106
+ # metric names.
107
+ #
108
+ # @return [String, nil]
109
+ #
110
+ # @note The `prefix` can be overridden by any metric call by setting the
111
+ # `no_prefix` keyword argument to `true`. We recommend against doing this,
112
+ # but this behavior is retained for backwards compatibility.
113
+ # Rather, when you feel the need to do this, we recommend instantiating
114
+ # a new client without prefix (using {#clone_with_options}), and using it
115
+ # to emit the metric.
116
+ attr_reader :prefix
117
+
118
+ # The tags to apply to all the metrics emitted through this client.
119
+ #
120
+ # The tags can be supplied in normal form: an array of strings. You can also
121
+ # provide a hash, which will be turned into normal form by concatanting the
122
+ # key and the value using a colon. To not use any default tags, set to `nil`.
123
+ # Note that other components of your StatsD metric pipeline may also add tags
124
+ # to metrics. E.g. the DataDog agent may add add tags like `hostname`.
125
+ #
126
+ # We generally recommend to not use default tags, or use them sparingly.
127
+ # Adding tags to every metric easily introduces carninality explosions, which
128
+ # will make metrics less precise due to the lossy nature of aggregation. It
129
+ # also makes your infrastructure more expsnive to run, and the user interface
130
+ # of your metric explorer less responsive.
131
+ #
132
+ # @return [Array<String>, Hash, nil]
133
+ attr_reader :default_tags
134
+
135
+ # The default sample rate to use for metrics that are emitted without a
136
+ # sample rate set. This should be a value between 0 (never emit a metric) and
137
+ # 1.0 (always emit). If it is not set, the default value 1.0 is used.
138
+ #
139
+ # We generally recommend setting sample rates on individual metrics based
140
+ # on their frequency, rather than changing the default sample rate.
141
+ #
142
+ # @return [Float] (default: 1.0) A value between 0.0 and 1.0.
143
+ attr_reader :default_sample_rate
144
+
145
+ # Instantiates a new client.
146
+ # @see .from_env to instantiate a client using environment variables.
147
+ def initialize(
148
+ prefix: nil,
149
+ default_sample_rate: 1.0,
150
+ default_tags: nil,
151
+ implementation: "datadog",
152
+ sink: StatsD::Instrument::NullSink.new,
153
+ datagram_builder_class: self.class.datagram_builder_class_for_implementation(implementation)
26
154
  )
27
- end
155
+ @sink = sink
156
+ @datagram_builder_class = datagram_builder_class
157
+
158
+ @prefix = prefix
159
+ @default_tags = default_tags
160
+ @default_sample_rate = default_sample_rate
28
161
 
29
- # @private
30
- def datagram_builder_class_for_implementation(implementation)
31
- case implementation.to_s
32
- when 'statsd'
33
- StatsD::Instrument::StatsDDatagramBuilder
34
- when 'datadog', 'dogstatsd'
35
- StatsD::Instrument::DogStatsDDatagramBuilder
36
- else
37
- raise NotImplementedError, "No implementation for #{statsd_implementation}"
162
+ @datagram_builder = { false => nil, true => nil }
38
163
  end
39
- end
40
- end
41
164
 
42
- attr_reader :sink, :datagram_builder_class, :prefix, :default_tags, :default_sample_rate
165
+ # @!group Metric Methods
43
166
 
44
- def initialize(
45
- prefix: nil,
46
- default_sample_rate: 1.0,
47
- default_tags: nil,
48
- implementation: 'datadog',
49
- sink: StatsD::Instrument::NullSink.new,
50
- datagram_builder_class: self.class.datagram_builder_class_for_implementation(implementation)
51
- )
52
- @sink = sink
53
- @datagram_builder_class = datagram_builder_class
167
+ # Emits a counter metric.
168
+ #
169
+ # You should use a counter metric to count the frequency of something happening. As a
170
+ # result, the value should generally be set to 1 (the default), unless you reporting
171
+ # about a batch of activity. E.g. `increment('messages.processed', messages.size)`
172
+ # For values that are not frequencies, you should use another metric type, e.g.
173
+ # {#histogram} or {#distribution}.
174
+ #
175
+ # @param name [String] The name of the metric.
176
+ #
177
+ # - We recommend using `snake_case.metric_names` as naming scheme.
178
+ # - A `.` should be used for namespacing, e.g. `foo.bar.baz`
179
+ # - A metric name should not include the following characters: `|`, `@`, and `:`.
180
+ # The library will convert these characters to `_`.
181
+ #
182
+ # @param value [Integer] (default: 1) The value to increment the counter by.
183
+ #
184
+ # You should not compensate for the sample rate using the counter increment. E.g., if
185
+ # your sample rate is set to `0.01`, you should not use 100 as increment to compensate
186
+ # for it. The sample rate is part of the packet that is being sent to the server, and
187
+ # the server should know how to compensate for it.
188
+ #
189
+ # @param [Float] sample_rate (default: `#default_sample_rate`) The rate at which to sample
190
+ # this metric call. This value should be between 0 and 1. This value can be used to reduce
191
+ # the amount of network I/O (and CPU cycles) is being used for very frequent metrics.
192
+ #
193
+ # - A value of `0.1` means that only 1 out of 10 calls will be emitted; the other 9 will
194
+ # be short-circuited.
195
+ # - When set to `1`, every metric will be emitted.
196
+ # - If this parameter is not set, the default sample rate for this client will be used.
197
+ #
198
+ # @param [Hash<Symbol, String>, Array<String>] tags (default: nil)
199
+ # @return [void]
200
+ def increment(name, value = 1, sample_rate: nil, tags: nil, no_prefix: false)
201
+ sample_rate ||= @default_sample_rate
202
+ return StatsD::Instrument::VOID unless sample?(sample_rate)
203
+ emit(datagram_builder(no_prefix: no_prefix).c(name, value, sample_rate, tags))
204
+ end
54
205
 
55
- @prefix = prefix
56
- @default_tags = default_tags
57
- @default_sample_rate = default_sample_rate
206
+ # Emits a timing metric.
207
+ #
208
+ # @param name (see #increment)
209
+ # @param [Numeric] value The duration to record, in milliseconds.
210
+ # @param sample_rate (see #increment)
211
+ # @param tags (see #increment)
212
+ # @return [void]
213
+ def measure(name, value = nil, sample_rate: nil, tags: nil, no_prefix: false, &block)
214
+ if block_given?
215
+ return latency(name, sample_rate: sample_rate, tags: tags, metric_type: :ms, no_prefix: no_prefix, &block)
216
+ end
58
217
 
59
- @datagram_builder = { false => nil, true => nil }
60
- end
218
+ sample_rate ||= @default_sample_rate
219
+ return StatsD::Instrument::VOID unless sample?(sample_rate)
220
+ emit(datagram_builder(no_prefix: no_prefix).ms(name, value, sample_rate, tags))
221
+ end
61
222
 
62
- # @!group Metric Methods
63
-
64
- # Emits a counter metric.
65
- #
66
- # You should use a counter metric to count the frequency of something happening. As a
67
- # result, the value should generally be set to 1 (the default), unless you reporting
68
- # about a batch of activity. E.g. `increment('messages.processed', messages.size)`
69
- # For values that are not frequencies, you should use another metric type, e.g.
70
- # {#histogram} or {#distribution}.
71
- #
72
- # @param name [String] The name of the metric.
73
- #
74
- # - We recommend using `snake_case.metric_names` as naming scheme.
75
- # - A `.` should be used for namespacing, e.g. `foo.bar.baz`
76
- # - A metric name should not include the following characters: `|`, `@`, and `:`.
77
- # The library will convert these characters to `_`.
78
- #
79
- # @param value [Integer] (default: 1) The value to increment the counter by.
80
- #
81
- # You should not compensate for the sample rate using the counter increment. E.g., if
82
- # your sample rate is set to `0.01`, you should not use 100 as increment to compensate
83
- # for it. The sample rate is part of the packet that is being sent to the server, and
84
- # the server should know how to compensate for it.
85
- #
86
- # @param [Float] sample_rate (default: `#default_sample_rate`) The rate at which to sample
87
- # this metric call. This value should be between 0 and 1. This value can be used to reduce
88
- # the amount of network I/O (and CPU cycles) is being used for very frequent metrics.
89
- #
90
- # - A value of `0.1` means that only 1 out of 10 calls will be emitted; the other 9 will
91
- # be short-circuited.
92
- # - When set to `1`, every metric will be emitted.
93
- # - If this parameter is not set, the default sample rate for this client will be used.
94
- #
95
- # @param [Hash<Symbol, String>, Array<String>] tags (default: nil)
96
- # @return [void]
97
- def increment(name, value = 1, sample_rate: nil, tags: nil, no_prefix: false)
98
- sample_rate ||= @default_sample_rate
99
- return StatsD::Instrument::VOID unless sample?(sample_rate)
100
- emit(datagram_builder(no_prefix: no_prefix).c(name, value, sample_rate, tags))
101
- end
223
+ # Emits a gauge metric.
224
+ #
225
+ # You should use a gauge if you are reporting the current value of
226
+ # something that can only have one value at the time. E.g., the
227
+ # speed of your car. A newly reported value will replace the previously
228
+ # reported value.
229
+ #
230
+ #
231
+ # @param name (see #increment)
232
+ # @param [Numeric] value The gauged value.
233
+ # @param sample_rate (see #increment)
234
+ # @param tags (see #increment)
235
+ # @return [void]
236
+ def gauge(name, value, sample_rate: nil, tags: nil, no_prefix: false)
237
+ sample_rate ||= @default_sample_rate
238
+ return StatsD::Instrument::VOID unless sample?(sample_rate)
239
+ emit(datagram_builder(no_prefix: no_prefix).g(name, value, sample_rate, tags))
240
+ end
102
241
 
103
- # Emits a timing metric.
104
- #
105
- # @param name (see #increment)
106
- # @param [Numeric] value The duration to record, in milliseconds.
107
- # @param sample_rate (see #increment)
108
- # @param tags (see #increment)
109
- # @return [void]
110
- def measure(name, value = nil, sample_rate: nil, tags: nil, no_prefix: false, &block)
111
- if block_given?
112
- return latency(name, sample_rate: sample_rate, tags: tags, metric_type: :ms, no_prefix: no_prefix, &block)
113
- end
242
+ # Emits a set metric, which counts distinct values.
243
+ #
244
+ # @param name (see #increment)
245
+ # @param [Numeric, String] value The value to count for distinct occurrences.
246
+ # @param sample_rate (see #increment)
247
+ # @param tags (see #increment)
248
+ # @return [void]
249
+ def set(name, value, sample_rate: nil, tags: nil, no_prefix: false)
250
+ sample_rate ||= @default_sample_rate
251
+ return StatsD::Instrument::VOID unless sample?(sample_rate)
252
+ emit(datagram_builder(no_prefix: no_prefix).s(name, value, sample_rate, tags))
253
+ end
114
254
 
115
- sample_rate ||= @default_sample_rate
116
- return StatsD::Instrument::VOID unless sample?(sample_rate)
117
- emit(datagram_builder(no_prefix: no_prefix).ms(name, value, sample_rate, tags))
118
- end
255
+ # Emits a distribution metric, which builds a histogram of the reported
256
+ # values.
257
+ #
258
+ # @note The distribution metric type is not available on all implementations.
259
+ # A `NotImplementedError` will be raised if you call this method, but
260
+ # the active implementation does not support it.
261
+ #
262
+ # @param name (see #increment)
263
+ # @param [Numeric] value The value to include in the distribution histogram.
264
+ # @param sample_rate (see #increment)
265
+ # @param tags (see #increment)
266
+ # @return [void]
267
+ def distribution(name, value = nil, sample_rate: nil, tags: nil, no_prefix: false, &block)
268
+ if block_given?
269
+ return latency(name, sample_rate: sample_rate, tags: tags, metric_type: :d, no_prefix: no_prefix, &block)
270
+ end
119
271
 
120
- # Emits a gauge metric.
121
- #
122
- # You should use a gauge if you are reporting the current value of
123
- # something that can only have one value at the time. E.g., the
124
- # speed of your car. A newly reported value will replace the previously
125
- # reported value.
126
- #
127
- #
128
- # @param name (see #increment)
129
- # @param [Numeric] value The gauged value.
130
- # @param sample_rate (see #increment)
131
- # @param tags (see #increment)
132
- # @return [void]
133
- def gauge(name, value, sample_rate: nil, tags: nil, no_prefix: false)
134
- sample_rate ||= @default_sample_rate
135
- return StatsD::Instrument::VOID unless sample?(sample_rate)
136
- emit(datagram_builder(no_prefix: no_prefix).g(name, value, sample_rate, tags))
137
- end
272
+ sample_rate ||= @default_sample_rate
273
+ return StatsD::Instrument::VOID unless sample?(sample_rate)
274
+ emit(datagram_builder(no_prefix: no_prefix).d(name, value, sample_rate, tags))
275
+ end
138
276
 
139
- # Emits a set metric, which counts distinct values.
140
- #
141
- # @param name (see #increment)
142
- # @param [Numeric, String] value The value to count for distinct occurrences.
143
- # @param sample_rate (see #increment)
144
- # @param tags (see #increment)
145
- # @return [void]
146
- def set(name, value, sample_rate: nil, tags: nil, no_prefix: false)
147
- sample_rate ||= @default_sample_rate
148
- return StatsD::Instrument::VOID unless sample?(sample_rate)
149
- emit(datagram_builder(no_prefix: no_prefix).s(name, value, sample_rate, tags))
150
- end
277
+ # Emits a histogram metric, which builds a histogram of the reported values.
278
+ #
279
+ # @note The histogram metric type is not available on all implementations.
280
+ # A `NotImplementedError` will be raised if you call this method, but
281
+ # the active implementation does not support it.
282
+ #
283
+ # @param name (see #increment)
284
+ # @param [Numeric] value The value to include in the histogram.
285
+ # @param sample_rate (see #increment)
286
+ # @param tags (see #increment)
287
+ # @return [void]
288
+ def histogram(name, value, sample_rate: nil, tags: nil, no_prefix: false)
289
+ sample_rate ||= @default_sample_rate
290
+ return StatsD::Instrument::VOID unless sample?(sample_rate)
291
+ emit(datagram_builder(no_prefix: no_prefix).h(name, value, sample_rate, tags))
292
+ end
151
293
 
152
- # Emits a distribution metric, which builds a histogram of the reported
153
- # values.
154
- #
155
- # @note The distribution metric type is not available on all implementations.
156
- # A `NotImplementedError` will be raised if you call this method, but
157
- # the active implementation does not support it.
158
- #
159
- # @param name (see #increment)
160
- # @param [Numeric] value The value to include in the distribution histogram.
161
- # @param sample_rate (see #increment)
162
- # @param tags (see #increment)
163
- # @return [void]
164
- def distribution(name, value = nil, sample_rate: nil, tags: nil, no_prefix: false, &block)
165
- if block_given?
166
- return latency(name, sample_rate: sample_rate, tags: tags, metric_type: :d, no_prefix: no_prefix, &block)
167
- end
294
+ # @!endgroup
168
295
 
169
- sample_rate ||= @default_sample_rate
170
- return StatsD::Instrument::VOID unless sample?(sample_rate)
171
- emit(datagram_builder(no_prefix: no_prefix).d(name, value, sample_rate, tags))
172
- end
296
+ # Measures the latency of the given block in milliseconds, and emits it as a metric.
297
+ #
298
+ # @param name (see #increment)
299
+ # @param sample_rate (see #increment)
300
+ # @param tags (see #increment)
301
+ # @param [Symbol] metric_type The metric type to use. If not specified, we will
302
+ # use the preferred metric type of the implementation. The default is `:ms`.
303
+ # Generally, you should not have to set this.
304
+ # @yield The latency (execution time) of the block
305
+ # @return The return value of the provided block will be passed through.
306
+ def latency(name, sample_rate: nil, tags: nil, metric_type: nil, no_prefix: false)
307
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
308
+ begin
309
+ yield
310
+ ensure
311
+ stop = Process.clock_gettime(Process::CLOCK_MONOTONIC)
173
312
 
174
- # Emits a histogram metric, which builds a histogram of the reported values.
175
- #
176
- # @note The histogram metric type is not available on all implementations.
177
- # A `NotImplementedError` will be raised if you call this method, but
178
- # the active implementation does not support it.
179
- #
180
- # @param name (see #increment)
181
- # @param [Numeric] value The value to include in the histogram.
182
- # @param sample_rate (see #increment)
183
- # @param tags (see #increment)
184
- # @return [void]
185
- def histogram(name, value, sample_rate: nil, tags: nil, no_prefix: false)
186
- sample_rate ||= @default_sample_rate
187
- return StatsD::Instrument::VOID unless sample?(sample_rate)
188
- emit(datagram_builder(no_prefix: no_prefix).h(name, value, sample_rate, tags))
189
- end
313
+ sample_rate ||= @default_sample_rate
314
+ if sample?(sample_rate)
315
+ metric_type ||= datagram_builder(no_prefix: no_prefix).latency_metric_type
316
+ latency_in_ms = 1000.0 * (stop - start)
317
+ emit(datagram_builder(no_prefix: no_prefix).send(metric_type, name, latency_in_ms, sample_rate, tags))
318
+ end
319
+ end
320
+ end
190
321
 
191
- # @!endgroup
192
-
193
- # Measures the latency of the given block in milliseconds, and emits it as a metric.
194
- #
195
- # @param name (see #increment)
196
- # @param sample_rate (see #increment)
197
- # @param tags (see #increment)
198
- # @param [Symbol] metric_type The metric type to use. If not specified, we will
199
- # use the preferred metric type of the implementation. The default is `:ms`.
200
- # Generally, you should not have to set this.
201
- # @yield The latency (execution time) of the block
202
- # @return The return value of the provided block will be passed through.
203
- def latency(name, sample_rate: nil, tags: nil, metric_type: nil, no_prefix: false)
204
- start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
205
- begin
206
- yield
207
- ensure
208
- stop = Process.clock_gettime(Process::CLOCK_MONOTONIC)
209
-
210
- sample_rate ||= @default_sample_rate
211
- if sample?(sample_rate)
212
- metric_type ||= datagram_builder(no_prefix: no_prefix).latency_metric_type
213
- latency_in_ms = 1000.0 * (stop - start)
214
- emit(datagram_builder(no_prefix: no_prefix).send(metric_type, name, latency_in_ms, sample_rate, tags))
322
+ # Emits a service check. Services Checks allow you to characterize the status
323
+ # of a service in order to monitor it within Datadog.
324
+ #
325
+ # @param name (see StatsD::Instrument::DogStatsDDatagramBuilder#_sc)
326
+ # @param status (see StatsD::Instrument::DogStatsDDatagramBuilder#_sc)
327
+ # @param timestamp (see StatsD::Instrument::DogStatsDDatagramBuilder#_sc)
328
+ # @param hostname (see StatsD::Instrument::DogStatsDDatagramBuilder#_sc)
329
+ # @param tags (see StatsD::Instrument::DogStatsDDatagramBuilder#_sc)
330
+ # @param message (see StatsD::Instrument::DogStatsDDatagramBuilder#_sc)
331
+ # @return [void]
332
+ #
333
+ # @note Supported by the Datadog implementation only.
334
+ def service_check(name, status, timestamp: nil, hostname: nil, tags: nil, message: nil, no_prefix: false)
335
+ emit(datagram_builder(no_prefix: no_prefix)._sc(name, status,
336
+ timestamp: timestamp, hostname: hostname, tags: tags, message: message))
215
337
  end
216
- end
217
- end
218
338
 
219
- # Emits a service check.
220
- #
221
- # @param [String] title Event title.
222
- # @param [String] text Event description. Newlines are allowed.
223
- # @param [Time] timestamp The of the event. If not provided,
224
- # Datadog will interpret it as the current timestamp.
225
- # @param [String] hostname A hostname to associate with the event.
226
- # @param [String] aggregation_key An aggregation key to group events with the same key.
227
- # @param [String] priority Priority of the event. Either "normal" (default) or "low".
228
- # @param [String] source_type_name The source type of the event.
229
- # @param [String] alert_type Either "error", "warning", "info" (default) or "success".
230
- # @param [Array, Hash] tags Tags to associate with the event.
231
- # @return [void]
232
- #
233
- # @note Supported by the Datadog implementation only.
234
- def service_check(name, status, timestamp: nil, hostname: nil, tags: nil, message: nil, no_prefix: false)
235
- emit(datagram_builder(no_prefix: no_prefix)._sc(name, status,
236
- timestamp: timestamp, hostname: hostname, tags: tags, message: message))
237
- end
339
+ # Emits an event. An event represents any record of activity noteworthy for engineers.
340
+ #
341
+ # @param title (see StatsD::Instrument::DogStatsDDatagramBuilder#_e)
342
+ # @param text (see StatsD::Instrument::DogStatsDDatagramBuilder#_e)
343
+ # @param timestamp (see StatsD::Instrument::DogStatsDDatagramBuilder#_e)
344
+ # @param hostname (see StatsD::Instrument::DogStatsDDatagramBuilder#_e)
345
+ # @param aggregation_key (see StatsD::Instrument::DogStatsDDatagramBuilder#_e)
346
+ # @param priority (see StatsD::Instrument::DogStatsDDatagramBuilder#_e)
347
+ # @param source_type_name (see StatsD::Instrument::DogStatsDDatagramBuilder#_e)
348
+ # @param alert_type (see StatsD::Instrument::DogStatsDDatagramBuilder#_e)
349
+ # @param tags (see StatsD::Instrument::DogStatsDDatagramBuilder#_e)
350
+ # @return [void]
351
+ #
352
+ # @note Supported by the Datadog implementation only.
353
+ def event(title, text, timestamp: nil, hostname: nil, aggregation_key: nil, priority: nil,
354
+ source_type_name: nil, alert_type: nil, tags: nil, no_prefix: false)
238
355
 
239
- # Emits an event.
240
- #
241
- # @param [String] name Name of the service
242
- # @param [Symbol] status Either `:ok`, `:warning`, `:critical` or `:unknown`
243
- # @param [Time] timestamp The moment when the service was checked. If not provided,
244
- # Datadog will interpret it as the current timestamp.
245
- # @param [String] hostname A hostname to associate with the check.
246
- # @param [Array, Hash] tags Tags to associate with the check.
247
- # @param [String] message A message describing the current state of the service check.
248
- # @return [void]
249
- #
250
- # @note Supported by the Datadog implementation only.
251
- def event(title, text, timestamp: nil, hostname: nil, aggregation_key: nil, priority: nil,
252
- source_type_name: nil, alert_type: nil, tags: nil, no_prefix: false)
253
-
254
- emit(datagram_builder(no_prefix: no_prefix)._e(title, text, timestamp: timestamp,
255
- hostname: hostname, tags: tags, aggregation_key: aggregation_key, priority: priority,
256
- source_type_name: source_type_name, alert_type: alert_type))
257
- end
356
+ emit(datagram_builder(no_prefix: no_prefix)._e(title, text, timestamp: timestamp,
357
+ hostname: hostname, tags: tags, aggregation_key: aggregation_key, priority: priority,
358
+ source_type_name: source_type_name, alert_type: alert_type))
359
+ end
258
360
 
259
- # Instantiates a new StatsD client that uses the settings of the current client,
260
- # except for the provided overrides.
261
- #
262
- # @yield [client] A new client will be constructed with the altered settings, and
263
- # yielded to the block. The original client will not be affected. The new client
264
- # will be disposed after the block returns
265
- # @return The return value of the block will be passed on as return value.
266
- def with_options(
267
- sink: nil,
268
- prefix: nil,
269
- default_sample_rate: nil,
270
- default_tags: nil,
271
- datagram_builder_class: nil
272
- )
273
- client = clone_with_options(sink: sink, prefix: prefix,
274
- default_sample_rate: default_sample_rate, default_tags: default_tags,
275
- datagram_builder_class: datagram_builder_class)
276
-
277
- yield(client)
278
- end
361
+ # Instantiates a new StatsD client that uses the settings of the current client,
362
+ # except for the provided overrides.
363
+ #
364
+ # @yield [client] A new client will be constructed with the altered settings, and
365
+ # yielded to the block. The original client will not be affected. The new client
366
+ # will be disposed after the block returns
367
+ # @return The return value of the block will be passed on as return value.
368
+ def with_options(
369
+ sink: nil,
370
+ prefix: nil,
371
+ default_sample_rate: nil,
372
+ default_tags: nil,
373
+ datagram_builder_class: nil
374
+ )
375
+ client = clone_with_options(sink: sink, prefix: prefix,
376
+ default_sample_rate: default_sample_rate, default_tags: default_tags,
377
+ datagram_builder_class: datagram_builder_class)
279
378
 
280
- def clone_with_options(
281
- sink: nil,
282
- prefix: nil,
283
- default_sample_rate: nil,
284
- default_tags: nil,
285
- datagram_builder_class: nil
286
- )
287
- self.class.new(
288
- sink: sink || @sink,
289
- prefix: prefix || @prefix,
290
- default_sample_rate: default_sample_rate || @default_sample_rate,
291
- default_tags: default_tags || @default_tags,
292
- datagram_builder_class: datagram_builder_class || @datagram_builder_class,
293
- )
294
- end
379
+ yield(client)
380
+ end
295
381
 
296
- def capture_sink
297
- StatsD::Instrument::CaptureSink.new(
298
- parent: @sink,
299
- datagram_class: datagram_builder_class.datagram_class,
300
- )
301
- end
382
+ def clone_with_options(
383
+ sink: nil,
384
+ prefix: nil,
385
+ default_sample_rate: nil,
386
+ default_tags: nil,
387
+ datagram_builder_class: nil
388
+ )
389
+ self.class.new(
390
+ sink: sink || @sink,
391
+ prefix: prefix || @prefix,
392
+ default_sample_rate: default_sample_rate || @default_sample_rate,
393
+ default_tags: default_tags || @default_tags,
394
+ datagram_builder_class: datagram_builder_class || @datagram_builder_class,
395
+ )
396
+ end
302
397
 
303
- def with_capture_sink(capture_sink)
304
- @sink = capture_sink
305
- yield
306
- ensure
307
- @sink = @sink.parent
308
- end
398
+ def capture_sink
399
+ StatsD::Instrument::CaptureSink.new(
400
+ parent: @sink,
401
+ datagram_class: datagram_builder_class.datagram_class,
402
+ )
403
+ end
309
404
 
310
- # Captures metrics that were emitted during the provided block.
311
- #
312
- # @yield During the execution of the provided block, metrics will be captured.
313
- # @return [Array<StatsD::Instagram::Datagram>] The list of metrics that were
314
- # emitted during the block, in the same order in which they were emitted.
315
- def capture(&block)
316
- sink = capture_sink
317
- with_capture_sink(sink, &block)
318
- sink.datagrams
319
- end
405
+ def with_capture_sink(capture_sink)
406
+ @sink = capture_sink
407
+ yield
408
+ ensure
409
+ @sink = @sink.parent
410
+ end
320
411
 
321
- protected
412
+ # Captures metrics that were emitted during the provided block.
413
+ #
414
+ # @yield During the execution of the provided block, metrics will be captured.
415
+ # @return [Array<StatsD::Instagram::Datagram>] The list of metrics that were
416
+ # emitted during the block, in the same order in which they were emitted.
417
+ def capture(&block)
418
+ sink = capture_sink
419
+ with_capture_sink(sink, &block)
420
+ sink.datagrams
421
+ end
322
422
 
323
- def datagram_builder(no_prefix:)
324
- @datagram_builder[no_prefix] ||= @datagram_builder_class.new(
325
- prefix: no_prefix ? nil : prefix,
326
- default_tags: default_tags,
327
- )
328
- end
423
+ protected
329
424
 
330
- def sample?(sample_rate)
331
- @sink.sample?(sample_rate)
332
- end
425
+ def datagram_builder(no_prefix:)
426
+ @datagram_builder[no_prefix] ||= @datagram_builder_class.new(
427
+ prefix: no_prefix ? nil : prefix,
428
+ default_tags: default_tags,
429
+ )
430
+ end
431
+
432
+ def sample?(sample_rate)
433
+ @sink.sample?(sample_rate)
434
+ end
333
435
 
334
- def emit(datagram)
335
- @sink << datagram
336
- StatsD::Instrument::VOID
436
+ def emit(datagram)
437
+ @sink << datagram
438
+ StatsD::Instrument::VOID
439
+ end
440
+ end
337
441
  end
338
442
  end