Class: Fluent::Plugin::WindowsEventLog2Input

Inherits:
Input
  • Object
show all
Defined in:
lib/fluent/plugin/in_windows_eventlog2.rb

Constant Summary collapse

DEFAULT_STORAGE_TYPE =
'local'
KEY_MAP =
{"ProviderName"      => ["ProviderName",          :string],
"ProviderGUID"      => ["ProviderGUID",          :string],
"EventID"           => ["EventID",               :string],
"Qualifiers"        => ["Qualifiers",            :string],
"Level"             => ["Level",                 :string],
"Task"              => ["Task",                  :string],
"Opcode"            => ["Opcode",                :string],
"Keywords"          => ["Keywords",              :string],
"TimeCreated"       => ["TimeCreated",           :string],
"EventRecordID"     => ["EventRecordID",         :string],
"ActivityID"        => ["ActivityID",            :string],
"RelatedActivityID" => ["RelatedActivityID",     :string],
"ThreadID"          => ["ThreadID",              :string],
"Channel"           => ["Channel",               :string],
"Computer"          => ["Computer",              :string],
"UserID"            => ["UserID",                :string],
"Version"           => ["Version",               :string],
"Description"       => ["Description",           :string],
"EventData"         => ["EventData",             :array]}
GROUP_DELIMITER =
"\r\n\r\n".freeze
RECORD_DELIMITER =
"\r\n\t".freeze
FIELD_DELIMITER =
"\t\t".freeze
NONE_FIELD_DELIMITER =
"\t".freeze

Instance Method Summary collapse

Instance Method Details

#configure(conf) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/fluent/plugin/in_windows_eventlog2.rb', line 56

def configure(conf)
  super
  @chs = @channels.map {|ch| ch.strip.downcase }.uniq
  @keynames = @keys.map {|k| k.strip }.uniq
  if @keynames.empty?
    @keynames = KEY_MAP.keys
  end
  @keynames.delete('EventData') if @parse_description

  @tag = tag
  @tailing = @read_from_head ? false : true
  @bookmarks_storage = storage_create(usage: "bookmarks")
  @parser = parser_create
end

#escape_channel(ch) ⇒ Object



86
87
88
# File 'lib/fluent/plugin/in_windows_eventlog2.rb', line 86

def escape_channel(ch)
  ch.gsub(/[^a-zA-Z0-9]/, '_')
end

#initalizeObject



50
51
52
53
54
# File 'lib/fluent/plugin/in_windows_eventlog2.rb', line 50

def initalize
  super
  @chs = []
  @keynames = []
end

#on_notify(ch, subscribe) ⇒ Object



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
121
122
# File 'lib/fluent/plugin/in_windows_eventlog2.rb', line 90

def on_notify(ch, subscribe)
  es = Fluent::MultiEventStream.new
  subscribe.each do |xml, message, string_inserts|
    @parser.parse(xml) do |time, record|
      # record.has_key?("EventData") for none parser checking.

      if record.has_key?("EventData")
        record["Description"] = message
        record["EventData"] = string_inserts

        h = {}
        @keynames.each do |k|
          type = KEY_MAP[k][1]
          value = record[KEY_MAP[k][0]]
          h[k]=case type
               when :string
                 value.to_s
               when :array
                 value.map {|v| v.to_s}
               else
                 raise "Unknown value type: #{type}"
               end
        end
        parse_desc(h) if @parse_description
        es.add(Fluent::Engine.now, h)
      else
        # for none parser

        es.add(Fluent::Engine.now, record)
      end
    end
  end
  router.emit_stream(@tag, es)
  @bookmarks_storage.put(ch, subscribe.bookmark)
end

#parse_desc(record) ⇒ Object



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
# File 'lib/fluent/plugin/in_windows_eventlog2.rb', line 131

def parse_desc(record)
  desc = record.delete("Description".freeze)
  return if desc.nil?

  elems = desc.split(GROUP_DELIMITER)
  record['DescriptionTitle'] = 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

#startObject



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/fluent/plugin/in_windows_eventlog2.rb', line 71

def start
  super

  @chs.each do |ch|
    bookmarkXml = @bookmarks_storage.get(ch) || ""
    subscribe = Winevt::EventLog::Subscribe.new
    bookmark = Winevt::EventLog::Bookmark.new(bookmarkXml)
    subscribe.tail = @tailing
    subscribe.subscribe(ch, "*", bookmark)
    timer_execute("in_windows_eventlog_#{escape_channel(ch)}".to_sym, @read_interval) do
      on_notify(ch, subscribe)
    end
  end
end

#to_key(key) ⇒ Object



162
163
164
165
166
# File 'lib/fluent/plugin/in_windows_eventlog2.rb', line 162

def to_key(key)
  key.downcase!
  key.gsub!(' '.freeze, '_'.freeze)
  key
end