fluentd 1.9.3 → 1.11.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fluentd might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/issue-auto-closer.yml +12 -0
- data/CHANGELOG.md +182 -0
- data/CONTRIBUTING.md +1 -1
- data/README.md +4 -0
- data/docs/SECURITY_AUDIT.pdf +0 -0
- data/lib/fluent/command/debug.rb +1 -0
- data/lib/fluent/command/fluentd.rb +25 -1
- data/lib/fluent/config.rb +1 -0
- data/lib/fluent/daemonizer.rb +88 -0
- data/lib/fluent/log.rb +45 -6
- data/lib/fluent/match.rb +1 -1
- data/lib/fluent/msgpack_factory.rb +13 -6
- data/lib/fluent/plugin/buffer.rb +2 -2
- data/lib/fluent/plugin/in_dummy.rb +3 -3
- data/lib/fluent/plugin/in_forward.rb +2 -2
- data/lib/fluent/plugin/in_gc_stat.rb +16 -0
- data/lib/fluent/plugin/in_http.rb +146 -75
- data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
- data/lib/fluent/plugin/in_syslog.rb +4 -4
- data/lib/fluent/plugin/in_tail.rb +40 -31
- data/lib/fluent/plugin/in_tail/position_file.rb +23 -6
- data/lib/fluent/plugin/in_unix.rb +77 -77
- data/lib/fluent/plugin/out_copy.rb +1 -1
- data/lib/fluent/plugin/out_file.rb +1 -1
- data/lib/fluent/plugin/out_forward.rb +25 -22
- data/lib/fluent/plugin/out_forward/handshake_protocol.rb +4 -0
- data/lib/fluent/plugin/out_forward/load_balancer.rb +1 -1
- data/lib/fluent/plugin/out_http.rb +15 -2
- data/lib/fluent/plugin/parser_multiline.rb +1 -1
- data/lib/fluent/plugin/parser_syslog.rb +303 -62
- data/lib/fluent/plugin/sd_file.rb +1 -0
- data/lib/fluent/plugin/sd_srv.rb +135 -0
- data/lib/fluent/plugin_helper/cert_option.rb +15 -2
- data/lib/fluent/plugin_helper/child_process.rb +3 -2
- data/lib/fluent/plugin_helper/record_accessor.rb +14 -0
- data/lib/fluent/plugin_helper/server.rb +3 -1
- data/lib/fluent/plugin_helper/service_discovery.rb +7 -0
- data/lib/fluent/plugin_helper/service_discovery/manager.rb +8 -0
- data/lib/fluent/plugin_helper/socket.rb +20 -2
- data/lib/fluent/plugin_helper/socket_option.rb +21 -3
- data/lib/fluent/supervisor.rb +21 -9
- data/lib/fluent/system_config.rb +2 -1
- data/lib/fluent/test/filter_test.rb +2 -2
- data/lib/fluent/test/output_test.rb +3 -3
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_fluentd.rb +71 -12
- data/test/config/test_system_config.rb +2 -0
- data/test/helper.rb +2 -2
- data/test/plugin/in_tail/test_fifo.rb +121 -0
- data/test/plugin/in_tail/test_io_handler.rb +132 -0
- data/test/plugin/in_tail/test_position_file.rb +25 -1
- data/test/plugin/out_forward/test_handshake_protocol.rb +10 -1
- data/test/plugin/out_forward/test_load_balancer.rb +46 -0
- data/test/plugin/test_buf_file.rb +3 -1
- data/test/plugin/test_buffer.rb +20 -0
- data/test/plugin/test_compressable.rb +7 -4
- data/test/plugin/test_in_dummy.rb +12 -14
- data/test/plugin/test_in_forward.rb +2 -2
- data/test/plugin/test_in_gc_stat.rb +24 -1
- data/test/plugin/test_in_http.rb +57 -0
- data/test/plugin/test_in_syslog.rb +16 -1
- data/test/plugin/test_in_tail.rb +43 -20
- data/test/plugin/test_in_unix.rb +128 -73
- data/test/plugin/test_out_forward.rb +39 -3
- data/test/plugin/test_out_http.rb +38 -0
- data/test/plugin/test_out_null.rb +1 -1
- data/test/plugin/test_output_as_buffered_retries.rb +12 -4
- data/test/plugin/test_output_as_buffered_secondary.rb +9 -1
- data/test/plugin/test_parser_syslog.rb +106 -46
- data/test/plugin/test_sd_file.rb +17 -0
- data/test/plugin/test_sd_srv.rb +230 -0
- data/test/plugin_helper/data/cert/cert-with-CRLF.pem +19 -0
- data/test/plugin_helper/data/cert/cert_chains/ca-cert-key.pem +27 -0
- data/test/plugin_helper/data/cert/cert_chains/ca-cert.pem +20 -0
- data/test/plugin_helper/data/cert/cert_chains/cert-key.pem +27 -0
- data/test/plugin_helper/data/cert/cert_chains/cert.pem +40 -0
- data/test/plugin_helper/data/cert/generate_cert.rb +38 -0
- data/test/plugin_helper/http_server/test_app.rb +1 -1
- data/test/plugin_helper/http_server/test_route.rb +1 -1
- data/test/plugin_helper/test_cert_option.rb +2 -0
- data/test/plugin_helper/test_child_process.rb +20 -3
- data/test/plugin_helper/test_http_server_helper.rb +2 -2
- data/test/plugin_helper/test_record_accessor.rb +41 -0
- data/test/plugin_helper/test_server.rb +1 -1
- data/test/plugin_helper/test_service_discovery.rb +37 -4
- data/test/plugin_helper/test_socket.rb +131 -0
- data/test/test_daemonizer.rb +91 -0
- data/test/test_log.rb +44 -0
- data/test/test_msgpack_factory.rb +18 -0
- metadata +28 -2
data/lib/fluent/system_config.rb
CHANGED
@@ -24,7 +24,7 @@ module Fluent
|
|
24
24
|
SYSTEM_CONFIG_PARAMETERS = [
|
25
25
|
:workers, :root_dir, :log_level,
|
26
26
|
:suppress_repeated_stacktrace, :emit_error_log_interval, :suppress_config_dump,
|
27
|
-
:log_event_verbose,
|
27
|
+
:log_event_verbose, :ignore_repeated_log_interval,
|
28
28
|
:without_source, :rpc_endpoint, :enable_get_dump, :process_name,
|
29
29
|
:file_permission, :dir_permission, :counter_server, :counter_client,
|
30
30
|
:strict_config_value, :enable_msgpack_time_support
|
@@ -34,6 +34,7 @@ module Fluent
|
|
34
34
|
config_param :root_dir, :string, default: nil
|
35
35
|
config_param :log_level, :enum, list: [:trace, :debug, :info, :warn, :error, :fatal], default: 'info'
|
36
36
|
config_param :suppress_repeated_stacktrace, :bool, default: nil
|
37
|
+
config_param :ignore_repeated_log_interval, :time, default: nil
|
37
38
|
config_param :emit_error_log_interval, :time, default: nil
|
38
39
|
config_param :suppress_config_dump, :bool, default: nil
|
39
40
|
config_param :log_event_verbose, :bool, default: nil
|
@@ -30,12 +30,12 @@ module Fluent
|
|
30
30
|
attr_reader :filtered
|
31
31
|
attr_accessor :tag
|
32
32
|
|
33
|
-
def emit(record, time =
|
33
|
+
def emit(record, time = EventTime.now)
|
34
34
|
emit_with_tag(@tag, record, time)
|
35
35
|
end
|
36
36
|
alias_method :filter, :emit
|
37
37
|
|
38
|
-
def emit_with_tag(tag, record, time =
|
38
|
+
def emit_with_tag(tag, record, time = EventTime.now)
|
39
39
|
@events[tag] ||= MultiEventStream.new
|
40
40
|
@events[tag].add(time, record)
|
41
41
|
end
|
@@ -41,7 +41,7 @@ module Fluent
|
|
41
41
|
|
42
42
|
attr_accessor :tag
|
43
43
|
|
44
|
-
def emit(record, time=
|
44
|
+
def emit(record, time=EventTime.now)
|
45
45
|
es = OneEventStream.new(time, record)
|
46
46
|
@instance.emit_events(@tag, es)
|
47
47
|
end
|
@@ -62,7 +62,7 @@ module Fluent
|
|
62
62
|
|
63
63
|
attr_accessor :tag
|
64
64
|
|
65
|
-
def emit(record, time=
|
65
|
+
def emit(record, time=EventTime.now)
|
66
66
|
@entries << [time, record]
|
67
67
|
self
|
68
68
|
end
|
@@ -110,7 +110,7 @@ module Fluent
|
|
110
110
|
|
111
111
|
attr_accessor :tag
|
112
112
|
|
113
|
-
def emit(record, time=
|
113
|
+
def emit(record, time=EventTime.now)
|
114
114
|
@entries << [time, record]
|
115
115
|
self
|
116
116
|
end
|
data/lib/fluent/version.rb
CHANGED
@@ -16,6 +16,7 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
16
16
|
FileUtils.mkdir_p(TMP_DIR)
|
17
17
|
@supervisor_pid = nil
|
18
18
|
@worker_pids = []
|
19
|
+
ENV["TEST_RUBY_PATH"] = nil
|
19
20
|
end
|
20
21
|
|
21
22
|
def process_exist?(pid)
|
@@ -84,9 +85,22 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
84
85
|
null_stream.close rescue nil
|
85
86
|
end
|
86
87
|
|
88
|
+
def eager_read(io)
|
89
|
+
buf = +''
|
90
|
+
|
91
|
+
loop do
|
92
|
+
b = io.read_nonblock(1024, nil, exception: false)
|
93
|
+
if b == :wait_readable || b.nil?
|
94
|
+
return buf
|
95
|
+
end
|
96
|
+
buf << b
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
87
100
|
def assert_log_matches(cmdline, *pattern_list, patterns_not_match: [], timeout: 10, env: {})
|
88
101
|
matched = false
|
89
|
-
|
102
|
+
matched_wrongly = false
|
103
|
+
assert_error_msg = ""
|
90
104
|
stdio_buf = ""
|
91
105
|
begin
|
92
106
|
execute_command(cmdline, TMP_DIR, env) do |pid, stdout|
|
@@ -97,7 +111,7 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
97
111
|
next unless readables
|
98
112
|
break if readables.first.eof?
|
99
113
|
|
100
|
-
buf = readables.first
|
114
|
+
buf = eager_read(readables.first)
|
101
115
|
# puts buf
|
102
116
|
stdio_buf << buf
|
103
117
|
lines = stdio_buf.split("\n")
|
@@ -116,13 +130,18 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
116
130
|
end
|
117
131
|
end
|
118
132
|
rescue Timeout::Error
|
119
|
-
assert_error_msg = "execution timeout
|
133
|
+
assert_error_msg = "execution timeout"
|
120
134
|
rescue => e
|
121
|
-
assert_error_msg = "unexpected error in launching fluentd: #{e.inspect}
|
135
|
+
assert_error_msg = "unexpected error in launching fluentd: #{e.inspect}"
|
136
|
+
else
|
137
|
+
assert_error_msg = "log doesn't match" unless matched
|
122
138
|
end
|
123
|
-
assert matched, assert_error_msg
|
124
139
|
|
125
|
-
|
140
|
+
if patterns_not_match.empty?
|
141
|
+
assert_error_msg = build_message(assert_error_msg,
|
142
|
+
"<?>\nwas expected to include:\n<?>",
|
143
|
+
stdio_buf, pattern_list)
|
144
|
+
else
|
126
145
|
lines = stdio_buf.split("\n")
|
127
146
|
patterns_not_match.each do |ptn|
|
128
147
|
matched_wrongly = if ptn.is_a? Regexp
|
@@ -130,9 +149,17 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
130
149
|
else
|
131
150
|
lines.any?{|line| line.include?(ptn) }
|
132
151
|
end
|
133
|
-
|
152
|
+
if matched_wrongly
|
153
|
+
assert_error_msg << "\n" unless assert_error_msg.empty?
|
154
|
+
assert_error_msg << "pattern exists in logs wrongly: #{ptn}"
|
155
|
+
end
|
134
156
|
end
|
157
|
+
assert_error_msg = build_message(assert_error_msg,
|
158
|
+
"<?>\nwas expected to include:\n<?>\nand not include:\n<?>",
|
159
|
+
stdio_buf, pattern_list, patterns_not_match)
|
135
160
|
end
|
161
|
+
|
162
|
+
assert matched && !matched_wrongly, assert_error_msg
|
136
163
|
end
|
137
164
|
|
138
165
|
def assert_fluentd_fails_to_start(cmdline, *pattern_list, timeout: 10)
|
@@ -150,7 +177,7 @@ class TestFluentdCommand < ::Test::Unit::TestCase
|
|
150
177
|
next unless readables
|
151
178
|
next if readables.first.eof?
|
152
179
|
|
153
|
-
stdio_buf << readables.first
|
180
|
+
stdio_buf << eager_read(readables.first)
|
154
181
|
lines = stdio_buf.split("\n")
|
155
182
|
if lines.any?{|line| line.include?("fluentd worker is now running") }
|
156
183
|
running = true
|
@@ -830,8 +857,7 @@ CONF
|
|
830
857
|
'-external-encoding' => '--external-encoding=utf-8',
|
831
858
|
'-internal-encoding' => '--internal-encoding=utf-8',
|
832
859
|
)
|
833
|
-
test "-E option is set to
|
834
|
-
omit "hard to run correctly on Windows. Need to debug." if Fluent.windows?
|
860
|
+
test "-E option is set to RUBYOPT" do |opt|
|
835
861
|
conf = <<CONF
|
836
862
|
<source>
|
837
863
|
@type dummy
|
@@ -842,6 +868,7 @@ CONF
|
|
842
868
|
</match>
|
843
869
|
CONF
|
844
870
|
conf_path = create_conf_file('rubyopt_test.conf', conf)
|
871
|
+
opt << " #{ENV['RUBYOPT']}" if ENV['RUBYOPT']
|
845
872
|
assert_log_matches(
|
846
873
|
create_cmdline(conf_path),
|
847
874
|
*opt.split(' '),
|
@@ -850,7 +877,7 @@ CONF
|
|
850
877
|
)
|
851
878
|
end
|
852
879
|
|
853
|
-
|
880
|
+
test "without RUBYOPT" do
|
854
881
|
conf = <<CONF
|
855
882
|
<source>
|
856
883
|
@type dummy
|
@@ -865,7 +892,7 @@ CONF
|
|
865
892
|
end
|
866
893
|
|
867
894
|
test 'invalid values are set to RUBYOPT' do
|
868
|
-
omit "hard to run correctly on Windows
|
895
|
+
omit "hard to run correctly because RUBYOPT=-r/path/to/bundler/setup is required on Windows while this test set invalid RUBYOPT" if Fluent.windows?
|
869
896
|
conf = <<CONF
|
870
897
|
<source>
|
871
898
|
@type dummy
|
@@ -883,6 +910,38 @@ CONF
|
|
883
910
|
)
|
884
911
|
end
|
885
912
|
|
913
|
+
# https://github.com/fluent/fluentd/issues/2915
|
914
|
+
test "ruby path contains spaces" do
|
915
|
+
conf = <<CONF
|
916
|
+
<source>
|
917
|
+
@type dummy
|
918
|
+
tag dummy
|
919
|
+
</source>
|
920
|
+
<match>
|
921
|
+
@type null
|
922
|
+
</match>
|
923
|
+
CONF
|
924
|
+
ruby_path = ServerEngine.ruby_bin_path
|
925
|
+
tmp_ruby_path = File.join(TMP_DIR, "ruby with spaces")
|
926
|
+
if Fluent.windows?
|
927
|
+
tmp_ruby_path << ".bat"
|
928
|
+
File.open(tmp_ruby_path, "w") do |file|
|
929
|
+
file.write "#{ruby_path} %*"
|
930
|
+
end
|
931
|
+
else
|
932
|
+
FileUtils.ln_sf(ruby_path, tmp_ruby_path)
|
933
|
+
end
|
934
|
+
ENV["TEST_RUBY_PATH"] = tmp_ruby_path
|
935
|
+
cmd_path = File.expand_path(File.dirname(__FILE__) + "../../../bin/fluentd")
|
936
|
+
conf_path = create_conf_file('space_mixed_ruby_path_test.conf', conf)
|
937
|
+
args = ["bundle", "exec", tmp_ruby_path, cmd_path, "-c", conf_path]
|
938
|
+
assert_log_matches(
|
939
|
+
args,
|
940
|
+
'spawn command to main:',
|
941
|
+
'-Eascii-8bit:ascii-8bit'
|
942
|
+
)
|
943
|
+
end
|
944
|
+
|
886
945
|
test 'success to start workers when file buffer is configured in non-workers way only for specific worker' do
|
887
946
|
conf = <<CONF
|
888
947
|
<system>
|
@@ -73,6 +73,7 @@ module Fluent::Config
|
|
73
73
|
assert_nil(sc.root_dir)
|
74
74
|
assert_equal(Fluent::Log::LEVEL_INFO, sc.log_level)
|
75
75
|
assert_nil(sc.suppress_repeated_stacktrace)
|
76
|
+
assert_nil(sc.ignore_repeated_log_interval)
|
76
77
|
assert_nil(sc.emit_error_log_interval)
|
77
78
|
assert_nil(sc.suppress_config_dump)
|
78
79
|
assert_nil(sc.without_source)
|
@@ -86,6 +87,7 @@ module Fluent::Config
|
|
86
87
|
'root_dir' => ['root_dir', File.join(TMP_DIR, 'root')],
|
87
88
|
'log_level' => ['log_level', 'error'],
|
88
89
|
'suppress_repeated_stacktrace' => ['suppress_repeated_stacktrace', true],
|
90
|
+
'ignore_repeated_log_interval' => ['ignore_repeated_log_interval', 10],
|
89
91
|
'log_event_verbose' => ['log_event_verbose', true],
|
90
92
|
'suppress_config_dump' => ['suppress_config_dump', true],
|
91
93
|
'without_source' => ['without_source', true],
|
data/test/helper.rb
CHANGED
@@ -49,8 +49,8 @@ require 'fluent/plugin_helper'
|
|
49
49
|
require 'fluent/msgpack_factory'
|
50
50
|
require 'fluent/time'
|
51
51
|
require 'serverengine'
|
52
|
-
|
53
|
-
|
52
|
+
require_relative 'helpers/fuzzy_assert'
|
53
|
+
require_relative 'helpers/process_extenstion'
|
54
54
|
|
55
55
|
module Fluent
|
56
56
|
module Plugin
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require_relative '../../helper'
|
2
|
+
|
3
|
+
require 'fluent/plugin/in_tail'
|
4
|
+
|
5
|
+
class IntailFIFO < Test::Unit::TestCase
|
6
|
+
sub_test_case '#read_line' do
|
7
|
+
test 'returns lines spliting per `\n`' do
|
8
|
+
fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
|
9
|
+
text = ("test\n" * 3).force_encoding(Encoding::ASCII_8BIT)
|
10
|
+
fifo << text
|
11
|
+
lines = []
|
12
|
+
fifo.read_lines(lines)
|
13
|
+
assert_equal Encoding::ASCII_8BIT, lines[0].encoding
|
14
|
+
assert_equal ["test\n", "test\n", "test\n"], lines
|
15
|
+
end
|
16
|
+
|
17
|
+
test 'concant line when line is separated' do
|
18
|
+
fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
|
19
|
+
text = ("test\n" * 3 + 'test').force_encoding(Encoding::ASCII_8BIT)
|
20
|
+
fifo << text
|
21
|
+
lines = []
|
22
|
+
fifo.read_lines(lines)
|
23
|
+
assert_equal Encoding::ASCII_8BIT, lines[0].encoding
|
24
|
+
assert_equal ["test\n", "test\n", "test\n"], lines
|
25
|
+
|
26
|
+
fifo << "2\n"
|
27
|
+
fifo.read_lines(lines)
|
28
|
+
assert_equal Encoding::ASCII_8BIT, lines[0].encoding
|
29
|
+
assert_equal ["test\n", "test\n", "test\n", "test2\n"], lines
|
30
|
+
end
|
31
|
+
|
32
|
+
test 'returns lines which convert encoding' do
|
33
|
+
fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::UTF_8)
|
34
|
+
text = ("test\n" * 3).force_encoding(Encoding::ASCII_8BIT)
|
35
|
+
fifo << text
|
36
|
+
lines = []
|
37
|
+
fifo.read_lines(lines)
|
38
|
+
assert_equal Encoding::UTF_8, lines[0].encoding
|
39
|
+
assert_equal ["test\n", "test\n", "test\n"], lines
|
40
|
+
end
|
41
|
+
|
42
|
+
test 'reads lines as from_encoding' do
|
43
|
+
fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::UTF_8, Encoding::ASCII_8BIT)
|
44
|
+
text = ("test\n" * 3).force_encoding(Encoding::UTF_8)
|
45
|
+
fifo << text
|
46
|
+
lines = []
|
47
|
+
fifo.read_lines(lines)
|
48
|
+
assert_equal Encoding::ASCII_8BIT, lines[0].encoding
|
49
|
+
assert_equal ["test\n", "test\n", "test\n"], lines
|
50
|
+
end
|
51
|
+
|
52
|
+
sub_test_case 'when it includes multi byte chars' do
|
53
|
+
test 'handles it as ascii_8bit' do
|
54
|
+
fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
|
55
|
+
text = ("てすと\n" * 3).force_encoding(Encoding::ASCII_8BIT)
|
56
|
+
fifo << text
|
57
|
+
lines = []
|
58
|
+
fifo.read_lines(lines)
|
59
|
+
assert_equal Encoding::ASCII_8BIT, lines[0].encoding
|
60
|
+
assert_equal ["てすと\n", "てすと\n", "てすと\n"].map { |e| e.force_encoding(Encoding::ASCII_8BIT) }, lines
|
61
|
+
end
|
62
|
+
|
63
|
+
test 'replaces character with ? when convert error happens' do
|
64
|
+
fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::UTF_8, Encoding::ASCII_8BIT)
|
65
|
+
text = ("てすと\n" * 3).force_encoding(Encoding::UTF_8)
|
66
|
+
fifo << text
|
67
|
+
lines = []
|
68
|
+
fifo.read_lines(lines)
|
69
|
+
assert_equal Encoding::ASCII_8BIT, lines[0].encoding
|
70
|
+
assert_equal ["???\n", "???\n", "???\n"].map { |e| e.force_encoding(Encoding::ASCII_8BIT) }, lines
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
test 'reutrns nothing when buffer is empty' do
|
75
|
+
fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
|
76
|
+
lines = []
|
77
|
+
fifo.read_lines(lines)
|
78
|
+
assert_equal [], lines
|
79
|
+
|
80
|
+
text = "test\n" * 3
|
81
|
+
fifo << text
|
82
|
+
fifo.read_lines(lines)
|
83
|
+
assert_equal ["test\n", "test\n", "test\n"], lines
|
84
|
+
|
85
|
+
lines = []
|
86
|
+
fifo.read_lines(lines)
|
87
|
+
assert_equal [], lines
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
sub_test_case '#<<' do
|
92
|
+
test 'does not make any change about encoding to an argument' do
|
93
|
+
fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
|
94
|
+
text = ("test\n" * 3).force_encoding(Encoding::UTF_8)
|
95
|
+
|
96
|
+
assert_equal Encoding::UTF_8, text.encoding
|
97
|
+
fifo << text
|
98
|
+
assert_equal Encoding::UTF_8, text.encoding
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
sub_test_case '#bytesize' do
|
103
|
+
test 'reutrns buffer size' do
|
104
|
+
fifo = Fluent::Plugin::TailInput::TailWatcher::FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
|
105
|
+
text = "test\n" * 3 + 'test'
|
106
|
+
fifo << text
|
107
|
+
|
108
|
+
assert_equal text.bytesize, fifo.bytesize
|
109
|
+
lines = []
|
110
|
+
fifo.read_lines(lines)
|
111
|
+
assert_equal ["test\n", "test\n", "test\n"], lines
|
112
|
+
|
113
|
+
assert_equal 'test'.bytesize, fifo.bytesize
|
114
|
+
fifo << "2\n"
|
115
|
+
fifo.read_lines(lines)
|
116
|
+
assert_equal ["test\n", "test\n", "test\n", "test2\n"], lines
|
117
|
+
|
118
|
+
assert_equal 0, fifo.bytesize
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require_relative '../../helper'
|
2
|
+
|
3
|
+
require 'fluent/plugin/in_tail'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
class IntailIOHandlerTest < Test::Unit::TestCase
|
7
|
+
setup do
|
8
|
+
@file = Tempfile.new('intail_io_handler').binmode
|
9
|
+
end
|
10
|
+
|
11
|
+
teardown do
|
12
|
+
@file.close rescue nil
|
13
|
+
@file.unlink rescue nil
|
14
|
+
end
|
15
|
+
|
16
|
+
test '#on_notify load file content and passed it to receive_lines method' do
|
17
|
+
text = "this line is test\ntest line is test\n"
|
18
|
+
@file.write(text)
|
19
|
+
@file.close
|
20
|
+
|
21
|
+
watcher = 'watcher'
|
22
|
+
|
23
|
+
update_pos = 0
|
24
|
+
|
25
|
+
stub(watcher).pe do
|
26
|
+
pe = 'position_file'
|
27
|
+
stub(pe).read_pos { 0 }
|
28
|
+
stub(pe).update_pos { |val| update_pos = val }
|
29
|
+
pe
|
30
|
+
end
|
31
|
+
|
32
|
+
returned_lines = ''
|
33
|
+
r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 100, log: $log, open_on_every_update: false) do |lines, _watcher|
|
34
|
+
returned_lines << lines.join
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
r.on_notify
|
39
|
+
assert_equal text.bytesize, update_pos
|
40
|
+
assert_equal text, returned_lines
|
41
|
+
|
42
|
+
r.on_notify
|
43
|
+
|
44
|
+
assert_equal text.bytesize, update_pos
|
45
|
+
assert_equal text, returned_lines
|
46
|
+
end
|
47
|
+
|
48
|
+
sub_test_case 'when open_on_every_update is true and read_pos returns always 0' do
|
49
|
+
test 'open new IO and change pos to 0 and read it' do
|
50
|
+
text = "this line is test\ntest line is test\n"
|
51
|
+
@file.write(text)
|
52
|
+
@file.close
|
53
|
+
|
54
|
+
update_pos = 0
|
55
|
+
|
56
|
+
watcher = 'watcher'
|
57
|
+
stub(watcher).pe do
|
58
|
+
pe = 'position_file'
|
59
|
+
stub(pe).read_pos { 0 }
|
60
|
+
stub(pe).update_pos { |val| update_pos = val }
|
61
|
+
pe
|
62
|
+
end
|
63
|
+
|
64
|
+
returned_lines = ''
|
65
|
+
r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 100, log: $log, open_on_every_update: true) do |lines, _watcher|
|
66
|
+
returned_lines << lines.join
|
67
|
+
true
|
68
|
+
end
|
69
|
+
|
70
|
+
r.on_notify
|
71
|
+
assert_equal text.bytesize, update_pos
|
72
|
+
assert_equal text, returned_lines
|
73
|
+
|
74
|
+
r.on_notify
|
75
|
+
assert_equal text * 2, returned_lines
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
sub_test_case 'when limit is 5' do
|
80
|
+
test 'call receive_lines once when short line(less than 8192)' do
|
81
|
+
text = "line\n" * 8
|
82
|
+
@file.write(text)
|
83
|
+
@file.close
|
84
|
+
|
85
|
+
update_pos = 0
|
86
|
+
|
87
|
+
watcher = 'watcher'
|
88
|
+
stub(watcher).pe do
|
89
|
+
pe = 'position_file'
|
90
|
+
stub(pe).read_pos { 0 }
|
91
|
+
stub(pe).update_pos { |val| update_pos = val }
|
92
|
+
pe
|
93
|
+
end
|
94
|
+
|
95
|
+
returned_lines = []
|
96
|
+
r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 5, log: $log, open_on_every_update: false) do |lines, _watcher|
|
97
|
+
returned_lines << lines.dup
|
98
|
+
true
|
99
|
+
end
|
100
|
+
|
101
|
+
r.on_notify
|
102
|
+
assert_equal 8, returned_lines[0].size
|
103
|
+
end
|
104
|
+
|
105
|
+
test 'call receive_lines some times when long line(more than 8192)' do
|
106
|
+
t = 'line' * (8192 / 8)
|
107
|
+
text = "#{t}\n" * 8
|
108
|
+
@file.write(text)
|
109
|
+
@file.close
|
110
|
+
|
111
|
+
update_pos = 0
|
112
|
+
|
113
|
+
watcher = 'watcher'
|
114
|
+
stub(watcher).pe do
|
115
|
+
pe = 'position_file'
|
116
|
+
stub(pe).read_pos { 0 }
|
117
|
+
stub(pe).update_pos { |val| update_pos = val }
|
118
|
+
pe
|
119
|
+
end
|
120
|
+
|
121
|
+
returned_lines = []
|
122
|
+
r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 5, log: $log, open_on_every_update: false) do |lines, _watcher|
|
123
|
+
returned_lines << lines.dup
|
124
|
+
true
|
125
|
+
end
|
126
|
+
|
127
|
+
r.on_notify
|
128
|
+
assert_equal 5, returned_lines[0].size
|
129
|
+
assert_equal 3, returned_lines[1].size
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|