Skip to content

Commit e8a1127

Browse files
authored
Merge pull request #1775 from fluent/in_tail-add-enable-stat-watcher-option
in_tail: Add enable_stat_watcher option to disable inotify events
2 parents 74e2b13 + 2e47989 commit e8a1127

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

lib/fluent/plugin/in_tail.rb

+13-6
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ def initialize
8080
config_param :emit_unmatched_lines, :bool, default: false
8181
desc 'Enable the additional watch timer.'
8282
config_param :enable_watch_timer, :bool, default: true
83+
desc 'Enable the stat watcher based on inotify.'
84+
config_param :enable_stat_watcher, :bool, default: true
8385
desc 'The encoding after conversion of the input.'
8486
config_param :encoding, :string, default: nil
8587
desc 'The encoding of the input.'
@@ -115,6 +117,10 @@ def configure(conf)
115117

116118
super
117119

120+
if !@enable_watch_timer && !@enable_stat_watcher
121+
raise Fluent::ConfigError, "either of enable_watch_timer or enable_stat_watcher must be true"
122+
end
123+
118124
@paths = @path.split(',').map {|path| path.strip }
119125
if @paths.empty?
120126
raise Fluent::ConfigError, "tail: 'path' parameter is required on tail input"
@@ -254,10 +260,10 @@ def refresh_watchers
254260

255261
def setup_watcher(path, pe)
256262
line_buffer_timer_flusher = (@multiline_mode && @multiline_flush_interval) ? TailWatcher::LineBufferTimerFlusher.new(log, @multiline_flush_interval, &method(:flush_buffer)) : nil
257-
tw = TailWatcher.new(path, @rotate_wait, pe, log, @read_from_head, @enable_watch_timer, @read_lines_limit, method(:update_watcher), line_buffer_timer_flusher, @from_encoding, @encoding, open_on_every_update, &method(:receive_lines))
263+
tw = TailWatcher.new(path, @rotate_wait, pe, log, @read_from_head, @enable_watch_timer, @enable_stat_watcher, @read_lines_limit, method(:update_watcher), line_buffer_timer_flusher, @from_encoding, @encoding, open_on_every_update, &method(:receive_lines))
258264
tw.attach do |watcher|
259265
watcher.timer_trigger = timer_execute(:in_tail_timer_trigger, 1, &watcher.method(:on_notify)) if watcher.enable_watch_timer
260-
event_loop_attach(watcher.stat_trigger)
266+
event_loop_attach(watcher.stat_trigger) if watcher.enable_stat_watcher
261267
end
262268
tw
263269
rescue => e
@@ -457,17 +463,18 @@ def parse_multilines(lines, tail_watcher)
457463
end
458464

459465
class TailWatcher
460-
def initialize(path, rotate_wait, pe, log, read_from_head, enable_watch_timer, read_lines_limit, update_watcher, line_buffer_timer_flusher, from_encoding, encoding, open_on_every_update, &receive_lines)
466+
def initialize(path, rotate_wait, pe, log, read_from_head, enable_watch_timer, enable_stat_watcher, read_lines_limit, update_watcher, line_buffer_timer_flusher, from_encoding, encoding, open_on_every_update, &receive_lines)
461467
@path = path
462468
@rotate_wait = rotate_wait
463469
@pe = pe || MemoryPositionEntry.new
464470
@read_from_head = read_from_head
465471
@enable_watch_timer = enable_watch_timer
472+
@enable_stat_watcher = enable_stat_watcher
466473
@read_lines_limit = read_lines_limit
467474
@receive_lines = receive_lines
468475
@update_watcher = update_watcher
469476

470-
@stat_trigger = StatWatcher.new(self, &method(:on_notify))
477+
@stat_trigger = @enable_stat_watcher ? StatWatcher.new(self, &method(:on_notify)) : nil
471478
@timer_trigger = nil
472479

473480
@rotate_handler = RotateHandler.new(self, &method(:on_rotate))
@@ -483,7 +490,7 @@ def initialize(path, rotate_wait, pe, log, read_from_head, enable_watch_timer, r
483490
attr_reader :path
484491
attr_reader :log, :pe, :read_lines_limit, :open_on_every_update
485492
attr_reader :from_encoding, :encoding
486-
attr_reader :stat_trigger, :enable_watch_timer
493+
attr_reader :stat_trigger, :enable_watch_timer, :enable_stat_watcher
487494
attr_accessor :timer_trigger
488495
attr_accessor :line_buffer, :line_buffer_timer_flusher
489496
attr_accessor :unwatched # This is used for removing position entry from PositionFile
@@ -503,7 +510,7 @@ def attach
503510

504511
def detach
505512
@timer_trigger.detach if @enable_watch_timer && @timer_trigger && @timer_trigger.attached?
506-
@stat_trigger.detach if @stat_trigger && @stat_trigger.attached?
513+
@stat_trigger.detach if @enable_stat_watcher && @stat_trigger && @stat_trigger.attached?
507514
@io_handler.on_notify if @io_handler
508515
end
509516

test/plugin/test_in_tail.rb

+33-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def cleanup_directory(path)
4141
COMMON_CONFIG = CONFIG + config_element("", "", { "pos_file" => "#{TMP_DIR}/tail.pos" })
4242
CONFIG_READ_FROM_HEAD = config_element("", "", { "read_from_head" => true })
4343
CONFIG_ENABLE_WATCH_TIMER = config_element("", "", { "enable_watch_timer" => false })
44+
CONFIG_DISABLE_STAT_WATCHER = config_element("", "", { "enable_stat_watcher" => false })
4445
CONFIG_OPEN_ON_EVERY_UPDATE = config_element("", "", { "open_on_every_update" => true })
4546
SINGLE_LINE_CONFIG = config_element("", "", { "format" => "/(?<message>.*)/" })
4647
PARSE_SINGLE_LINE_CONFIG = config_element("", "", {}, [config_element("parse", "", { "@type" => "/(?<message>.*)/" })])
@@ -83,6 +84,12 @@ def create_driver(conf = SINGLE_LINE_CONFIG, use_common_conf = true)
8384
end
8485
end
8586

87+
test "both enable_watch_timer and enable_stat_watcher are false" do
88+
assert_raise(Fluent::ConfigError) do
89+
create_driver(CONFIG_ENABLE_WATCH_TIMER + CONFIG_DISABLE_STAT_WATCHER + PARSE_SINGLE_LINE_CONFIG)
90+
end
91+
end
92+
8693
sub_test_case "encoding" do
8794
test "valid" do
8895
conf = SINGLE_LINE_CONFIG + config_element("", "", { "encoding" => "utf-8" })
@@ -256,6 +263,30 @@ def test_emit_with_enable_watch_timer(data)
256263
assert_equal({"message" => "test3"}, events[0][2])
257264
assert_equal({"message" => "test4"}, events[1][2])
258265
end
266+
267+
data(flat: CONFIG_DISABLE_STAT_WATCHER + SINGLE_LINE_CONFIG,
268+
parse: CONFIG_DISABLE_STAT_WATCHER + PARSE_SINGLE_LINE_CONFIG)
269+
def test_emit_with_disable_stat_watcher(data)
270+
config = data
271+
File.open("#{TMP_DIR}/tail.txt", "wb") {|f|
272+
f.puts "test1"
273+
f.puts "test2"
274+
}
275+
276+
d = create_driver(config)
277+
278+
d.run(expect_emits: 1) do
279+
File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
280+
f.puts "test3"
281+
f.puts "test4"
282+
}
283+
end
284+
285+
events = d.events
286+
assert(events.length > 0)
287+
assert_equal({"message" => "test3"}, events[0][2])
288+
assert_equal({"message" => "test4"}, events[1][2])
289+
end
259290
end
260291

261292
class TestWithSystem < self
@@ -926,7 +957,7 @@ def test_z_refresh_watchers
926957
Timecop.freeze(2010, 1, 2, 3, 4, 5) do
927958
flexstub(Fluent::Plugin::TailInput::TailWatcher) do |watcherclass|
928959
EX_PATHS.each do |path|
929-
watcherclass.should_receive(:new).with(path, EX_ROTATE_WAIT, Fluent::Plugin::TailInput::FilePositionEntry, any, true, true, 1000, any, any, any, any, any, any).once.and_return do
960+
watcherclass.should_receive(:new).with(path, EX_ROTATE_WAIT, Fluent::Plugin::TailInput::FilePositionEntry, any, true, true, true, 1000, any, any, any, any, any, any).once.and_return do
930961
flexmock('TailWatcher') { |watcher|
931962
watcher.should_receive(:attach).once
932963
watcher.should_receive(:unwatched=).zero_or_more_times
@@ -944,7 +975,7 @@ def test_z_refresh_watchers
944975

945976
Timecop.freeze(2010, 1, 2, 3, 4, 6) do
946977
flexstub(Fluent::Plugin::TailInput::TailWatcher) do |watcherclass|
947-
watcherclass.should_receive(:new).with('test/plugin/data/2010/01/20100102-030406.log', EX_ROTATE_WAIT, Fluent::Plugin::TailInput::FilePositionEntry, any, true, true, 1000, any, any, any, any, any, any).once.and_return do
978+
watcherclass.should_receive(:new).with('test/plugin/data/2010/01/20100102-030406.log', EX_ROTATE_WAIT, Fluent::Plugin::TailInput::FilePositionEntry, any, true, true, true, 1000, any, any, any, any, any, any).once.and_return do
948979
flexmock('TailWatcher') do |watcher|
949980
watcher.should_receive(:attach).once
950981
watcher.should_receive(:unwatched=).zero_or_more_times

0 commit comments

Comments
 (0)