lib/fozzie/classes.rb in fozzie-0.0.13 vs lib/fozzie/classes.rb in fozzie-0.0.14
- old
+ new
@@ -1,66 +1,136 @@
-require 'statsd'
-
module Fozzie
module Classes
- class AbstractFozzie < Statsd
+ class AbstractFozzie
+ RESERVED_CHARS_REGEX = /[\:\|\@]/
+
attr_reader :prefix, :configuration
- def initialize
- @namespace = Fozzie.c.data_prefix
- super Fozzie.c.host, Fozzie.c.port
+ # Sends an increment (count = 1) for the given stat to the statsd server.
+ #
+ # @param stat (see #count)
+ # @param sample_rate (see #count)
+ # @see #count
+ def increment(stat, sample_rate=1)
+ count(stat, 1, sample_rate)
+ end
- self
+ # Sends a decrement (count = -1) for the given stat to the statsd server.
+ #
+ # @param stat (see #count)
+ # @param sample_rate (see #count)
+ # @see #count
+ def decrement(stat, sample_rate=1)
+ count(stat, -1, sample_rate)
end
- def time_to_do(stat, sample_rate=1, &block); time_for(stat, sample_rate, &block); end
+ # Sends an arbitrary count for the given stat to the statsd server.
+ #
+ # @param [String] stat stat name
+ # @param [Integer] count count
+ # @param [Integer] sample_rate sample rate, 1 for always
+ def count(stat, count, sample_rate=1)
+ send(stat, count, 'c', sample_rate)
+ 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 stat stat name
+ # @param [Integer] ms timing in milliseconds
+ # @param [Integer] sample_rate sample rate, 1 for always
+ def timing(stat, ms, sample_rate=1)
+ send(stat, ms, 'ms', sample_rate)
+ end
+
+ # Reports execution time of the provided block using {#timing}.
+ #
+ # @param stat (see #timing)
+ # @param sample_rate (see #timing)
+ # @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! }
+ def time(stat, sample_rate=1)
+ stat = stat.flatten.join('.') if stat.kind_of?(Array)
+ start = Time.now
+ result = yield
+ timing(stat, ((Time.now - start) * 1000).round, sample_rate)
+ result
+ end
+
+ def time_to_do(stat, sample_rate=1, &block)
+ time_for(stat, sample_rate, &block)
+ end
+
def time_for(stat, sample_rate=1, &block)
- stat = stat.flatten.join('.') if stat.kind_of?(Array)
time(stat, sample_rate, &block)
end
- def committed; commit; end
def commit
event :commit
end
+ def committed; commit; end
- def build; built; end
def built
event :build
end
+ def build; built; end
- def deploy(app = nil); deployed(app); end
def deployed(app = nil)
event :deploy, app
end
+ def deploy(app = nil); deployed(app); end
def increment_on(stat, perf, sample_rate=1)
key = "#{stat}.%s" % (perf ? "success" : "fail")
increment(key, sample_rate)
perf
end
+ def logger
+ self.class.logger
+ end
+
+ def self.logger
+ @logger
+ end
+
private
def event(type, app = nil)
stat = "event.#{type.to_s}"
stat << ".#{app}" unless app.nil?
timing stat, Time.now.usec
end
def send_to_socket(message)
+ return false if Fozzie.c.ip_from_host.blank?
begin
- ip = Fozzie.c.ip_from_host
- raise RuntimeError, "Could not locate IP" unless ip
-
self.class.logger.debug {"Statsd: #{message}"} if self.class.logger
- socket.send(message, 0, ip, Fozzie.c.port)
- rescue SocketError, RuntimeError => exc
+ socket.send(message, 0, Fozzie.c.ip_from_host, Fozzie.c.port)
+ rescue SocketError, RuntimeError, Errno::EADDRNOTAVAIL, Timeout::Error => exc
self.class.logger.debug {"Statsd Failure: #{exc.message}"} if self.class.logger
nil
end
+ end
+
+ def sampled(sample_rate)
+ yield unless sample_rate < 1 and rand > sample_rate
+ end
+
+ def send(stat, delta, type, sample_rate)
+ prefix = "#{Fozzie.c.data_prefix}." unless Fozzie.c.data_prefix.nil?
+ stat = stat.to_s.gsub('::', '.').gsub(RESERVED_CHARS_REGEX, '_')
+ sampled(sample_rate) { send_to_socket("#{prefix}#{stat}:#{delta}|#{type}#{'|@' << sample_rate.to_s if sample_rate < 1}") }
+ end
+
+ def socket
+ @socket ||= UDPSocket.new
end
end
def self.included(klass)
\ No newline at end of file