class Statsd

Statsd: A Statsd client (github.com/etsy/statsd)

@example Set up a global Statsd client for a server on localhost:8125

$statsd = Statsd.new 'localhost', 8125

@example Set up a global Statsd client for a server on IPv6 port 8125

$statsd = Statsd.new '::1', 8125

@example Send some stats

$statsd.increment 'garets'
$statsd.timing 'glork', 320
$statsd.gauge 'bork', 100

@example Use {#time} to time the execution of a block

$statsd.time('account.activate') { @account.activate! }

@example Create a namespaced statsd client and increment 'account.activate'

statsd = Statsd.new('localhost').tap{|sd| sd.namespace = 'account'}
statsd.increment 'activate'

Statsd instances are thread safe for general usage, by using a thread local UDPSocket and carrying no state. The attributes are stateful, and are not mutexed, it is expected that users will not change these at runtime in threaded environments. If users require such use cases, it is recommend that users either mutex around their Statsd object, or create separate objects for each namespace / host+port combination.

Attributes

logger[RW]

Set to a standard logger instance to enable debug logging.

batch_size[RW]

The default batch size for new batches (default: 10)

host[R]

StatsD host. Defaults to 127.0.0.1.

namespace[R]

A namespace to prepend to all statsd calls.

port[R]

StatsD port. Defaults to 8125.

postfix[R]

a postfix to append to all metrics

prefix[R]

StatsD namespace prefix, generated from namespace

Public Class Methods

new(host = '127.0.0.1', port = 8125, socket = nil) click to toggle source

@param [String] host your statsd host @param [Integer] port your statsd port @param [Object] A socket object (probably UDPSocket) to reuse

# File lib/statsd.rb, line 238
def initialize(host = '127.0.0.1', port = 8125, socket = nil)
  self.host, self.port = host, port
  @prefix = nil
  @batch_size = 10
  @postfix = nil
  @socket = socket
end

Public Instance Methods

batch(&block) click to toggle source

Creates and yields a Batch that can be used to batch instrument reports into larger packets. Batches are sent either when the packet is “full” (defined by batch_size), or when the block completes, whichever is the sooner.

@yield [Batch] a statsd subclass that collects and batches instruments @example Batch two instument operations:

$statsd.batch do |batch|
  batch.increment 'sys.requests'
  batch.gauge('user.count', User.count)
end
# File lib/statsd.rb, line 370
def batch(&block)
  Batch.new(self).easy &block
end
count(stat, count, sample_rate=1) click to toggle source

Sends an arbitrary count for the given stat to the statsd server.

@param [String] stat stat name @param [Integer] count count @param [Numeric] sample_rate sample rate, 1 for always

# File lib/statsd.rb, line 298
def count(stat, count, sample_rate=1)
  send_stats stat, count, :c, sample_rate
end
decrement(stat, sample_rate=1) click to toggle source

Sends a decrement (count = -1) for the given stat to the statsd server.

@param [String] stat stat name @param [Numeric] sample_rate sample rate, 1 for always @see count

# File lib/statsd.rb, line 289
def decrement(stat, sample_rate=1)
  count stat, -1, sample_rate
end
gauge(stat, value, sample_rate=1) click to toggle source

Sends an arbitary gauge value for the given stat to the statsd server.

This is useful for recording things like available disk space, memory usage, and the like, which have different semantics than counters.

@param [String] stat stat name. @param [Numeric] value gauge value. @param [Numeric] sample_rate sample rate, 1 for always @example Report the current user count:

$statsd.gauge('user.count', User.count)
# File lib/statsd.rb, line 313
def gauge(stat, value, sample_rate=1)
  send_stats stat, value, :g, sample_rate
end
host=(host) click to toggle source

@attribute [w] host

Writes are not thread safe.
# File lib/statsd.rb, line 265
def host=(host)
  @host = host || '127.0.0.1'
end
increment(stat, sample_rate=1) click to toggle source

Sends an increment (count = 1) for the given stat to the statsd server.

@param [String] stat stat name @param [Numeric] sample_rate sample rate, 1 for always @see count

# File lib/statsd.rb, line 280
def increment(stat, sample_rate=1)
  count stat, 1, sample_rate
end
namespace=(namespace) click to toggle source

@attribute [w] namespace

Writes are not thread safe.
# File lib/statsd.rb, line 248
def namespace=(namespace)
  @namespace = namespace
  @prefix = "#{namespace}."
end
port=(port) click to toggle source

@attribute [w] port

Writes are not thread safe.
# File lib/statsd.rb, line 271
def port=(port)
  @port = port || 8125
end
postfix=(pf) click to toggle source

@attribute [w] postfix

A value to be appended to the stat name after a '.'. If the value is
blank then the postfix will be reset to nil (rather than to '.').
# File lib/statsd.rb, line 256
def postfix=(pf)
  case pf
  when nil, false, '' then @postfix = nil
  else @postfix = ".#{pf}"
  end
end
set(stat, value, sample_rate=1) click to toggle source

Sends an arbitary set value for the given stat to the statsd server.

This is for recording counts of unique events, which are useful to see on graphs to correlate to other values. For example, a deployment might get recorded as a set, and be drawn as annotations on a CPU history graph.

@param [String] stat stat name. @param [Numeric] value event value. @param [Numeric] sample_rate sample rate, 1 for always @example Report a deployment happening:

$statsd.set('deployment', DEPLOYMENT_EVENT_CODE)
# File lib/statsd.rb, line 329
def set(stat, value, sample_rate=1)
  send_stats stat, value, :s, sample_rate
end
time(stat, sample_rate=1) { || ... } click to toggle source

Reports execution time of the provided block using {#timing}.

@param [String] stat stat name @param [Numeric] sample_rate sample rate, 1 for always @yield The operation to be timed @see timing @example Report the time (in ms) taken to activate an account

$statsd.time('account.activate') { @account.activate! }
# File lib/statsd.rb, line 353
def time(stat, sample_rate=1)
  start = Time.now
  result = yield
  timing(stat, ((Time.now - start) * 1000).round, sample_rate)
  result
end
timing(stat, ms, sample_rate=1) click to toggle source

Sends a timing (in ms) for the given stat to the statsd server. The sample_rate determines what percentage of the time this report is sent. The statsd server then uses the sample_rate to correctly track the average timing for the stat.

@param [String] stat stat name @param [Integer] ms timing in milliseconds @param [Numeric] sample_rate sample rate, 1 for always

# File lib/statsd.rb, line 341
def timing(stat, ms, sample_rate=1)
  send_stats stat, ms, :ms, sample_rate
end

Protected Instance Methods

send_to_socket(message) click to toggle source
# File lib/statsd.rb, line 376
def send_to_socket(message)
  self.class.logger.debug { "Statsd: #{message}" } if self.class.logger
  socket.send(message, 0, @host, @port)
rescue => boom
  self.class.logger.error { "Statsd: #{boom.class} #{boom}" } if self.class.logger
  nil
end

Private Instance Methods

addr_family() click to toggle source
# File lib/statsd.rb, line 399
def addr_family
  Addrinfo.udp(@host, @port).ipv6? ? Socket::AF_INET6 : Socket::AF_INET
end
send_stats(stat, delta, type, sample_rate=1) click to toggle source
# File lib/statsd.rb, line 386
def send_stats(stat, delta, type, sample_rate=1)
  if sample_rate == 1 or rand < sample_rate
    # Replace Ruby module scoping with '.' and reserved chars (: | @) with underscores.
    stat = stat.to_s.gsub('::', '.').tr(':|@', '_')
    rate = "|@#{sample_rate}" unless sample_rate == 1
    send_to_socket "#{prefix}#{stat}#{postfix}:#{delta}|#{type}#{rate}"
  end
end
socket() click to toggle source
# File lib/statsd.rb, line 395
def socket
  @socket || Thread.current[:statsd_socket] ||= UDPSocket.new(addr_family)
end