class Fluent::Plugin::WindowsEventLogInput

Constants

DEFAULT_STORAGE_TYPE
FIELD_DELIMITER
GROUP_DELIMITER
KEY_MAP
NONE_FIELD_DELIMITER
RECORD_DELIMITER

Attributes

chs[R]

Public Class Methods

new() click to toggle source
Calls superclass method
# File lib/fluent/plugin/in_windows_eventlog.rb, line 44
def initialize
  super
  @chs = []
  @keynames = []
  @tails = {}
end

Public Instance Methods

configure(conf) click to toggle source
Calls superclass method
# File lib/fluent/plugin/in_windows_eventlog.rb, line 51
def configure(conf)
  log.warn "in_windows_eventlog is deprecated. It will be removed in the future version."
  super
  @chs = @channels.map {|ch| ch.strip.downcase }.uniq
  if @chs.empty?
    raise Fluent::ConfigError, "windows_eventlog: 'channels' parameter is required on windows_eventlog input"
  end
  @keynames = @keys.map {|k| k.strip }.uniq
  if @keynames.empty?
    @keynames = KEY_MAP.keys
  end
  @keynames.delete('string_inserts') if @parse_description

  @tag = tag
  @stop = false
  configure_encoding
  @receive_handlers = if @encoding
                        method(:encode_record)
                      else
                        method(:no_encode_record)
                      end
  @pos_storage = storage_create(usage: "positions")
end
configure_encoding() click to toggle source
# File lib/fluent/plugin/in_windows_eventlog.rb, line 75
def configure_encoding
  unless @encoding
    if @from_encoding
      raise Fluent::ConfigError, "windows_eventlog: 'from_encoding' parameter must be specied with 'encoding' parameter."
    end
  end

  @encoding = parse_encoding_param(@encoding) if @encoding
  @from_encoding = parse_encoding_param(@from_encoding) if @from_encoding
end
encode_record(record) click to toggle source
# File lib/fluent/plugin/in_windows_eventlog.rb, line 94
def encode_record(record)
  if @encoding
    if @from_encoding
      record.encode!(@encoding, @from_encoding)
    else
      record.force_encoding(@encoding)
    end
  end
end
escape_channel(ch) click to toggle source
# File lib/fluent/plugin/in_windows_eventlog.rb, line 123
def escape_channel(ch)
  ch.gsub(/[^a-zA-Z0-9]/, '_')
end
no_encode_record(record) click to toggle source
# File lib/fluent/plugin/in_windows_eventlog.rb, line 104
def no_encode_record(record)
  record
end
on_notify(ch) click to toggle source
# File lib/fluent/plugin/in_windows_eventlog.rb, line 154
def on_notify(ch)
  begin
    el = Win32::EventLog.open(ch)
  rescue => e
    log.error "Failed to open Windows Event log.", error: e
  end

  current_oldest_record_number = el.oldest_record_number
  current_total_records = el.total_records

  read_start, read_num = @pos_storage.get(ch)

  # if total_records is zero, oldest_record_number has no meaning.
  if current_total_records == 0
    return
  end

  if read_start == 0 && read_num == 0
    @pos_storage.put(ch, [current_oldest_record_number, current_total_records])
    return
  end

  current_end = current_oldest_record_number + current_total_records - 1
  old_end = read_start + read_num - 1

  if current_oldest_record_number < read_start
    # may be a record number rotated.
    current_end += 0xFFFFFFFF
  end

  if current_end < old_end
    # something occured.
    @pos_storage.put(ch, [current_oldest_record_number, current_total_records])
    return
  end

  winlogs = el.read(Win32::EventLog::SEEK_READ | Win32::EventLog::FORWARDS_READ, old_end + 1)
  receive_lines(ch, winlogs)
  @pos_storage.put(ch, [read_start, read_num + winlogs.size])
ensure
  if el
    el.close
  end
end
parse_desc(record) click to toggle source
# File lib/fluent/plugin/in_windows_eventlog.rb, line 204
def parse_desc(record)
  desc = record.delete('description'.freeze)
  return if desc.nil?

  elems = desc.split(GROUP_DELIMITER)
  record['description_title'] = elems.shift
  elems.each { |elem|
    parent_key = nil
    elem.split(RECORD_DELIMITER).each { |r|
      key, value = if r.index(FIELD_DELIMITER)
                     r.split(FIELD_DELIMITER)
                   else
                     r.split(NONE_FIELD_DELIMITER)
                   end
      key.chop!  # remove ':' from key
      if value.nil?
        parent_key = to_key(key)
      else
        # parsed value sometimes contain unexpected "\t". So remove it.
        value.strip!
        if parent_key.nil?
          record[to_key(key)] = value
        else
          k = "#{parent_key}.#{to_key(key)}"
          record[k] = value
        end
      end
    }
  }
end
parse_encoding_param(encoding_name) click to toggle source
# File lib/fluent/plugin/in_windows_eventlog.rb, line 86
def parse_encoding_param(encoding_name)
  begin
    Encoding.find(encoding_name) if encoding_name
  rescue ArgumentError => e
    raise Fluent::ConfigError, e.message
  end
end
receive_lines(ch, lines) click to toggle source
# File lib/fluent/plugin/in_windows_eventlog.rb, line 127
def receive_lines(ch, lines)
  return if lines.empty?
  begin
    for r in lines
      h = {"channel" => ch}
      @keynames.each do |k|
        type = KEY_MAP[k][1]
        value = r.send(KEY_MAP[k][0])
        h[k]=case type
             when :string
               @receive_handlers.call(value.to_s)
             when :array
               value.map {|v| @receive_handlers.call(v.to_s)}
             else
               raise "Unknown value type: #{type}"
             end
      end
      parse_desc(h) if @parse_description
      #h = Hash[@keynames.map {|k| [k, r.send(KEY_MAP[k][0]).to_s]}]
      router.emit(@tag, Fluent::Engine.now, h)
    end
  rescue => e
    log.error "unexpected error", error: e
    log.error_backtrace
  end
end
start() click to toggle source
Calls superclass method
# File lib/fluent/plugin/in_windows_eventlog.rb, line 108
def start
  super
  @chs.each do |ch|
    start, num = @pos_storage.get(ch)
    if @read_from_head || (!num || num.zero?)
      el = Win32::EventLog.open(ch)
      @pos_storage.put(ch, [el.oldest_record_number - 1, 1])
      el.close
    end
    timer_execute("in_windows_eventlog_#{escape_channel(ch)}".to_sym, @read_interval) do
      on_notify(ch)
    end
  end
end
to_key(key) click to toggle source
# File lib/fluent/plugin/in_windows_eventlog.rb, line 235
def to_key(key)
  key.downcase!
  key.gsub!(' '.freeze, '_'.freeze)
  key
end