logstash-input-file 4.1.18 → 4.2.4
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 +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +1 -1
- data/lib/filewatch/discoverer.rb +9 -8
- data/lib/filewatch/observing_base.rb +1 -12
- data/lib/filewatch/processor.rb +55 -0
- data/lib/filewatch/read_mode/handlers/base.rb +12 -11
- data/lib/filewatch/read_mode/handlers/read_file.rb +23 -8
- data/lib/filewatch/read_mode/handlers/read_zip_file.rb +8 -6
- data/lib/filewatch/read_mode/processor.rb +22 -36
- data/lib/filewatch/settings.rb +1 -2
- data/lib/filewatch/sincedb_collection.rb +40 -41
- data/lib/filewatch/sincedb_record_serializer.rb +5 -11
- data/lib/filewatch/stat/generic.rb +8 -13
- data/lib/filewatch/stat/windows_path.rb +7 -9
- data/lib/filewatch/tail_mode/handlers/base.rb +32 -23
- data/lib/filewatch/tail_mode/handlers/delete.rb +2 -4
- data/lib/filewatch/tail_mode/handlers/shrink.rb +2 -3
- data/lib/filewatch/tail_mode/handlers/unignore.rb +4 -4
- data/lib/filewatch/tail_mode/processor.rb +47 -54
- data/lib/filewatch/watch.rb +12 -14
- data/lib/filewatch/watched_file.rb +25 -14
- data/lib/filewatch/watched_files_collection.rb +11 -78
- data/lib/jars/filewatch-1.0.1.jar +0 -0
- data/lib/logstash/inputs/file.rb +4 -3
- data/lib/logstash/inputs/file_listener.rb +3 -14
- data/logstash-input-file.gemspec +2 -1
- data/spec/filewatch/reading_spec.rb +63 -12
- data/spec/filewatch/rotate_spec.rb +4 -4
- data/spec/filewatch/settings_spec.rb +3 -0
- data/spec/filewatch/sincedb_record_serializer_spec.rb +6 -2
- data/spec/filewatch/spec_helper.rb +12 -14
- data/spec/filewatch/tailing_spec.rb +24 -22
- data/spec/filewatch/watched_file_spec.rb +30 -0
- data/spec/filewatch/watched_files_collection_spec.rb +62 -8
- data/spec/inputs/file_read_spec.rb +58 -14
- metadata +17 -2
@@ -35,5 +35,35 @@ module FileWatch
|
|
35
35
|
expect(watched_file.recent_states).to eq([:watched, :active, :watched, :closed, :watched, :active, :unwatched, :active])
|
36
36
|
end
|
37
37
|
end
|
38
|
+
|
39
|
+
context 'restat' do
|
40
|
+
|
41
|
+
let(:directory) { Stud::Temporary.directory }
|
42
|
+
let(:file_path) { ::File.join(directory, "restat.file.txt") }
|
43
|
+
let(:pathname) { Pathname.new(file_path) }
|
44
|
+
|
45
|
+
before { FileUtils.touch file_path, :mtime => Time.now - 300 }
|
46
|
+
|
47
|
+
it 'reports false value when no changes' do
|
48
|
+
file = WatchedFile.new(pathname, PathStatClass.new(pathname), Settings.new)
|
49
|
+
mtime = file.modified_at
|
50
|
+
expect( file.modified_at_changed? ).to be false
|
51
|
+
expect( file.restat! ).to be_falsy
|
52
|
+
expect( file.modified_at_changed? ).to be false
|
53
|
+
expect( file.modified_at ).to eql mtime
|
54
|
+
expect( file.modified_at(true) ).to eql mtime
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'reports truthy when changes detected' do
|
58
|
+
file = WatchedFile.new(pathname, PathStatClass.new(pathname), Settings.new)
|
59
|
+
mtime = file.modified_at
|
60
|
+
expect( file.modified_at_changed? ).to be false
|
61
|
+
FileUtils.touch file_path
|
62
|
+
expect( file.restat! ).to be_truthy
|
63
|
+
expect( file.modified_at_changed? ).to be true
|
64
|
+
expect( file.modified_at ).to eql mtime # until updated
|
65
|
+
expect( file.modified_at(true) ).to be > mtime
|
66
|
+
end
|
67
|
+
end
|
38
68
|
end
|
39
69
|
end
|
@@ -4,15 +4,18 @@ require_relative 'spec_helper'
|
|
4
4
|
module FileWatch
|
5
5
|
describe WatchedFilesCollection do
|
6
6
|
let(:time) { Time.now }
|
7
|
-
let(:filepath1){"/var/log/z.log"}
|
8
|
-
let(:filepath2){"/var/log/m.log"}
|
9
|
-
let(:filepath3){"/var/log/a.log"}
|
10
|
-
let(:
|
11
|
-
let(:
|
12
|
-
let(:
|
7
|
+
let(:filepath1) { "/var/log/z.log" }
|
8
|
+
let(:filepath2) { "/var/log/m.log" }
|
9
|
+
let(:filepath3) { "/var/log/a.log" }
|
10
|
+
let(:filepath4) { "/var/log/b.log" }
|
11
|
+
let(:stat1) { double("stat1", :size => 98, :modified_at => time - 30, :inode => 234567, :inode_struct => InodeStruct.new("234567", 3, 2)) }
|
12
|
+
let(:stat2) { double("stat2", :size => 99, :modified_at => time - 20, :inode => 234568, :inode_struct => InodeStruct.new("234568", 3, 2)) }
|
13
|
+
let(:stat3) { double("stat3", :size => 100, :modified_at => time, :inode => 234569, :inode_struct => InodeStruct.new("234569", 3, 2)) }
|
14
|
+
let(:stat4) { double("stat4", :size => 99, :modified_at => time, :inode => 234570, :inode_struct => InodeStruct.new("234570", 3, 2)) }
|
13
15
|
let(:wf1) { WatchedFile.new(filepath1, stat1, Settings.new) }
|
14
16
|
let(:wf2) { WatchedFile.new(filepath2, stat2, Settings.new) }
|
15
17
|
let(:wf3) { WatchedFile.new(filepath3, stat3, Settings.new) }
|
18
|
+
let(:wf4) { WatchedFile.new(filepath4, stat4, Settings.new) }
|
16
19
|
|
17
20
|
context "sort by last_modified in ascending order" do
|
18
21
|
let(:sort_by) { "last_modified" }
|
@@ -20,12 +23,29 @@ module FileWatch
|
|
20
23
|
|
21
24
|
it "sorts earliest modified first" do
|
22
25
|
collection = described_class.new(Settings.from_options(:file_sort_by => sort_by, :file_sort_direction => sort_direction))
|
26
|
+
expect(collection.empty?).to be true
|
23
27
|
collection.add(wf2)
|
28
|
+
expect(collection.empty?).to be false
|
24
29
|
expect(collection.values).to eq([wf2])
|
25
30
|
collection.add(wf3)
|
26
31
|
expect(collection.values).to eq([wf2, wf3])
|
27
32
|
collection.add(wf1)
|
28
33
|
expect(collection.values).to eq([wf1, wf2, wf3])
|
34
|
+
expect(collection.keys.size).to eq 3
|
35
|
+
end
|
36
|
+
|
37
|
+
it "sorts by path when mtime is same" do
|
38
|
+
collection = described_class.new(Settings.from_options(:file_sort_by => sort_by, :file_sort_direction => sort_direction))
|
39
|
+
expect(collection.size).to eq 0
|
40
|
+
collection.add(wf2)
|
41
|
+
collection.add(wf4)
|
42
|
+
collection.add(wf1)
|
43
|
+
expect(collection.size).to eq 3
|
44
|
+
expect(collection.values).to eq([wf1, wf2, wf4])
|
45
|
+
collection.add(wf3)
|
46
|
+
expect(collection.size).to eq 4
|
47
|
+
expect(collection.values).to eq([wf1, wf2, wf3, wf4])
|
48
|
+
expect(collection.keys.size).to eq 4
|
29
49
|
end
|
30
50
|
end
|
31
51
|
|
@@ -74,7 +94,7 @@ module FileWatch
|
|
74
94
|
end
|
75
95
|
end
|
76
96
|
|
77
|
-
context "
|
97
|
+
context "remove_paths" do
|
78
98
|
let(:sort_by) { "path" }
|
79
99
|
let(:sort_direction) { "desc" }
|
80
100
|
|
@@ -85,9 +105,43 @@ module FileWatch
|
|
85
105
|
collection.add(wf3)
|
86
106
|
expect(collection.keys).to eq([filepath1, filepath2, filepath3])
|
87
107
|
|
88
|
-
collection.remove_paths([filepath2,filepath3])
|
108
|
+
ret = collection.remove_paths([filepath2, filepath3])
|
109
|
+
expect(ret).to eq 2
|
89
110
|
expect(collection.keys).to eq([filepath1])
|
90
111
|
expect(collection.values.size).to eq 1
|
112
|
+
|
113
|
+
ret = collection.remove_paths([filepath2])
|
114
|
+
expect(ret).to eq 0
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context "update" do
|
119
|
+
let(:sort_by) { "last_modified" }
|
120
|
+
let(:sort_direction) { "asc" }
|
121
|
+
|
122
|
+
let(:re_stat1) { double("restat1", :size => 99, :modified_at => time, :inode => 234567, :inode_struct => InodeStruct.new("234567", 3, 2)) }
|
123
|
+
let(:re_stat2) { double("restat2", :size => 99, :modified_at => time, :inode => 234568, :inode_struct => InodeStruct.new("234568", 3, 2)) }
|
124
|
+
|
125
|
+
it "updates entry with changed mtime" do
|
126
|
+
collection = described_class.new(Settings.from_options(:file_sort_by => sort_by, :file_sort_direction => sort_direction))
|
127
|
+
collection.add(wf1)
|
128
|
+
collection.add(wf2)
|
129
|
+
collection.add(wf3)
|
130
|
+
expect(collection.files).to eq([wf1, wf2, wf3])
|
131
|
+
|
132
|
+
wf2.send(:set_stat, re_stat2)
|
133
|
+
expect( wf2.modified_at_changed? ).to be_truthy
|
134
|
+
|
135
|
+
collection.update wf2
|
136
|
+
expect(collection.files).to eq([wf1, wf3, wf2])
|
137
|
+
|
138
|
+
wf1.send(:set_stat, re_stat1)
|
139
|
+
expect( wf1.modified_at_changed? ).to be_truthy
|
140
|
+
collection.update wf1
|
141
|
+
expect(collection.files).to eq([wf3, wf2, wf1])
|
142
|
+
|
143
|
+
collection.add(wf4)
|
144
|
+
expect(collection.files).to eq([wf3, wf4, wf2, wf1])
|
91
145
|
end
|
92
146
|
end
|
93
147
|
|
@@ -267,7 +267,7 @@ describe LogStash::Inputs::File do
|
|
267
267
|
describe 'delete on complete' do
|
268
268
|
|
269
269
|
let(:options) do
|
270
|
-
super.merge({ 'file_completed_action' => "delete", 'exit_after_read' => false })
|
270
|
+
super().merge({ 'file_completed_action' => "delete", 'exit_after_read' => false })
|
271
271
|
end
|
272
272
|
|
273
273
|
let(:sample_file) { File.join(temp_directory, "sample.log") }
|
@@ -301,25 +301,69 @@ describe LogStash::Inputs::File do
|
|
301
301
|
watched_files = plugin.watcher.watch.watched_files_collection
|
302
302
|
expect( watched_files ).to be_empty
|
303
303
|
end
|
304
|
+
end
|
304
305
|
|
305
|
-
|
306
|
+
describe 'sincedb cleanup' do
|
306
307
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
308
|
+
let(:options) do
|
309
|
+
super().merge(
|
310
|
+
'sincedb_path' => sincedb_path,
|
311
|
+
'sincedb_clean_after' => '1.0 seconds',
|
312
|
+
'sincedb_write_interval' => 0.25,
|
313
|
+
'stat_interval' => 0.1,
|
314
|
+
)
|
315
|
+
end
|
316
|
+
|
317
|
+
let(:sincedb_path) { "#{temp_directory}/.sincedb" }
|
318
|
+
|
319
|
+
let(:sample_file) { File.join(temp_directory, "sample.txt") }
|
320
|
+
|
321
|
+
before do
|
322
|
+
plugin.register
|
323
|
+
@run_thread = Thread.new(plugin) do |plugin|
|
324
|
+
Thread.current.abort_on_exception = true
|
325
|
+
plugin.run queue
|
317
326
|
end
|
327
|
+
|
328
|
+
File.open(sample_file, 'w') { |fd| fd.write("line1\nline2\n") }
|
329
|
+
|
330
|
+
wait_for_start_processing(@run_thread)
|
318
331
|
end
|
319
332
|
|
320
|
-
|
321
|
-
|
333
|
+
after { plugin.stop }
|
334
|
+
|
335
|
+
it 'cleans up sincedb entry' do
|
336
|
+
wait_for_file_removal(sample_file) # watched discovery
|
337
|
+
|
338
|
+
sincedb_content = File.read(sincedb_path).strip
|
339
|
+
expect( sincedb_content ).to_not be_empty
|
340
|
+
|
341
|
+
Stud.try(3.times) do
|
342
|
+
sleep(1.5) # > sincedb_clean_after
|
343
|
+
|
344
|
+
sincedb_content = File.read(sincedb_path).strip
|
345
|
+
expect( sincedb_content ).to be_empty
|
346
|
+
end
|
322
347
|
end
|
323
348
|
|
324
349
|
end
|
350
|
+
|
351
|
+
private
|
352
|
+
|
353
|
+
def wait_for_start_processing(run_thread, timeout: 1.0)
|
354
|
+
begin
|
355
|
+
Timeout.timeout(timeout) do
|
356
|
+
sleep(0.01) while run_thread.status != 'sleep'
|
357
|
+
sleep(timeout) unless plugin.queue
|
358
|
+
end
|
359
|
+
rescue Timeout::Error
|
360
|
+
raise "plugin did not start processing (timeout: #{timeout})" unless plugin.queue
|
361
|
+
else
|
362
|
+
raise "plugin did not start processing" unless plugin.queue
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
def wait_for_file_removal(path, timeout: 3 * interval)
|
367
|
+
wait(timeout).for { File.exist?(path) }.to be_falsey
|
368
|
+
end
|
325
369
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-file
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,6 +58,20 @@ dependencies:
|
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '1.0'
|
67
|
+
name: concurrent-ruby
|
68
|
+
prerelease: false
|
69
|
+
type: :runtime
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '1.0'
|
61
75
|
- !ruby/object:Gem::Dependency
|
62
76
|
requirement: !ruby/object:Gem::Requirement
|
63
77
|
requirements:
|
@@ -178,6 +192,7 @@ files:
|
|
178
192
|
- lib/filewatch/observing_base.rb
|
179
193
|
- lib/filewatch/observing_read.rb
|
180
194
|
- lib/filewatch/observing_tail.rb
|
195
|
+
- lib/filewatch/processor.rb
|
181
196
|
- lib/filewatch/read_mode/handlers/base.rb
|
182
197
|
- lib/filewatch/read_mode/handlers/read_file.rb
|
183
198
|
- lib/filewatch/read_mode/handlers/read_zip_file.rb
|