Class: Graphiterb::Monitors::AccumulationsConsumer

Inherits:
PeriodicMonitor show all
Defined in:
lib/graphiterb/monitors/accumulations_consumer.rb

Overview

A monitor which consumes counts accumulated in a Redis store by Graphiterb::Accumulator.

Instance Attribute Summary collapse

Attributes inherited from PeriodicMonitor

#current_iter, #iter, #iter_interval, #last_time, #main_scope, #options, #started_at, #time_interval

Instance Method Summary collapse

Methods inherited from PeriodicMonitor

#enough_iterations?, #enough_time?, #inst_rate, #periodically, #rate, #run!, #scope, #sender, #since

Methods included from Utils::SystemInfo

#graphite_identifier, #hostname, #node_name

Constructor Details

#initialize(options = {}) ⇒ AccumulationsConsumer

Instantiate a new AccumulationsConsumer.

Options are passed to Redis.new as well as Graphiterb::Monitors::PeriodicMonitor.

Include the :namespace option to tell this consumer which Redis namespace to consume keys from (defaults to ‘graphiterb’).

Include the :regexp option if you want this monitor to only consume keys corresponding to Graphite targets which match the regexp. This is useful for having multiple AccumulationsConsumer monitors running with different frequencies tracking different Graphite target families.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/graphiterb/monitors/accumulations_consumer.rb', line 40

def initialize options={}
  require 'redis'
  begin
    require 'redis-namespace'
  rescue LoadError
    require 'redis/namespace'
  end
  @redis        = Redis.new(options)
  @namespace    = options[:namespace] || 'graphiterb'
  @accumulators = Redis::Namespace.new(namespace, :redis => @redis)
  @regexp       = options[:regexp] || /.*/
  @report_timestamp_key = options[:report_timestamp_key] || '_last_report_timestamp_'
  super('fake_scope', options) # FIXME shouldn't have to use a fake scope
end

Instance Attribute Details

#accumulatorsObject

The Redis namespace used for the accumulators.



20
21
22
# File 'lib/graphiterb/monitors/accumulations_consumer.rb', line 20

def accumulators
  @accumulators
end

#namespaceObject

The name of the Redis namespace (a string) in which accumulations are stored (defaults to ‘graphiterb’)



13
14
15
# File 'lib/graphiterb/monitors/accumulations_consumer.rb', line 13

def namespace
  @namespace
end

#redisObject

The Redis database.



9
10
11
# File 'lib/graphiterb/monitors/accumulations_consumer.rb', line 9

def redis
  @redis
end

#regexpObject

A regular expression that must match the Graphite target (defaults to always matching).



24
25
26
# File 'lib/graphiterb/monitors/accumulations_consumer.rb', line 24

def regexp
  @regexp
end

#report_timestamp_keyObject

The key used to store the last report time. Will live inside the namespace.



17
18
19
# File 'lib/graphiterb/monitors/accumulations_consumer.rb', line 17

def report_timestamp_key
  @report_timestamp_key
end

Instance Method Details

#get_metrics(metrics, since) ⇒ Object

Uses Redis’ getset call to retrieve total accumulated counts from Redis and reset them to 0 atomically.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/graphiterb/monitors/accumulations_consumer.rb', line 57

def get_metrics metrics, since
  # compute the length of the interval between the last time
  # this monitor ran and now
  last_report_timestamp = accumulators.get(report_timestamp_key).to_i
  now                   = Time.now.to_i
  interval              = now - last_report_timestamp

  accumulators.keys.each do |target|
    next if target == report_timestamp_key
    next unless regexp && regexp =~ target
    current_count = accumulators.getset(target, 0) rescue 0.0

    # if we don't know when the last time we ran was, we bail,
    # resetting the accumulated count to 0 in preparation for
    # the next iteration
    #
    # we lost a data point this way (say the monitor went down
    # for a while and we brought it back up) but we also don't
    # ruin the scale of the graph...
    next if last_report_timestamp == 0
    
    rate          = current_count.to_f / interval.to_f rescue 0.0
    metrics << [target, rate] # no need to scope as targets are pre-scoped
  end

  # store the timestamp for this run for the next
  accumulators.set(report_timestamp_key, now)
end