class Bosh::Monitor::Plugins::ConsulEventForwarder

Constants

CONSUL_ENDPOINTS
CONSUL_MAX_EVENT_BYTESIZE
CONSUL_REQUEST_HEADER
REQUIRED_OPTIONS
TTL_STATUS_MAP

Public Instance Methods

process(event) click to toggle source
# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 47
def process(event)
  validate_options && forward_event(event)
end
run() click to toggle source
# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 22
def run
  @checklist       = []
  @host            = options['host']
  @namespace       = options['namespace']
  @port            = options['port']
  @protocol        = options['protocol']
  @params          = options['params']
  @ttl             = options['ttl']
  @use_events      = options['events']
  @ttl_note        = options['ttl_note']

  @heartbeats_as_alerts = options['heartbeats_as_alerts']
  @use_ttl              = !@ttl.nil?

  @status_map = Hash.new(:warn)
  @status_map.merge!(TTL_STATUS_MAP)

  logger.info("Consul Event Forwarder plugin is running...")
end
validate_options() click to toggle source
# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 42
def validate_options
  valid_array = REQUIRED_OPTIONS.map{ |o| options[o].to_s.empty? }
  !valid_array.include?(true)
end

Private Instance Methods

consul_uri(event, note_type) click to toggle source
# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 53
def consul_uri(event, note_type)
  path = get_path_for_note_type(event, note_type)
  URI.parse("#{@protocol}://#{@host}:#{@port}#{path}?#{@params}")
end
event_unregistered?(event) click to toggle source

Has this process not encountered a specific ttl check yet? We keep track so we aren't sending superfluous registrations Only register ttl for events that have a job assigned

# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 161
def event_unregistered?(event)
  @use_ttl && event.respond_to?(:job) && !@checklist.include?(label_for_ttl(event))
end
forward_event(event) click to toggle source

heartbeats get forwarded as ttl checks and alerts get forwarded as events if heartbeat_as_alert is true than a heartbeat gets forwarded as events as well

# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 60
def forward_event(event)

  if forward_this_event?(event)
    notify_consul(event, :event)
  end

  if forward_this_ttl?(event)
    event_unregistered?(event) ? notify_consul(event, :register, registration_payload(event)) : notify_consul(event, :ttl)
  end

end
forward_this_event?(event) click to toggle source

should an individual alert or heartbeat be forwarded as a consul event

# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 73
def forward_this_event?(event)
  @use_events && (event.is_a?(Bosh::Monitor::Events::Alert) || ( event.is_a?(Bosh::Monitor::Events::Heartbeat) && @heartbeats_as_alerts && event.node_id))
end
forward_this_ttl?(event) click to toggle source
# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 77
def forward_this_ttl?(event)
  @use_ttl && event.is_a?(Bosh::Monitor::Events::Heartbeat) && event.node_id
end
get_path_for_note_type(event, note_type) click to toggle source
# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 81
def get_path_for_note_type(event, note_type)
  case note_type
  when :event
    CONSUL_ENDPOINTS[:event] + label_for_event(event)
  when :ttl
    job_state = event.attributes['job_state']
    status_id = @status_map[job_state]
    CONSUL_ENDPOINTS[status_id] + label_for_ttl(event)
  when :register
    CONSUL_ENDPOINTS[:register]
  end
end
label_for_event(event) click to toggle source
# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 94
def label_for_event(event)
  case event
    when Bosh::Monitor::Events::Heartbeat
      label_for_ttl(event)
    when Bosh::Monitor::Events::Alert
      event_label = event.title.downcase.gsub(" ","_")
      "#{@namespace}#{event_label}"
    else
      #Something we haven't encountered yet
      "#{@namespace}event"
  end
end
label_for_ttl(event) click to toggle source
# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 107
def label_for_ttl(event)
  "#{@namespace}#{event.job}_#{event.node_id}"
end
notify_consul(event, note_type, message=nil) click to toggle source

Notify consul of an event note_type: the type of notice we are sending (:event, :ttl, :register) message: an optional body for the message, event.json is used by default

# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 114
def notify_consul(event, note_type, message=nil)
  body    = message.nil? ? right_sized_body_for_consul(event).to_json : message.to_json
  uri     = consul_uri(event, note_type)

  request = { :body => body }

  send_http_put_request(uri , request)

  #if a registration request returns without error we log it
  #we don't want to send extra registrations
  @checklist << label_for_event(event) if note_type == :register
rescue => e
  logger.error("Could not forward event to Consul Cluster @#{@host}: #{e.inspect}")
end
registration_payload(event) click to toggle source
# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 165
def registration_payload(event)
  { "name"  => label_for_ttl(event), "notes" => @ttl_note, "ttl" => @ttl }
end
right_sized_body_for_consul(event) click to toggle source

consul limits event payload to < 512 bytes, unfortunately we have to do some pruning so this limit is not as likely to be reached this is suboptimal but otherwise the event post will fail, and how do we decide what data isn't important?

# File lib/bosh/monitor/plugins/consul_event_forwarder.rb, line 131
def right_sized_body_for_consul(event)
  body = event.to_hash
  if event.is_a?(Bosh::Monitor::Events::Heartbeat)
    vitals = body[:vitals]
    #currently assuming the event hash details are always put together in the same order
    #this should yield consistent results from the values method
    {
      :agent  => body[:agent_id],
      :name   => "#{body[:job]}/#{body[:node_id]}",
      :id     => body[:node_id],
      :state  => "#{body[:job_state]}",
      :data   => {
          :cpu => vitals['cpu'].values,
          :dsk => {
            :eph => vitals['disk']['ephemeral'].values,
            :sys => vitals['disk']['system'].values,
          },
          :ld  => vitals['load'],
          :mem => vitals['mem'].values,
          :swp => vitals['swap'].values
      }
    }
  else
    body
  end
end