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
Set to a standard logger instance to enable debug logging.
The default batch size for new batches (default: 10)
StatsD host. Defaults to 127.0.0.1.
A namespace to prepend to all statsd calls.
StatsD port. Defaults to 8125.
a postfix to append to all metrics
StatsD namespace prefix, generated from namespace
Public Class Methods
@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
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
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
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
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
@attribute [w] host
Writes are not thread safe.
# File lib/statsd.rb, line 265 def host=(host) @host = host || '127.0.0.1' end
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
@attribute [w] namespace
Writes are not thread safe.
# File lib/statsd.rb, line 248 def namespace=(namespace) @namespace = namespace @prefix = "#{namespace}." end
@attribute [w] port
Writes are not thread safe.
# File lib/statsd.rb, line 271 def port=(port) @port = port || 8125 end
@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
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
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
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
# 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
# File lib/statsd.rb, line 399 def addr_family Addrinfo.udp(@host, @port).ipv6? ? Socket::AF_INET6 : Socket::AF_INET end
# 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
# File lib/statsd.rb, line 395 def socket @socket || Thread.current[:statsd_socket] ||= UDPSocket.new(addr_family) end