lib/honeybadger/agent/metrics_collector.rb
require 'securerandom' require 'forwardable' module Honeybadger class Agent autoload :MetricsCollection, 'honeybadger/agent/metrics_collection' class MetricsCollector extend Forwardable class Chunk extend Forwardable attr_reader :id def initialize(id, metrics) @id = SecureRandom.uuid @metrics = metrics end def_delegators :@metrics, :to_json, :size end def initialize(config, interval = 60, now = now()) @id = SecureRandom.uuid @config = config @interval = interval @future = now + interval @mutex = Mutex.new @metrics = { :timing => {}, :counter => {} } end attr_reader :id def_delegators :@metrics, :[] def timing(name, value) add_metric(name, value, :timing) end def increment(name, value) add_metric(name, value, :counter) end def flush? now >= future end def size mutex.synchronize do metrics.reduce(0) do |count, hash| count + hash[1].size end end end def to_a mutex.synchronize do [].tap do |m| metrics[:counter].each do |metric, values| m << "#{metric} #{values.sum}" end metrics[:timing].each do |metric, values| m << "#{metric}:mean #{values.mean}" m << "#{metric}:median #{values.median}" m << "#{metric}:percentile_90 #{values.percentile(90)}" m << "#{metric}:min #{values.min}" m << "#{metric}:max #{values.max}" m << "#{metric}:stddev #{values.standard_dev}" if values.count > 1 m << "#{metric} #{values.count}" end m.compact! end end end def chunk(size) to_a.each_slice(size) do |metrics| yield(Chunk.new(id, as_json(metrics))) end end def as_json(metrics = to_a) {metrics: metrics, :environment => config[:env], :hostname => config[:hostname]} end def to_json(*args) as_json.to_json(*args) end private attr_reader :config, :future, :metrics, :mutex def now Time.now.to_i end def add_metric(name, value, kind) mutex.synchronize do (metrics[kind][name] ||= MetricsCollection.new) << value end end end end end