Class: StatsD::Instrument::Client

Inherits:
Object
  • Object
show all
Includes:
Strict
Defined in:
lib/statsd/instrument/client.rb

Overview

The Client is the main interface for using StatsD. It defines the metric methods that you would normally call from your application.

The client set to StatsD.singleton_client will handle all metric calls made against the StatsD singleton, e.g. StatsD.increment.

We recommend that the configuration of the StatsD setup is provided through environment variables

You are encouraged to instantiate multiple clients, and instantiate variants of an existing clients using #clone_with_options. We recommend instantiating a separate client for every logical component of your application using clone_with_options, and setting a different metric prefix.

Instance Attribute Summary collapse

Metric Methods collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(prefix: nil, default_sample_rate: 1.0, default_tags: nil, implementation: "datadog", sink: StatsD::Instrument::NullSink.new, datagram_builder_class: self.class.datagram_builder_class_for_implementation(implementation)) ⇒ Client

Instantiates a new client.



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/statsd/instrument/client.rb', line 147

def initialize(
  prefix: nil,
  default_sample_rate: 1.0,
  default_tags: nil,
  implementation: "datadog",
  sink: StatsD::Instrument::NullSink.new,
  datagram_builder_class: self.class.datagram_builder_class_for_implementation(implementation)
)
  @sink = sink
  @datagram_builder_class = datagram_builder_class

  @prefix = prefix
  @default_tags = default_tags
  @default_sample_rate = default_sample_rate

  @datagram_builder = { false => nil, true => nil }
end

Instance Attribute Details

#datagram_builder_classClass (readonly)

The class to use to build StatsD datagrams. To build the actual datagrams, the class will be instantiated, potentially multiple times, by the client.



71
72
73
# File 'lib/statsd/instrument/client.rb', line 71

def datagram_builder_class
  @datagram_builder_class
end

#default_sample_rateFloat (readonly)

The default sample rate to use for metrics that are emitted without a sample rate set. This should be a value between 0 (never emit a metric) and 1.0 (always emit). If it is not set, the default value 1.0 is used.

We generally recommend setting sample rates on individual metrics based on their frequency, rather than changing the default sample rate.



143
144
145
# File 'lib/statsd/instrument/client.rb', line 143

def default_sample_rate
  @default_sample_rate
end

#default_tagsArray<String>, ... (readonly)

The tags to apply to all the metrics emitted through this client.

The tags can be supplied in normal form: an array of strings. You can also provide a hash, which will be turned into normal form by concatanting the key and the value using a colon. To not use any default tags, set to nil. Note that other components of your StatsD metric pipeline may also add tags to metrics. E.g. the DataDog agent may add add tags like hostname.

We generally recommend to not use default tags, or use them sparingly. Adding tags to every metric easily introduces carninality explosions, which will make metrics less precise due to the lossy nature of aggregation. It also makes your infrastructure more expsnive to run, and the user interface of your metric explorer less responsive.



133
134
135
# File 'lib/statsd/instrument/client.rb', line 133

def default_tags
  @default_tags
end

#prefixString? (readonly)

Note:

The prefix can be overridden by any metric call by setting the no_prefix keyword argument to true. We recommend against doing this, but this behavior is retained for backwards compatibility. Rather, when you feel the need to do this, we recommend instantiating a new client without prefix (using #clone_with_options), and using it to emit the metric.

The prefix to prepend to the metric names that are emitted through this client, using a dot (.) as namespace separator. E.g. when the prefix is set to foo, and you emit a metric named bar, the metric name will be foo.bar.

Generally all the metrics you emit to the same StatsD server will share a single, global namespace. If you are emitting metrics from multiple applications, using a prefix is recommended to prevent metric name collisions.

You can also leave this value to be nil if you don't want to prefix your metric names.



116
117
118
# File 'lib/statsd/instrument/client.rb', line 116

def prefix
  @prefix
end

#sink#sample?, #<< (readonly)

The sink to send UDP datagrams to.

This can be set to any object that responds to the following methods:

  • sample? which should return true if the metric should be sampled, i.e. actually sent to the sink.
  • #<< which takes a UDP datagram as string to emit the datagram. This method will only be called if sample? returned true.

Generally, you should use an instance of one of the following classes that ship with this library:

  • UDPSink A sink that will actually emit the provided datagrams over UDP.
  • NullSink A sink that will simply swallow every datagram. This sink is for use when testing your application.
  • LogSink A sink that log all provided datagrams to a Logger, normally StatsD.logger.


93
94
95
# File 'lib/statsd/instrument/client.rb', line 93

def sink
  @sink
end

Class Method Details

.datagram_builder_class_for_implementation(implementation) ⇒ Class

Finds the right DatagramBuilder class for a given implementation.

Raises:

  • NotImplementedError if the implementation is not recognized or supported.



54
55
56
57
58
59
60
61
62
63
# File 'lib/statsd/instrument/client.rb', line 54

def datagram_builder_class_for_implementation(implementation)
  case implementation.to_s
  when "statsd"
    StatsD::Instrument::StatsDDatagramBuilder
  when "datadog", "dogstatsd"
    StatsD::Instrument::DogStatsDDatagramBuilder
  else
    raise NotImplementedError, "Implementation named #{implementation} could not be found"
  end
end

.from_env(env = StatsD::Instrument::Environment.current, prefix: env.statsd_prefix, default_sample_rate: env.statsd_sample_rate, default_tags: env.statsd_default_tags, implementation: env.statsd_implementation, sink: env.default_sink_for_environment, datagram_builder_class: datagram_builder_class_for_implementation(implementation)) ⇒ Object

Instantiates a StatsD::Instrument::Client using configuration values provided in environment variables.

See Also:



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/statsd/instrument/client.rb', line 27

def from_env(
  env = StatsD::Instrument::Environment.current,
  prefix: env.statsd_prefix,
  default_sample_rate: env.statsd_sample_rate,
  default_tags: env.statsd_default_tags,
  implementation: env.statsd_implementation,
  sink: env.default_sink_for_environment,
  datagram_builder_class: datagram_builder_class_for_implementation(implementation)
)
  new(
    prefix: prefix,
    default_sample_rate: default_sample_rate,
    default_tags: default_tags,
    implementation: implementation,
    sink: sink,
    datagram_builder_class: datagram_builder_class,
  )
end

Instance Method Details

#capture { ... } ⇒ Array<StatsD::Instagram::Datagram>

Captures metrics that were emitted during the provided block.

Yields:

  • During the execution of the provided block, metrics will be captured.



423
424
425
426
427
# File 'lib/statsd/instrument/client.rb', line 423

def capture(&block)
  sink = capture_sink
  with_capture_sink(sink, &block)
  sink.datagrams
end

#capture_sinkObject



404
405
406
407
408
409
# File 'lib/statsd/instrument/client.rb', line 404

def capture_sink
  StatsD::Instrument::CaptureSink.new(
    parent: @sink,
    datagram_class: datagram_builder_class.datagram_class,
  )
end

#clone_with_options(sink: nil, prefix: nil, default_sample_rate: nil, default_tags: nil, datagram_builder_class: nil) ⇒ Object



388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/statsd/instrument/client.rb', line 388

def clone_with_options(
  sink: nil,
  prefix: nil,
  default_sample_rate: nil,
  default_tags: nil,
  datagram_builder_class: nil
)
  self.class.new(
    sink: sink || @sink,
    prefix: prefix || @prefix,
    default_sample_rate: default_sample_rate || @default_sample_rate,
    default_tags: default_tags || @default_tags,
    datagram_builder_class: datagram_builder_class || @datagram_builder_class,
  )
end

#distribution(name, value = nil, sample_rate: nil, tags: nil, no_prefix: false, &block) ⇒ void

Note:

The distribution metric type is not available on all implementations. A NotImplementedError will be raised if you call this method, but the active implementation does not support it.

This method returns an undefined value.

Emits a distribution metric, which builds a histogram of the reported values.



271
272
273
274
275
276
277
278
279
280
# File 'lib/statsd/instrument/client.rb', line 271

def distribution(name, value = nil, sample_rate: nil, tags: nil, no_prefix: false, &block)
  if block_given?
    return latency(name, sample_rate: sample_rate, tags: tags, metric_type: :d, no_prefix: no_prefix, &block)
  end

  sample_rate ||= @default_sample_rate
  return StatsD::Instrument::VOID unless sample?(sample_rate)

  emit(datagram_builder(no_prefix: no_prefix).d(name, value, sample_rate, tags))
end

#event(title, text, timestamp: nil, hostname: nil, aggregation_key: nil, priority: nil, source_type_name: nil, alert_type: nil, tags: nil, no_prefix: false) ⇒ void

Note:

Supported by the Datadog implementation only.

This method returns an undefined value.

Emits an event. An event represents any record of activity noteworthy for engineers.



359
360
361
362
363
364
365
# File 'lib/statsd/instrument/client.rb', line 359

def event(title, text, timestamp: nil, hostname: nil, aggregation_key: nil, priority: nil,
  source_type_name: nil, alert_type: nil, tags: nil, no_prefix: false)

  emit(datagram_builder(no_prefix: no_prefix)._e(title, text, timestamp: timestamp,
    hostname: hostname, tags: tags, aggregation_key: aggregation_key, priority: priority,
    source_type_name: source_type_name, alert_type: alert_type))
end

#gauge(name, value, sample_rate: nil, tags: nil, no_prefix: false) ⇒ void

This method returns an undefined value.

Emits a gauge metric.

You should use a gauge if you are reporting the current value of something that can only have one value at the time. E.g., the speed of your car. A newly reported value will replace the previously reported value.



238
239
240
241
242
243
# File 'lib/statsd/instrument/client.rb', line 238

def gauge(name, value, sample_rate: nil, tags: nil, no_prefix: false)
  sample_rate ||= @default_sample_rate
  return StatsD::Instrument::VOID unless sample?(sample_rate)

  emit(datagram_builder(no_prefix: no_prefix).g(name, value, sample_rate, tags))
end

#histogram(name, value, sample_rate: nil, tags: nil, no_prefix: false) ⇒ void

Note:

The histogram metric type is not available on all implementations. A NotImplementedError will be raised if you call this method, but the active implementation does not support it.

This method returns an undefined value.

Emits a histogram metric, which builds a histogram of the reported values.



293
294
295
296
297
298
# File 'lib/statsd/instrument/client.rb', line 293

def histogram(name, value, sample_rate: nil, tags: nil, no_prefix: false)
  sample_rate ||= @default_sample_rate
  return StatsD::Instrument::VOID unless sample?(sample_rate)

  emit(datagram_builder(no_prefix: no_prefix).h(name, value, sample_rate, tags))
end

#increment(name, value = 1, sample_rate: nil, tags: nil, no_prefix: false) ⇒ void

This method returns an undefined value.

Emits a counter metric.

You should use a counter metric to count the frequency of something happening. As a result, the value should generally be set to 1 (the default), unless you reporting about a batch of activity. E.g. increment('messages.processed', messages.size) For values that are not frequencies, you should use another metric type, e.g. #histogram or #distribution.



200
201
202
203
204
205
# File 'lib/statsd/instrument/client.rb', line 200

def increment(name, value = 1, sample_rate: nil, tags: nil, no_prefix: false)
  sample_rate ||= @default_sample_rate
  return StatsD::Instrument::VOID unless sample?(sample_rate)

  emit(datagram_builder(no_prefix: no_prefix).c(name, value, sample_rate, tags))
end

#latency(name, sample_rate: nil, tags: nil, metric_type: nil, no_prefix: false) { ... } ⇒ Object

Measures the latency of the given block in milliseconds, and emits it as a metric.

Yields:

  • The latency (execution time) of the block



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/statsd/instrument/client.rb', line 312

def latency(name, sample_rate: nil, tags: nil, metric_type: nil, no_prefix: false)
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  begin
    yield
  ensure
    stop = Process.clock_gettime(Process::CLOCK_MONOTONIC)

    sample_rate ||= @default_sample_rate
    if sample?(sample_rate)
      metric_type ||= datagram_builder(no_prefix: no_prefix).latency_metric_type
      latency_in_ms = 1000.0 * (stop - start)
      emit(datagram_builder(no_prefix: no_prefix).send(metric_type, name, latency_in_ms, sample_rate, tags))
    end
  end
end

#measure(name, value = nil, sample_rate: nil, tags: nil, no_prefix: false, &block) ⇒ void

This method returns an undefined value.

Emits a timing metric.



214
215
216
217
218
219
220
221
222
223
# File 'lib/statsd/instrument/client.rb', line 214

def measure(name, value = nil, sample_rate: nil, tags: nil, no_prefix: false, &block)
  if block_given?
    return latency(name, sample_rate: sample_rate, tags: tags, metric_type: :ms, no_prefix: no_prefix, &block)
  end

  sample_rate ||= @default_sample_rate
  return StatsD::Instrument::VOID unless sample?(sample_rate)

  emit(datagram_builder(no_prefix: no_prefix).ms(name, value, sample_rate, tags))
end

#service_check(name, status, timestamp: nil, hostname: nil, tags: nil, message: nil, no_prefix: false) ⇒ void

Note:

Supported by the Datadog implementation only.

This method returns an undefined value.

Emits a service check. Services Checks allow you to characterize the status of a service in order to monitor it within Datadog.



340
341
342
343
# File 'lib/statsd/instrument/client.rb', line 340

def service_check(name, status, timestamp: nil, hostname: nil, tags: nil, message: nil, no_prefix: false)
  emit(datagram_builder(no_prefix: no_prefix)._sc(name, status,
    timestamp: timestamp, hostname: hostname, tags: tags, message: message))
end

#set(name, value, sample_rate: nil, tags: nil, no_prefix: false) ⇒ void

This method returns an undefined value.

Emits a set metric, which counts distinct values.



252
253
254
255
256
257
# File 'lib/statsd/instrument/client.rb', line 252

def set(name, value, sample_rate: nil, tags: nil, no_prefix: false)
  sample_rate ||= @default_sample_rate
  return StatsD::Instrument::VOID unless sample?(sample_rate)

  emit(datagram_builder(no_prefix: no_prefix).s(name, value, sample_rate, tags))
end

#with_capture_sink(capture_sink) ⇒ Object



411
412
413
414
415
416
# File 'lib/statsd/instrument/client.rb', line 411

def with_capture_sink(capture_sink)
  @sink = capture_sink
  yield
ensure
  @sink = @sink.parent
end

#with_options(sink: nil, prefix: nil, default_sample_rate: nil, default_tags: nil, datagram_builder_class: nil) {|client| ... } ⇒ Object

Instantiates a new StatsD client that uses the settings of the current client, except for the provided overrides.

Yields:

  • (client)

    A new client will be constructed with the altered settings, and yielded to the block. The original client will not be affected. The new client will be disposed after the block returns



374
375
376
377
378
379
380
381
382
383
384
385
386
# File 'lib/statsd/instrument/client.rb', line 374

def with_options(
  sink: nil,
  prefix: nil,
  default_sample_rate: nil,
  default_tags: nil,
  datagram_builder_class: nil
)
  client = clone_with_options(sink: sink, prefix: prefix,
    default_sample_rate: default_sample_rate, default_tags: default_tags,
    datagram_builder_class: datagram_builder_class)

  yield(client)
end