fluent-plugin-windows-eventlog 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.