Class: LogStash::Outputs::Gelf

Inherits:
Base
  • Object
show all
Defined in:
lib/logstash/outputs/gelf.rb

Overview

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]

Instance Method Summary collapse

Instance Method Details

#gelfObject



77
78
79
# File 'lib/logstash/outputs/gelf.rb', line 77

def gelf
  @gelf
end

#inject_client(gelf) ⇒ Object



72
73
74
75
# File 'lib/logstash/outputs/gelf.rb', line 72

def inject_client(gelf)
  @gelf = gelf
  self
end

#receive(event) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# 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

#registerObject



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# 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