class LogStash::Outputs::Gelf

This output generates messages in GELF format. This is most useful if you want to use Logstash to output events to Graylog2.

More information at graylog2.org/gelf#specs[The Graylog2 GELF specs page]

Public Instance Methods

gelf() click to toggle source
# File lib/logstash/outputs/gelf.rb, line 77
def gelf
  @gelf
end
inject_client(gelf) click to toggle source
# File lib/logstash/outputs/gelf.rb, line 72
def inject_client(gelf)
  @gelf = gelf
  self
end
receive(event) click to toggle source
# File lib/logstash/outputs/gelf.rb, line 123
def receive(event)
  

  # We have to make our own hash here because GELF expects a hash
  # with a specific format.
  m = Hash.new

  m["short_message"] = event.get("message")
  if event.get(@short_message)
    v = event.get(@short_message)
    short_message = (v.is_a?(Array) && v.length == 1) ? v.first : v
    short_message = short_message.to_s
    if !short_message.empty?
      m["short_message"] = short_message
    end
  end

  m["full_message"] = event.sprintf(@full_message)

  m["host"] = event.sprintf(@sender)

  if @ship_metadata
    event.to_hash.each do |name, value|
      next if value == nil
      next if name == "message"

      # Trim leading '_' in the event
      name = name[1..-1] if name.start_with?('_')
      name = "_id" if name == "id"  # "_id" is reserved, so use "__id"
      if !value.nil? and !@ignore_metadata.include?(name)
        if value.is_a?(Array)
          m["_#{name}"] = value.join(', ')
        elsif value.is_a?(Hash)
          value.each do |hash_name, hash_value|
            m["_#{name}_#{hash_name}"] = hash_value
          end
        else
          # Non array values should be presented as-is
          # https://logstash.jira.com/browse/LOGSTASH-113
          m["_#{name}"] = value
        end
      end
    end
  end

  if @ship_tags
    m["_tags"] = event.get("tags").join(', ') if event.get("tags")
  end

  if @custom_fields
    @custom_fields.each do |field_name, field_value|
      m["_#{field_name}"] = field_value unless field_name == 'id'
    end
  end

  # Probe severity array levels
  level = nil
  if @level.is_a?(Array)
    @level.each do |value|
      parsed_value = event.sprintf(value)
      next if value.count('%{') > 0 and parsed_value == value

      level = parsed_value
      break
    end
  else
    level = event.sprintf(@level.to_s)
  end
  m["level"] = (level.respond_to?(:downcase) && @level_map[level.downcase] || level).to_i

  @logger.debug("Sending GELF event", :event => m)
  begin
    @gelf.notify!(m, :timestamp => event.timestamp.to_f)
  rescue
    @logger.warn("Trouble sending GELF event", :gelf_event => m,
                 :event => event, :error => $!)
  end
end
register() click to toggle source
# File lib/logstash/outputs/gelf.rb, line 81
def register
  require "gelf" # rubygem 'gelf'
  option_hash = Hash.new

  #@gelf = GELF::Notifier.new(@host, @port, @chunksize, option_hash)
  @gelf ||= GELF::Notifier.new(@host, @port, @chunksize, { :protocol => GELF::Protocol.const_get(@protocol) })

  # This sets the 'log level' of gelf; since we're forwarding messages, we'll
  # want to forward *all* messages, so set level to 0 so all messages get
  # shipped
  @gelf.level = 0

  # Since we use gelf-rb which assumes the severity level integer
  # is coming from a ruby logging subsystem, we need to instruct it
  # that the levels we provide should be mapped directly since they're
  # already RFC 5424 compliant
  # this requires gelf-rb commit bb1f4a9 which added the level_mapping def
  level_mapping = Hash.new
  (0..7).step(1) { |l| level_mapping[l]=l }
  @gelf.level_mapping = level_mapping

  # If we leave that set, the gelf gem will extract the file and line number
  # of the source file that logged the message (i.e. logstash/gelf.rb:138).
  # With that set to false, it can use the actual event's filename (i.e.
  # /var/log/syslog), which is much more useful
  @gelf.collect_file_and_line = false

  # these are syslog words and abbreviations mapped to RFC 5424 integers
  # and logstash's syslog_pri filter
  @level_map = {
    "debug" => 7, "d" => 7,
    "info" => 6, "i" => 6, "informational" => 6,
    "notice" => 5, "n" => 5,
    "warn" => 4, "w" => 4, "warning" => 4,
    "error" => 3, "e" => 3,
    "critical" => 2, "c" => 2,
    "alert" => 1, "a" => 1,
    "emergency" => 0, "e" => 0,
   }
end