module FFWD::Plugin::Collectd::Parser

An parser implementation of collectd.org/wiki/index.php/Binary_protocol

Constants

ABSOLUTE
B64
COUNTER
DERIVE
FACTOR_HR
GAUGE
HOST
INTERVAL
INTERVAL_HR
MESSAGE
PLUGIN
PLUGIN_INSTANCE
SB64
SEVERITY
TIME
TIME_HR
TYPE
TYPE_INSTANCE
VALUES

Public Class Methods

interval_high_res(frame, i, size) click to toggle source
# File lib/ffwd/plugin/collectd/parser.rb, line 104
def self.interval_high_res frame, i, size
  numeric(frame, i, size).to_f / FACTOR_HR
end
numeric(frame, i, size) click to toggle source
# File lib/ffwd/plugin/collectd/parser.rb, line 96
def self.numeric frame, i, size
  unsigned_integer frame[4 + i, 8]
end
parse(frame) { |current| ... } click to toggle source

Maintain a current frame, and yield a copy of it to the subscribing block.

Reading a ‘values’ part is the indicator that a block is ‘ready’.

# File lib/ffwd/plugin/collectd/parser.rb, line 112
def self.parse frame
  raise "invalid frame" if frame.size < 4

  current = {}

  i = 0

  loop do
    break if i >= frame.size

    type, size = frame[i,4].unpack("nn")

    case type
    when HOST
      current[:host] = self.string(frame, i, size)
    when TIME
      current[:time] = Time.at(self.numeric(frame, i, size))
    when TIME_HR
      current[:time] = self.time_high_res(frame, i, size)
    when PLUGIN
      current[:plugin] = self.string(frame, i, size)
    when PLUGIN_INSTANCE
      current[:plugin_instance] = self.string(frame, i, size)
    when TYPE
      current[:type] = self.string(frame, i, size)
    when TYPE_INSTANCE
      current[:type_instance] = self.string(frame, i, size)
    when VALUES
      values = self.values(frame, i, size)
      current[:values] = values
      yield current
    when INTERVAL
      current[:interval] = self.numeric(frame, i, size).to_f
    when INTERVAL_HR
      current[:interval] = self.interval_high_res(frame, i, size)
    when MESSAGE
      current[:message] = self.string(frame, i, size)
    when SEVERITY
      current[:severity] = self.numeric(frame, i, size)
    else
      log.warning("cannot understand type: #{type}")
    end

    i += size
  end
end
signed_integer(data) click to toggle source
# File lib/ffwd/plugin/collectd/parser.rb, line 52
def self.signed_integer data
  us = unsigned_integer(data)

  if (us & SB64) == SB64
    us - B64
  else
    us
  end
end
string(frame, i, size) click to toggle source
# File lib/ffwd/plugin/collectd/parser.rb, line 92
def self.string frame, i, size
  frame[4 + i, (size - 5)]
end
time_high_res(frame, i, size) click to toggle source
# File lib/ffwd/plugin/collectd/parser.rb, line 100
def self.time_high_res frame, i, size
  Time.at(numeric(frame, i, size).to_f / FACTOR_HR)
end
unsigned_integer(data) click to toggle source
# File lib/ffwd/plugin/collectd/parser.rb, line 47
def self.unsigned_integer data
  high, low = data.unpack("NN")
  ((high << 32) | low)
end
values(frame, i, size) click to toggle source
# File lib/ffwd/plugin/collectd/parser.rb, line 62
def self.values frame, i, size
  n = frame[i + 4, 2].unpack("n")[0]

  result = []

  types = frame[i + 6, n].unpack("C" * n)

  types.each_with_index do |type, j|
    o = 6 + n + (j * 8)
    data = frame[i + o, 8]

    case type
    when COUNTER
      result << [:counter, self.unsigned_integer(data)]
    when GAUGE
      result << [:gauge, data.unpack("E")[0]]
    when DERIVE
      result << [:derive, self.signed_integer(data)]
    when ABSOLUTE
      result << [:absolute, self.unsigned_integer(data)]
    else
      raise "unkonwn value type: #{type}"
    end

    j += 1
  end

  result
end