fluent-plugin-windows-eventlog 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 182e98e93e8d43f333025671ae6698ccddefd580
4
- data.tar.gz: fdeda6fa7866b56938cfa714a0025aae635453ef
3
+ metadata.gz: e4ec43a83a8b3f54edc73e2f26ee4ec43005ba73
4
+ data.tar.gz: 1f225569741fe7768cf373c8d287f9ff1c11cdab
5
5
  SHA512:
6
- metadata.gz: 7e46f28f6814ed735edb7db078a5784614f4e620457f1082737496b6ae80188168ed8dd5f3a5233e0ec66a261fb26a5519fc172f6821ab170c11d45ebd9568c1
7
- data.tar.gz: dcb0c4be720f231921fb7dfa5430563c96cf31b392661086e2e328e2c3d4e42412328258cceb3b062b5ab4db7563a159874c4b9d75f5b159cbd474e7b8b6a627
6
+ metadata.gz: 343bbf9e3c173ca9707821599602fa767e3d693756c823bcafb5eeea2f87d073eefc3bae34eafaa55a15745f6875cd7c670fcd0c6ac6b096d82a9f842adec025
7
+ data.tar.gz: 1c30bc7385783027f6d2e3c509e3b811aede90c42cd27bc9da9b786f4de960262892a8a56c3d3b59cd42cc707af303fd499a59f7283ad41de960415a8aa41564
data/README.md CHANGED
@@ -14,11 +14,18 @@ You must use fluentd 'Windows' brach to use me, and it doesn't work on Linux of
14
14
  #### fluentd Input plugin for Windows Event Log
15
15
 
16
16
  <source>
17
- type windows_eventlog
17
+ @type windows_eventlog
18
18
  channels application,system
19
19
  pos_file c:\temp\mypos
20
20
  read_interval 2
21
21
  tag winevt.raw
22
+ @id windows_eventlog
23
+ <storage>
24
+ @type local # @type local is default.
25
+ persistent true # persistent true is default.
26
+ path ./tmp/storage.json # This is required when persistent is true.
27
+ # Or, please consider to use <system> section's root_dir parameter.
28
+ </storage>
22
29
  </source>
23
30
 
24
31
 
@@ -4,9 +4,9 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "fluent-plugin-windows-eventlog"
7
- spec.version = "0.1.0"
7
+ spec.version = "0.2.0"
8
8
  spec.authors = ["okahashi117", "Hiroshi Hatake", "Masahiro Nakagawa"]
9
- spec.email = ["naruki_okahashi@jbat.co.jp", "cosmo0920.wp@gmail.com", "repeatedly@gmail.com"]
9
+ spec.email = ["naruki_okahashi@jbat.co.jp", "cosmo0920.oucc@gmail.com", "repeatedly@gmail.com"]
10
10
  spec.summary = %q{Fluentd Input plugin to read windows event log.}
11
11
  spec.description = %q{Fluentd Input plugin to read windwos event log.}
12
12
  spec.homepage = "https://github.com/fluent/fluent-plugin-windows-eventlog"
@@ -20,6 +20,6 @@ Gem::Specification.new do |spec|
20
20
  spec.add_development_dependency "bundler"
21
21
  spec.add_development_dependency "rake"
22
22
  spec.add_development_dependency "test-unit", "~> 3.2.0"
23
- spec.add_runtime_dependency "fluentd", [">= 0.14.11", "< 2"]
23
+ spec.add_runtime_dependency "fluentd", [">= 0.14.12", "< 2"]
24
24
  spec.add_runtime_dependency "win32-eventlog"
25
25
  end
@@ -6,8 +6,9 @@ module Fluent::Plugin
6
6
  class WindowsEventLogInput < Input
7
7
  Fluent::Plugin.register_input('windows_eventlog', self)
8
8
 
9
- helpers :timer
9
+ helpers :timer, :storage
10
10
 
11
+ DEFAULT_STORAGE_TYPE = 'local'
11
12
  KEY_MAP = {"record_number" => :record_number,
12
13
  "time_generated" => :time_generated,
13
14
  "time_written" => :time_written,
@@ -21,13 +22,20 @@ module Fluent::Plugin
21
22
 
22
23
  config_param :tag, :string
23
24
  config_param :read_interval, :time, default: 2
24
- config_param :pos_file, :string, default: nil
25
+ config_param :pos_file, :string, default: nil,
26
+ obsoleted: "This section is not used anymore. Use 'store_pos' instead."
25
27
  config_param :channels, :array, default: ['Application']
26
28
  config_param :keys, :string, default: []
27
29
  config_param :read_from_head, :bool, default: false
28
30
  config_param :from_encoding, :string, default: nil
29
31
  config_param :encoding, :string, default: nil
30
32
 
33
+ config_section :storage do
34
+ config_set_default :usage, "positions"
35
+ config_set_default :@type, DEFAULT_STORAGE_TYPE
36
+ config_set_default :persistent, true
37
+ end
38
+
31
39
  attr_reader :chs
32
40
 
33
41
  def initialize
@@ -55,6 +63,7 @@ module Fluent::Plugin
55
63
  else
56
64
  method(:no_encode_record)
57
65
  end
66
+ @pos_storage = storage_create(usage: "positions")
58
67
  end
59
68
 
60
69
  def configure_encoding
@@ -92,59 +101,24 @@ module Fluent::Plugin
92
101
 
93
102
  def start
94
103
  super
95
- if @pos_file
96
- @pf_file = File.open(@pos_file, File::RDWR|File::CREAT|File::BINARY)
97
- @pf_file.sync = true
98
- @pf = PositionFile.parse(@pf_file)
99
- end
100
- start_watchers(@chs)
101
- end
102
-
103
- def shutdown
104
- stop_watchers(@tails.keys, true)
105
- @pf_file.close if @pf_file
106
- super
107
- end
108
-
109
- def setup_wacther(ch, pe)
110
- wlw = WindowsLogWatcher.new(ch, pe, &method(:receive_lines))
111
- wlw.attach do |watcher|
112
- wlw.timer_trigger = timer_execute(:in_winevtlog, @read_interval, &watcher.method(:on_notify))
113
- end
114
- wlw
115
- end
116
-
117
- def start_watchers(chs)
118
- chs.each { |ch|
119
- pe = nil
120
- if @pf
121
- pe = @pf[ch]
122
- if @read_from_head && pe.read_num.zero?
123
- el = Win32::EventLog.open(ch)
124
- pe.update(el.oldest_record_number-1,1)
125
- el.close
126
- end
104
+ @chs.each do |ch|
105
+ start, num = @pos_storage.get(ch)
106
+ if @read_from_head || (!num || num.zero?)
107
+ el = Win32::EventLog.open(ch)
108
+ @pos_storage.put(ch, [el.oldest_record_number - 1, 1])
109
+ el.close
127
110
  end
128
- @tails[ch] = setup_wacther(ch, pe)
129
- }
130
- end
131
-
132
- def stop_watchers(chs, unwatched = false)
133
- chs.each { |ch|
134
- wlw = @tails.delete(ch)
135
- if wlw
136
- wlw.unwatched = unwatched
137
- close_watcher(wlw)
111
+ timer_execute("in_windows_eventlog_#{escape_channel(ch)}".to_sym, @read_interval) do
112
+ on_notify(ch)
138
113
  end
139
- }
114
+ end
140
115
  end
141
116
 
142
- def close_watcher(wlw)
143
- wlw.close
144
- # flush_buffer(wlw)
117
+ def escape_channel(ch)
118
+ ch.gsub(/[^a-zA-Z0-9]/, '_')
145
119
  end
146
120
 
147
- def receive_lines(ch, lines, pe)
121
+ def receive_lines(ch, lines)
148
122
  return if lines.empty?
149
123
  begin
150
124
  for r in lines
@@ -152,169 +126,50 @@ module Fluent::Plugin
152
126
  @keynames.each {|k| h[k]=@receive_handlers.call(r.send(KEY_MAP[k]).to_s)}
153
127
  #h = Hash[@keynames.map {|k| [k, r.send(KEY_MAP[k]).to_s]}]
154
128
  router.emit(@tag, Fluent::Engine.now, h)
155
- pe[1] +=1
156
- end
157
- rescue
158
- $log.error "unexpected error", error: $!.to_s
159
- $log.error_backtrace
160
- end
161
- end
162
-
163
-
164
- class WindowsLogWatcher
165
- def initialize(ch, pe, &receive_lines)
166
- @ch = ch
167
- @pe = pe || MemoryPositionEntry.new
168
- @receive_lines = receive_lines
169
- @timer_trigger = nil
170
- end
171
-
172
- attr_reader :ch
173
- attr_accessor :unwatched
174
- attr_accessor :pe
175
- attr_accessor :timer_trigger
176
-
177
- def attach
178
- yield self
179
- on_notify
180
- end
181
-
182
- def detach
183
- @timer_trigger.detach if @timer_trigger.attached?
184
- end
185
-
186
- def close
187
- detach
188
- end
189
-
190
- def on_notify
191
- el = Win32::EventLog.open(@ch)
192
- rl_sn = [el.oldest_record_number, el.total_records]
193
- pe_sn = [@pe.read_start, @pe.read_num]
194
- # if total_records is zero, oldest_record_number has no meaning.
195
- if rl_sn[1] == 0
196
- return
197
- end
198
-
199
- if pe_sn[0] == 0 && pe_sn[1] == 0
200
- @pe.update(rl_sn[0], rl_sn[1])
201
- return
202
- end
203
-
204
- cur_end = rl_sn[0] + rl_sn[1] -1
205
- old_end = pe_sn[0] + pe_sn[1] -1
206
-
207
- if (rl_sn[0] < pe_sn[0])
208
- # may be a record number rotated.
209
- cur_end += 0xFFFFFFFF
210
- end
211
-
212
- if (cur_end < old_end)
213
- # something occured.
214
- @pe.update(rl_sn[0], rl_sn[1])
215
- return
216
- end
217
-
218
- read_more = false
219
- begin
220
- numlines = cur_end - old_end
221
-
222
- winlogs = el.read(Win32::EventLog::SEEK_READ | Win32::EventLog::FORWARDS_READ, old_end + 1)
223
- @receive_lines.call(@ch, winlogs, pe_sn)
224
-
225
- @pe.update(pe_sn[0], pe_sn[1])
226
- old_end = pe_sn[0] + pe_sn[1] -1
227
- end while read_more
228
- el.close
229
- end
230
- end
231
-
232
- class PositionFile
233
- def initialize(file, map, last_pos)
234
- @file = file
235
- @map = map
236
- @last_pos = last_pos
237
- end
238
-
239
- def [](ch)
240
- if m = @map[ch]
241
- return m
242
129
  end
243
- @file.pos = @last_pos
244
- @file.write ch
245
- @file.write "\t"
246
- seek = @file.pos
247
- @file.write "00000000\t00000000\n"
248
- @last_pos = @file.pos
249
- @map[ch] = FilePositionEntry.new(@file, seek)
250
- end
251
-
252
- # parsing file and rebuild mysself
253
- def self.parse(file)
254
- map = {}
255
- file.pos = 0
256
- file.each_line {|line|
257
- # check and get a matched line as m
258
- m = /^([^\t]+)\t([0-9a-fA-F]+)\t([0-9a-fA-F]+)/.match(line)
259
- next unless m
260
- ch = m[1]
261
- pos = m[2].to_i(16)
262
- seek = file.pos - line.bytesize + ch.bytesize + 1
263
- map[ch] = FilePositionEntry.new(file, seek)
264
- }
265
- new(file, map, file.pos)
130
+ rescue => e
131
+ log.error "unexpected error", error: e
132
+ log.error_backtrace
266
133
  end
267
134
  end
268
135
 
269
- class FilePositionEntry
270
- START_SIZE = 8
271
- NUM_OFFSET = 9
272
- NUM_SIZE = 8
273
- LN_OFFSET = 17
274
- SIZE = 18
136
+ def on_notify(ch)
137
+ el = Win32::EventLog.open(ch)
275
138
 
276
- def initialize(file, seek)
277
- @file = file
278
- @seek = seek
279
- end
139
+ current_oldest_record_number = el.oldest_record_number
140
+ current_total_records = el.total_records
280
141
 
281
- def update(start, num)
282
- @file.pos = @seek
283
- @file.write "%08x\t%08x" % [start, num]
284
- end
142
+ read_start, read_num = @pos_storage.get(ch)
285
143
 
286
- def read_start
287
- @file.pos = @seek
288
- raw = @file.read(START_SIZE)
289
- raw ? raw.to_i(16) : 0
144
+ # if total_records is zero, oldest_record_number has no meaning.
145
+ if current_total_records == 0
146
+ return
290
147
  end
291
148
 
292
- def read_num
293
- @file.pos = @seek + NUM_OFFSET
294
- raw = @file.read(NUM_SIZE)
295
- raw ? raw.to_i(16) : 0
149
+ if read_start == 0 && read_num == 0
150
+ @pos_storage.put(ch, [current_oldest_record_number, current_total_records])
151
+ return
296
152
  end
297
- end
298
153
 
299
- class MemoryPositionEntry
300
- def initialize
301
- @start = 0
302
- @num = 0
303
- end
154
+ current_end = current_oldest_record_number + current_total_records - 1
155
+ old_end = read_start + read_num - 1
304
156
 
305
- def update(start, num)
306
- @start = start
307
- @num = num
157
+ if current_oldest_record_number < read_start
158
+ # may be a record number rotated.
159
+ current_end += 0xFFFFFFFF
308
160
  end
309
161
 
310
- def read_start
311
- @start
162
+ if current_end < old_end
163
+ # something occured.
164
+ @pos_storage.put(ch, [current_oldest_record_number, current_total_records])
165
+ return
312
166
  end
313
167
 
314
- def read_num
315
- @num
316
- end
168
+ winlogs = el.read(Win32::EventLog::SEEK_READ | Win32::EventLog::FORWARDS_READ, old_end + 1)
169
+ receive_lines(ch, winlogs)
170
+ @pos_storage.put(ch, [read_start, read_num + winlogs.size])
171
+ ensure
172
+ el.close
317
173
  end
318
-
319
174
  end
320
175
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-windows-eventlog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - okahashi117
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-01-23 00:00:00.000000000 Z
13
+ date: 2017-03-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -60,7 +60,7 @@ dependencies:
60
60
  requirements:
61
61
  - - ">="
62
62
  - !ruby/object:Gem::Version
63
- version: 0.14.11
63
+ version: 0.14.12
64
64
  - - "<"
65
65
  - !ruby/object:Gem::Version
66
66
  version: '2'
@@ -70,7 +70,7 @@ dependencies:
70
70
  requirements:
71
71
  - - ">="
72
72
  - !ruby/object:Gem::Version
73
- version: 0.14.11
73
+ version: 0.14.12
74
74
  - - "<"
75
75
  - !ruby/object:Gem::Version
76
76
  version: '2'
@@ -91,7 +91,7 @@ dependencies:
91
91
  description: Fluentd Input plugin to read windwos event log.
92
92
  email:
93
93
  - naruki_okahashi@jbat.co.jp
94
- - cosmo0920.wp@gmail.com
94
+ - cosmo0920.oucc@gmail.com
95
95
  - repeatedly@gmail.com
96
96
  executables: []
97
97
  extensions: []
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  version: '0'
127
127
  requirements: []
128
128
  rubyforge_project:
129
- rubygems_version: 2.6.8
129
+ rubygems_version: 2.5.2
130
130
  signing_key:
131
131
  specification_version: 4
132
132
  summary: Fluentd Input plugin to read windows event log.