lib/visage-app/collectd/json.rb in visage-app-1.0.0 vs lib/visage-app/collectd/json.rb in visage-app-2.0.0
- old
+ new
@@ -8,135 +8,132 @@
# Exposes RRDs as JSON.
#
# A loose shim onto RRDtool, with some extra logic to normalise the data.
#
-class CollectdJSON
+module Visage
+ module Collectd
+ class JSON
- def initialize(opts={})
- @rrddir = opts[:rrddir] || CollectdJSON.rrddir
- @types = opts[:types] || CollectdJSON.types
- end
+ def initialize(opts={})
+ @rrddir = opts[:rrddir] || Visage::Collectd::JSON.rrddir
+ @types = opts[:types] || Visage::Collectd::JSON.types
+ end
- # Entry point.
- def json(opts={})
- host = opts[:host]
- plugin = opts[:plugin]
- plugin_instances = opts[:plugin_instances][/\w.*/]
- instances = plugin_instances.blank? ? '*' : '{' + plugin_instances.split('/').join(',') + '}'
- rrdglob = "#{@rrddir}/#{host}/#{plugin}/#{instances}.rrd"
+ def parse_time(time, opts={})
+ case
+ when time && time.index('.')
+ time.split('.').first.to_i
+ when time
+ time.to_i
+ else
+ opts[:default] || Time.now.to_i
+ end
+ end
- start = case
- when opts[:start] && opts[:start].index('.')
- opts[:start].split('.').first
- when opts[:start]
- opts[:start]
- else
- (Time.now - 3600).to_i
- end
+ # Entry point.
+ def json(opts={})
+ host = opts[:host]
+ plugin = opts[:plugin]
+ instances = opts[:instances][/\w.*/]
+ instances = instances.blank? ? '*' : '{' + instances.split('/').join(',') + '}'
+ rrdglob = "#{@rrddir}/#{host}/#{plugin}/#{instances}.rrd"
+ finish = parse_time(opts[:finish])
+ start = parse_time(opts[:start], :default => (finish - 3600 || (Time.now - 3600).to_i))
+ data = []
- finish = case
- when opts[:finish] && opts[:finish].index('.')
- opts[:finish].split('.').first
- when opts[:finish]
- opts[:finish]
- else
- Time.now.to_i
- end
+ Dir.glob(rrdglob).map do |rrdname|
+ parts = rrdname.gsub(/#{@rrddir}\//, '').split('/')
+ host_name = parts[0]
+ plugin_name = parts[1]
+ instance_name = File.basename(parts[2], '.rrd')
+ rrd = Errand.new(:filename => rrdname)
- data = []
+ data << { :plugin => plugin_name, :instance => instance_name,
+ :host => host_name,
+ :start => start,
+ :finish => finish,
+ :rrd => rrd }
+ end
- Dir.glob(rrdglob).map do |rrdname|
- parts = rrdname.gsub(/#{@rrddir}\//, '').split('/')
- host_name = parts[0]
- plugin_name = parts[1]
- instance_name = File.basename(parts[2], '.rrd')
- rrd = Errand.new(:filename => rrdname)
+ encode(data)
+ end
+ private
+ # Attempt to structure the JSON reasonably sanely, so the consumer (i.e. a
+ # browser) doesn't have to do a lot of computationally expensive work.
+ def encode(datas)
- data << { :plugin => plugin_name, :instance => instance_name,
- :host => host_name,
- :start => start,
- :finish => finish,
- :rrd => rrd }
- end
+ structure = {}
+ datas.each do |data|
+ fetch = data[:rrd].fetch(:function => "AVERAGE",
+ :start => data[:start],
+ :finish => data[:finish])
+ rrd_data = fetch[:data]
- encode(data)
- end
+ # A single rrd can have multiple data sets (multiple metrics within
+ # the same file). Separate the metrics.
+ rrd_data.each_pair do |source, metric|
- private
- # Attempt to structure the JSON reasonably sanely, so the consumer (i.e. a
- # browser) doesn't have to do a lot of computationally expensive work.
- def encode(datas)
+ # Filter out NaNs and weirdly massive values so yajl doesn't choke
+ metric.map! do |datapoint|
+ case
+ when datapoint && datapoint.nan?
+ @tripped = true
+ @last_valid
+ when @tripped
+ @last_valid
+ else
+ @last_valid = datapoint
+ end
+ end
- structure = {}
- datas.each do |data|
- fetch = data[:rrd].fetch(:function => "AVERAGE",
- :start => data[:start],
- :finish => data[:finish])
- rrd_data = fetch[:data]
+ # Last value is always wack. Set to 0, so the timescale isn't off by 1.
+ metric[-1] = 0.0
+ host = data[:host]
+ plugin = data[:plugin]
+ instance = data[:instance]
+ start = data[:start].to_i
+ finish = data[:finish].to_i
- # A single rrd can have multiple data sets (multiple metrics within
- # the same file). Separate the metrics.
- rrd_data.each_pair do |source, metric|
+ structure[host] ||= {}
+ structure[host][plugin] ||= {}
+ structure[host][plugin][instance] ||= {}
+ structure[host][plugin][instance][source] ||= {}
+ structure[host][plugin][instance][source][:start] ||= start
+ structure[host][plugin][instance][source][:finish] ||= finish
+ structure[host][plugin][instance][source][:data] ||= metric
- # Filter out NaNs and weirdly massive values so yajl doesn't choke
- metric.map! do |datapoint|
- case
- when datapoint && datapoint.nan?
- @tripped = true
- @last_valid
- when @tripped
- @last_valid
- else
- @last_valid = datapoint
end
end
- # Last value is always wack. Set to 0, so the timescale isn't off by 1.
- metric[-1] = 0.0
- host = data[:host]
- plugin = data[:plugin]
- instance = data[:instance]
- start = data[:start].to_i
- finish = data[:finish].to_i
-
- structure[host] ||= {}
- structure[host][plugin] ||= {}
- structure[host][plugin][instance] ||= {}
- structure[host][plugin][instance][source] ||= {}
- structure[host][plugin][instance][source][:start] ||= start
- structure[host][plugin][instance][source][:finish] ||= finish
- structure[host][plugin][instance][source][:data] ||= metric
-
+ encoder = Yajl::Encoder.new
+ encoder.encode(structure)
end
- end
- encoder = Yajl::Encoder.new
- encoder.encode(structure)
- end
+ class << self
+ attr_writer :rrddir
- class << self
- attr_writer :rrddir
+ def rrddir
+ @rrddir ||= Visage::Config.rrddir
+ end
- def rrddir
- @rrddir ||= Visage::Config.rrddir
- end
+ def types
+ @types ||= Visage::Config.types
+ end
- def types
- @types ||= Visage::Config.types
- end
+ def hosts
+ if @rrddir
+ Dir.glob("#{@rrddir}/*").map {|e| e.split('/').last }.sort
+ end
+ end
- def hosts
- if @rrddir
- Dir.glob("#{@rrddir}/*").map {|e| e.split('/').last }.sort
+ def plugins(opts={})
+ host = opts[:host] || '*'
+ Dir.glob("#{@rrddir}/#{host}/*").map {|e| e.split('/').last }.sort
+ end
+
end
- end
- def plugins(opts={})
- host = opts[:host] || '*'
- Dir.glob("#{@rrddir}/#{host}/*").map {|e| e.split('/').last }.sort
- end
-
- end
-
-end
+ end # class JSON
+ end # module Collectd
+end # module Visage