fluentd 1.16.0 → 1.16.7
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/.github/ISSUE_TEMPLATE/{bug_report.yaml → bug_report.yml} +1 -0
- data/.github/ISSUE_TEMPLATE/{feature_request.yaml → feature_request.yml} +1 -0
- data/.github/workflows/stale-actions.yml +24 -0
- data/.github/workflows/test.yml +39 -0
- data/CHANGELOG.md +161 -0
- data/CONTRIBUTING.md +1 -1
- data/MAINTAINERS.md +3 -3
- data/README.md +0 -2
- data/SECURITY.md +5 -9
- data/fluentd.gemspec +10 -2
- data/lib/fluent/command/ctl.rb +2 -2
- data/lib/fluent/command/fluentd.rb +1 -1
- data/lib/fluent/command/plugin_config_formatter.rb +1 -1
- data/lib/fluent/config/dsl.rb +1 -1
- data/lib/fluent/config/v1_parser.rb +2 -2
- data/lib/fluent/config/yaml_parser/parser.rb +4 -0
- data/lib/fluent/counter/server.rb +1 -1
- data/lib/fluent/counter/validator.rb +3 -3
- data/lib/fluent/engine.rb +1 -1
- data/lib/fluent/event.rb +8 -4
- data/lib/fluent/log.rb +9 -0
- data/lib/fluent/match.rb +1 -1
- data/lib/fluent/msgpack_factory.rb +6 -1
- data/lib/fluent/plugin/base.rb +1 -1
- data/lib/fluent/plugin/buffer.rb +96 -87
- data/lib/fluent/plugin/filter_record_transformer.rb +1 -1
- data/lib/fluent/plugin/in_forward.rb +1 -1
- data/lib/fluent/plugin/in_http.rb +8 -8
- data/lib/fluent/plugin/in_sample.rb +1 -1
- data/lib/fluent/plugin/in_tail/position_file.rb +32 -18
- data/lib/fluent/plugin/in_tail.rb +99 -31
- data/lib/fluent/plugin/in_tcp.rb +43 -0
- data/lib/fluent/plugin/out_exec_filter.rb +2 -2
- data/lib/fluent/plugin/out_file.rb +8 -0
- data/lib/fluent/plugin/output.rb +2 -2
- data/lib/fluent/plugin/parser_json.rb +4 -12
- data/lib/fluent/plugin_helper/event_loop.rb +2 -2
- data/lib/fluent/plugin_helper/record_accessor.rb +1 -1
- data/lib/fluent/plugin_helper/server.rb +8 -0
- data/lib/fluent/plugin_helper/thread.rb +3 -3
- data/lib/fluent/plugin_id.rb +1 -1
- data/lib/fluent/supervisor.rb +2 -2
- data/lib/fluent/system_config.rb +1 -1
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +28 -3
- data/templates/new_gem/test/helper.rb.erb +0 -1
- data/test/command/test_cat.rb +2 -2
- data/test/command/test_fluentd.rb +65 -12
- data/test/config/test_system_config.rb +2 -2
- data/test/helper.rb +27 -7
- data/test/plugin/in_tail/test_io_handler.rb +13 -14
- data/test/plugin/in_tail/test_position_file.rb +37 -8
- data/test/plugin/out_forward/test_ack_handler.rb +3 -3
- data/test/plugin/out_forward/test_socket_cache.rb +3 -3
- data/test/plugin/test_base.rb +1 -1
- data/test/plugin/test_buffer.rb +110 -0
- data/test/plugin/test_buffer_chunk.rb +11 -0
- data/test/plugin/test_in_forward.rb +11 -10
- data/test/plugin/test_in_http.rb +1 -1
- data/test/plugin/test_in_monitor_agent.rb +6 -6
- data/test/plugin/test_in_syslog.rb +25 -18
- data/test/plugin/test_in_tail.rb +639 -0
- data/test/plugin/test_in_tcp.rb +75 -5
- data/test/plugin/test_in_udp.rb +35 -1
- data/test/plugin/test_in_unix.rb +2 -2
- data/test/plugin/test_multi_output.rb +1 -1
- data/test/plugin/test_out_exec_filter.rb +14 -9
- data/test/plugin/test_out_file.rb +24 -4
- data/test/plugin/test_out_forward.rb +36 -42
- data/test/plugin/test_out_stream.rb +1 -1
- data/test/plugin/test_output.rb +12 -12
- data/test/plugin/test_output_as_buffered.rb +44 -44
- data/test/plugin/test_output_as_buffered_compress.rb +32 -18
- data/test/plugin/test_output_as_buffered_retries.rb +1 -1
- data/test/plugin/test_output_as_buffered_secondary.rb +2 -2
- data/test/plugin/test_parser_json.rb +31 -0
- data/test/plugin_helper/test_child_process.rb +15 -5
- data/test/plugin_helper/test_http_server_helper.rb +1 -1
- data/test/plugin_helper/test_server.rb +110 -38
- data/test/plugin_helper/test_socket.rb +1 -1
- data/test/test_config.rb +6 -0
- data/test/test_event_router.rb +2 -2
- data/test/test_log.rb +38 -1
- data/test/test_msgpack_factory.rb +32 -0
- data/test/test_supervisor.rb +13 -0
- metadata +44 -17
- data/.github/workflows/linux-test.yaml +0 -36
- data/.github/workflows/macos-test.yaml +0 -34
- data/.github/workflows/windows-test.yaml +0 -49
data/test/plugin/test_in_tcp.rb
CHANGED
|
@@ -5,7 +5,7 @@ require 'fluent/plugin/in_tcp'
|
|
|
5
5
|
class TcpInputTest < Test::Unit::TestCase
|
|
6
6
|
def setup
|
|
7
7
|
Fluent::Test.setup
|
|
8
|
-
@port = unused_port
|
|
8
|
+
@port = unused_port(protocol: :tcp)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def teardown
|
|
@@ -218,16 +218,14 @@ class TcpInputTest < Test::Unit::TestCase
|
|
|
218
218
|
</client>
|
|
219
219
|
</security>
|
|
220
220
|
!)
|
|
221
|
-
d.run(
|
|
221
|
+
d.run(expect_records: 1, timeout: 2) do
|
|
222
222
|
create_tcp_socket('127.0.0.1', @port) do |sock|
|
|
223
223
|
sock.send("hello\n", 0)
|
|
224
224
|
end
|
|
225
225
|
end
|
|
226
226
|
|
|
227
|
-
assert_equal 1, d.
|
|
227
|
+
assert_equal 1, d.logs.count { |l| l =~ /anonymous client/ }
|
|
228
228
|
assert_equal 0, d.events.size
|
|
229
|
-
ensure
|
|
230
|
-
d.instance_shutdown if d&.instance
|
|
231
229
|
end
|
|
232
230
|
end
|
|
233
231
|
|
|
@@ -255,4 +253,76 @@ class TcpInputTest < Test::Unit::TestCase
|
|
|
255
253
|
assert_equal 'hello', event[2]['msg']
|
|
256
254
|
end
|
|
257
255
|
end
|
|
256
|
+
|
|
257
|
+
sub_test_case "message_length_limit" do
|
|
258
|
+
data("batch_emit", { extract: "" }, keep: true)
|
|
259
|
+
data("single_emit", { extract: "<extract>\ntag_key tag\n</extract>\n" }, keep: true)
|
|
260
|
+
test "drop records exceeding limit" do |data|
|
|
261
|
+
message_length_limit = 10
|
|
262
|
+
d = create_driver(base_config + %!
|
|
263
|
+
message_length_limit #{message_length_limit}
|
|
264
|
+
<parse>
|
|
265
|
+
@type none
|
|
266
|
+
</parse>
|
|
267
|
+
#{data[:extract]}
|
|
268
|
+
!)
|
|
269
|
+
d.run(expect_records: 2, timeout: 10) do
|
|
270
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
|
271
|
+
sock.send("a" * message_length_limit + "\n", 0)
|
|
272
|
+
sock.send("b" * (message_length_limit + 1) + "\n", 0)
|
|
273
|
+
sock.send("c" * (message_length_limit - 1) + "\n", 0)
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
expected_records = [
|
|
278
|
+
"a" * message_length_limit,
|
|
279
|
+
"c" * (message_length_limit - 1)
|
|
280
|
+
]
|
|
281
|
+
actual_records = d.events.collect do |event|
|
|
282
|
+
event[2]["message"]
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
assert_equal expected_records, actual_records
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
test "clear buffer and discard the subsequent data until the next delimiter" do |data|
|
|
289
|
+
message_length_limit = 12
|
|
290
|
+
d = create_driver(base_config + %!
|
|
291
|
+
message_length_limit #{message_length_limit}
|
|
292
|
+
delimiter ";"
|
|
293
|
+
<parse>
|
|
294
|
+
@type json
|
|
295
|
+
</parse>
|
|
296
|
+
#{data[:extract]}
|
|
297
|
+
!)
|
|
298
|
+
d.run(expect_records: 1, timeout: 10) do
|
|
299
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
|
300
|
+
sock.send('{"message":', 0)
|
|
301
|
+
sock.send('"hello', 0)
|
|
302
|
+
sleep 1 # To make the server read data and clear the buffer here.
|
|
303
|
+
sock.send('world!"};', 0) # This subsequent data must be discarded so that a parsing failure doesn't occur.
|
|
304
|
+
sock.send('{"k":"v"};', 0) # This will succeed to parse.
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
logs = d.logs.collect do |log|
|
|
309
|
+
log.gsub(/\A\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4} /, "")
|
|
310
|
+
end
|
|
311
|
+
actual_records = d.events.collect do |event|
|
|
312
|
+
event[2]
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
assert_equal(
|
|
316
|
+
{
|
|
317
|
+
# Asserting that '[warn]: pattern not matched message="world!\"}"' warning does not occur.
|
|
318
|
+
logs: ['[info]: The buffer size exceeds \'message_length_limit\', cleared: limit=12 size=17 head="{\"message\":\"hello"' + "\n"],
|
|
319
|
+
records: [{"k" => "v"}],
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
logs: logs[1..],
|
|
323
|
+
records: actual_records,
|
|
324
|
+
}
|
|
325
|
+
)
|
|
326
|
+
end
|
|
327
|
+
end
|
|
258
328
|
end
|
data/test/plugin/test_in_udp.rb
CHANGED
|
@@ -5,7 +5,7 @@ require 'fluent/plugin/in_udp'
|
|
|
5
5
|
class UdpInputTest < Test::Unit::TestCase
|
|
6
6
|
def setup
|
|
7
7
|
Fluent::Test.setup
|
|
8
|
-
@port = unused_port
|
|
8
|
+
@port = unused_port(protocol: :udp)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def teardown
|
|
@@ -265,4 +265,38 @@ class UdpInputTest < Test::Unit::TestCase
|
|
|
265
265
|
end
|
|
266
266
|
end
|
|
267
267
|
end
|
|
268
|
+
|
|
269
|
+
test 'message_length_limit' do
|
|
270
|
+
message_length_limit = 32
|
|
271
|
+
|
|
272
|
+
if Fluent.windows?
|
|
273
|
+
expected_records = ["0" * 30, "4" * 30]
|
|
274
|
+
else
|
|
275
|
+
expected_records = 1.upto(3).collect do |i|
|
|
276
|
+
"#{i}" * message_length_limit
|
|
277
|
+
end
|
|
278
|
+
expected_records.prepend("0" * 30)
|
|
279
|
+
expected_records.append("4" * 30)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
d = create_driver(base_config + %!
|
|
283
|
+
format none
|
|
284
|
+
message_length_limit #{message_length_limit}
|
|
285
|
+
!)
|
|
286
|
+
d.run(expect_records: expected_records.size, timeout: 5) do
|
|
287
|
+
create_udp_socket('127.0.0.1', @port) do |u|
|
|
288
|
+
u.send("0" * 30 + "\n", 0)
|
|
289
|
+
1.upto(3) do |i|
|
|
290
|
+
u.send("#{i}" * 40 + "\n", 0)
|
|
291
|
+
end
|
|
292
|
+
u.send("4" * 30 + "\n", 0)
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
actual_records = d.events.collect do |event|
|
|
297
|
+
event[2]["message"]
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
assert_equal expected_records, actual_records
|
|
301
|
+
end
|
|
268
302
|
end
|
data/test/plugin/test_in_unix.rb
CHANGED
|
@@ -174,8 +174,8 @@ class UnixInputTest < Test::Unit::TestCase
|
|
|
174
174
|
assert_equal 0, @d.events.size
|
|
175
175
|
|
|
176
176
|
logs = @d.instance.log.logs
|
|
177
|
-
assert_equal 1, logs.
|
|
177
|
+
assert_equal 1, logs.count { |line|
|
|
178
178
|
line =~ / \[warn\]: incoming data is broken: msg=#{data.inspect}/
|
|
179
|
-
}
|
|
179
|
+
}, "should not accept broken chunk"
|
|
180
180
|
end
|
|
181
181
|
end unless Fluent.windows?
|
|
@@ -150,7 +150,7 @@ class MultiOutputTest < Test::Unit::TestCase
|
|
|
150
150
|
log_size_for_metrics_plugin_helper = 4
|
|
151
151
|
expected_warn_log_size = log_size_for_multi_output_itself + log_size_for_metrics_plugin_helper
|
|
152
152
|
logs = @i.log.out.logs
|
|
153
|
-
assert{ logs.
|
|
153
|
+
assert{ logs.count{|log| log.include?('[warn]') && log.include?("'type' is deprecated parameter name. use '@type' instead.") } == expected_warn_log_size }
|
|
154
154
|
end
|
|
155
155
|
|
|
156
156
|
test '#emit_events calls #process always' do
|
|
@@ -500,10 +500,18 @@ class ExecFilterOutputTest < Test::Unit::TestCase
|
|
|
500
500
|
d = create_driver(conf)
|
|
501
501
|
time = event_time('2011-01-02 13:14:15')
|
|
502
502
|
|
|
503
|
-
d.run(default_tag: 'test', expect_emits:
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
503
|
+
d.run(default_tag: 'test', expect_emits: 4) do
|
|
504
|
+
d.feed(time, {"k1" => 0})
|
|
505
|
+
d.flush
|
|
506
|
+
sleep 0.5
|
|
507
|
+
d.feed(time, {"k1" => 1})
|
|
508
|
+
d.flush
|
|
509
|
+
sleep 0.5
|
|
510
|
+
d.feed(time, {"k1" => 2})
|
|
511
|
+
d.flush
|
|
512
|
+
sleep 0.5
|
|
513
|
+
d.feed(time, {"k1" => 3})
|
|
514
|
+
end
|
|
507
515
|
|
|
508
516
|
assert_equal "2011-01-02 13:14:15\ttest\t0\n", d.formatted[0]
|
|
509
517
|
assert_equal "2011-01-02 13:14:15\ttest\t1\n", d.formatted[1]
|
|
@@ -524,9 +532,6 @@ class ExecFilterOutputTest < Test::Unit::TestCase
|
|
|
524
532
|
assert_equal pid_list[1], events[1][2]['child_pid']
|
|
525
533
|
assert_equal pid_list[0], events[2][2]['child_pid']
|
|
526
534
|
assert_equal pid_list[1], events[3][2]['child_pid']
|
|
527
|
-
|
|
528
|
-
ensure
|
|
529
|
-
d.run(start: false, shutdown: true)
|
|
530
535
|
end
|
|
531
536
|
|
|
532
537
|
# child process exits per 3 lines
|
|
@@ -597,8 +602,8 @@ class ExecFilterOutputTest < Test::Unit::TestCase
|
|
|
597
602
|
# the number of pids should be same with number of child processes
|
|
598
603
|
assert_equal 2, pid_list.size
|
|
599
604
|
logs = d.instance.log.out.logs
|
|
600
|
-
assert_equal 2, logs.
|
|
601
|
-
assert_equal 2, logs.
|
|
605
|
+
assert_equal 2, logs.count { |l| l.include?('child process exits with error code') }
|
|
606
|
+
assert_equal 2, logs.count { |l| l.include?('respawning child process') }
|
|
602
607
|
|
|
603
608
|
ensure
|
|
604
609
|
d.run(start: false, shutdown: true)
|
|
@@ -130,7 +130,7 @@ class FileOutputTest < Test::Unit::TestCase
|
|
|
130
130
|
'path' => "#{TMP_DIR}/${tag}/${type}/conf_test.%Y%m%d.%H%M.log",
|
|
131
131
|
'add_path_suffix' => 'false',
|
|
132
132
|
'append' => "true",
|
|
133
|
-
'symlink_path' => "#{TMP_DIR}/conf_test.current.log",
|
|
133
|
+
'symlink_path' => "#{TMP_DIR}/${tag}/conf_test.current.log",
|
|
134
134
|
'compress' => 'gzip',
|
|
135
135
|
'recompress' => 'true',
|
|
136
136
|
}, [
|
|
@@ -183,6 +183,26 @@ class FileOutputTest < Test::Unit::TestCase
|
|
|
183
183
|
Fluent::Test::Driver::Output.new(Fluent::Plugin::NullOutput).configure(conf)
|
|
184
184
|
end
|
|
185
185
|
end
|
|
186
|
+
|
|
187
|
+
test 'warning for symlink_path not including correct placeholders corresponding to chunk keys' do
|
|
188
|
+
omit "Windows doesn't support symlink" if Fluent.windows?
|
|
189
|
+
conf = config_element('match', '**', {
|
|
190
|
+
'path' => "#{TMP_DIR}/${tag}/${key1}/${key2}/conf_test.%Y%m%d.%H%M.log",
|
|
191
|
+
'symlink_path' => "#{TMP_DIR}/conf_test.current.log",
|
|
192
|
+
}, [
|
|
193
|
+
config_element('buffer', 'time,tag,key1,key2', {
|
|
194
|
+
'@type' => 'file',
|
|
195
|
+
'timekey' => '1d',
|
|
196
|
+
'path' => "#{TMP_DIR}/buf_conf_test",
|
|
197
|
+
}),
|
|
198
|
+
])
|
|
199
|
+
assert_nothing_raised do
|
|
200
|
+
d = create_driver(conf)
|
|
201
|
+
assert do
|
|
202
|
+
d.logs.count { |log| log.include?("multiple chunks are competing for a single symlink_path") } == 2
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
186
206
|
end
|
|
187
207
|
|
|
188
208
|
sub_test_case 'fully configured output' do
|
|
@@ -264,8 +284,8 @@ class FileOutputTest < Test::Unit::TestCase
|
|
|
264
284
|
assert !(Dir.exist?("#{TMP_DIR}/my.data/a"))
|
|
265
285
|
assert !(Dir.exist?("#{TMP_DIR}/your.data/a"))
|
|
266
286
|
buffer_files = Dir.entries("#{TMP_DIR}/buf_full").reject{|e| e =~ /^\.+$/ }
|
|
267
|
-
assert_equal 2, buffer_files.
|
|
268
|
-
assert_equal 2, buffer_files.
|
|
287
|
+
assert_equal 2, buffer_files.count{|n| n.end_with?('.meta') }
|
|
288
|
+
assert_equal 2, buffer_files.count{|n| !n.end_with?('.meta') }
|
|
269
289
|
|
|
270
290
|
m1 = d.instance.metadata('my.data', t1, {"type" => "a"})
|
|
271
291
|
m2 = d.instance.metadata('your.data', t3, {"type" => "a"})
|
|
@@ -314,7 +334,7 @@ class FileOutputTest < Test::Unit::TestCase
|
|
|
314
334
|
assert_equal r5, d.formatted[4]
|
|
315
335
|
|
|
316
336
|
read_gunzip = ->(path){
|
|
317
|
-
File.open(path){ |fio|
|
|
337
|
+
File.open(path, 'rb'){ |fio|
|
|
318
338
|
Zlib::GzipReader.new(StringIO.new(fio.read)).read
|
|
319
339
|
}
|
|
320
340
|
}
|
|
@@ -12,7 +12,8 @@ class ForwardOutputTest < Test::Unit::TestCase
|
|
|
12
12
|
FileUtils.rm_rf(TMP_DIR)
|
|
13
13
|
FileUtils.mkdir_p(TMP_DIR)
|
|
14
14
|
@d = nil
|
|
15
|
-
|
|
15
|
+
# forward plugin uses TCP and UDP sockets on the same port number
|
|
16
|
+
@target_port = unused_port(protocol: :all)
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def teardown
|
|
@@ -156,7 +157,14 @@ EOL
|
|
|
156
157
|
normal_conf = config_element('match', '**', {}, [
|
|
157
158
|
config_element('server', '', {'name' => 'test', 'host' => 'unexisting.yaaaaaaaaaaaaaay.host.example.com'})
|
|
158
159
|
])
|
|
159
|
-
|
|
160
|
+
|
|
161
|
+
if Socket.const_defined?(:ResolutionError) # as of Ruby 3.3
|
|
162
|
+
error_class = Socket::ResolutionError
|
|
163
|
+
else
|
|
164
|
+
error_class = SocketError
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
assert_raise error_class do
|
|
160
168
|
create_driver(normal_conf)
|
|
161
169
|
end
|
|
162
170
|
|
|
@@ -165,7 +173,7 @@ EOL
|
|
|
165
173
|
])
|
|
166
174
|
@d = d = create_driver(conf)
|
|
167
175
|
expected_log = "failed to resolve node name when configured"
|
|
168
|
-
expected_detail =
|
|
176
|
+
expected_detail = "server=\"test\" error_class=#{error_class.name}"
|
|
169
177
|
logs = d.logs
|
|
170
178
|
assert{ logs.any?{|log| log.include?(expected_log) && log.include?(expected_detail) } }
|
|
171
179
|
end
|
|
@@ -603,7 +611,6 @@ EOL
|
|
|
603
611
|
|
|
604
612
|
@d = d = create_driver(config + %[
|
|
605
613
|
require_ack_response true
|
|
606
|
-
ack_response_timeout 1s
|
|
607
614
|
<buffer tag>
|
|
608
615
|
flush_mode immediate
|
|
609
616
|
retry_type periodic
|
|
@@ -651,7 +658,6 @@ EOL
|
|
|
651
658
|
|
|
652
659
|
@d = d = create_driver(config + %[
|
|
653
660
|
require_ack_response true
|
|
654
|
-
ack_response_timeout 10s
|
|
655
661
|
<buffer tag>
|
|
656
662
|
flush_mode immediate
|
|
657
663
|
retry_type periodic
|
|
@@ -1241,27 +1247,22 @@ EOL
|
|
|
1241
1247
|
target_input_driver = create_target_input_driver(conf: target_config)
|
|
1242
1248
|
output_conf = config
|
|
1243
1249
|
d = create_driver(output_conf)
|
|
1244
|
-
d.instance_start
|
|
1245
1250
|
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
) { |sock| mock(sock).close.once; sock }.twice
|
|
1251
|
+
chunk = Fluent::Plugin::Buffer::MemoryChunk.new(Fluent::Plugin::Buffer::Metadata.new(nil, nil, nil))
|
|
1252
|
+
mock.proxy(d.instance).socket_create_tcp(TARGET_HOST, @target_port,
|
|
1253
|
+
linger_timeout: anything,
|
|
1254
|
+
send_timeout: anything,
|
|
1255
|
+
recv_timeout: anything,
|
|
1256
|
+
connect_timeout: anything
|
|
1257
|
+
) { |sock| mock(sock).close.once; sock }.twice
|
|
1254
1258
|
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
end
|
|
1259
|
+
target_input_driver.run(timeout: 15) do
|
|
1260
|
+
d.run do
|
|
1261
|
+
node = d.instance.nodes.first
|
|
1262
|
+
2.times do
|
|
1263
|
+
node.send_data('test', chunk) rescue nil
|
|
1261
1264
|
end
|
|
1262
1265
|
end
|
|
1263
|
-
ensure
|
|
1264
|
-
d.instance_shutdown
|
|
1265
1266
|
end
|
|
1266
1267
|
end
|
|
1267
1268
|
|
|
@@ -1275,7 +1276,6 @@ EOL
|
|
|
1275
1276
|
port #{@target_port}
|
|
1276
1277
|
</server>
|
|
1277
1278
|
])
|
|
1278
|
-
d.instance_start
|
|
1279
1279
|
assert_nothing_raised { d.run }
|
|
1280
1280
|
end
|
|
1281
1281
|
|
|
@@ -1287,33 +1287,28 @@ EOL
|
|
|
1287
1287
|
keepalive_timeout 2
|
|
1288
1288
|
]
|
|
1289
1289
|
d = create_driver(output_conf)
|
|
1290
|
-
d.instance_start
|
|
1291
1290
|
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
) { |sock| mock(sock).close.once; sock }.once
|
|
1291
|
+
chunk = Fluent::Plugin::Buffer::MemoryChunk.new(Fluent::Plugin::Buffer::Metadata.new(nil, nil, nil))
|
|
1292
|
+
mock.proxy(d.instance).socket_create_tcp(TARGET_HOST, @target_port,
|
|
1293
|
+
linger_timeout: anything,
|
|
1294
|
+
send_timeout: anything,
|
|
1295
|
+
recv_timeout: anything,
|
|
1296
|
+
connect_timeout: anything
|
|
1297
|
+
) { |sock| mock(sock).close.once; sock }.once
|
|
1300
1298
|
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
end
|
|
1299
|
+
target_input_driver.run(timeout: 15) do
|
|
1300
|
+
d.run do
|
|
1301
|
+
node = d.instance.nodes.first
|
|
1302
|
+
2.times do
|
|
1303
|
+
node.send_data('test', chunk) rescue nil
|
|
1307
1304
|
end
|
|
1308
1305
|
end
|
|
1309
|
-
ensure
|
|
1310
|
-
d.instance_shutdown
|
|
1311
1306
|
end
|
|
1312
1307
|
end
|
|
1313
1308
|
|
|
1314
1309
|
test 'create timer of purging obsolete sockets' do
|
|
1315
1310
|
output_conf = config + %[keepalive true]
|
|
1316
|
-
d = create_driver(output_conf)
|
|
1311
|
+
@d = d = create_driver(output_conf)
|
|
1317
1312
|
|
|
1318
1313
|
mock(d.instance).timer_execute(:out_forward_heartbeat_request, 1).once
|
|
1319
1314
|
mock(d.instance).timer_execute(:out_forward_keep_alived_socket_watcher, 5).once
|
|
@@ -1329,7 +1324,6 @@ EOL
|
|
|
1329
1324
|
keepalive_timeout 2
|
|
1330
1325
|
]
|
|
1331
1326
|
d = create_driver(output_conf)
|
|
1332
|
-
d.instance_start
|
|
1333
1327
|
|
|
1334
1328
|
chunk = Fluent::Plugin::Buffer::MemoryChunk.new(Fluent::Plugin::Buffer::Metadata.new(nil, nil, nil))
|
|
1335
1329
|
mock.proxy(d.instance).socket_create_tcp(TARGET_HOST, @target_port,
|
data/test/plugin/test_output.rb
CHANGED
|
@@ -447,25 +447,25 @@ class OutputTest < Test::Unit::TestCase
|
|
|
447
447
|
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
|
448
448
|
validators = @i.placeholder_validators(:path, "/my/path/${tag}/${username}/file.%Y%m%d_%H%M.log")
|
|
449
449
|
assert_equal 3, validators.size
|
|
450
|
-
assert_equal 1, validators.
|
|
451
|
-
assert_equal 1, validators.
|
|
452
|
-
assert_equal 1, validators.
|
|
450
|
+
assert_equal 1, validators.count(&:time?)
|
|
451
|
+
assert_equal 1, validators.count(&:tag?)
|
|
452
|
+
assert_equal 1, validators.count(&:keys?)
|
|
453
453
|
end
|
|
454
454
|
|
|
455
455
|
test 'returns validators for time, tag and keys when a plugin is configured with these keys even if a template does not have placeholders' do
|
|
456
456
|
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,username', {'timekey' => 60})]))
|
|
457
457
|
validators = @i.placeholder_validators(:path, "/my/path/file.log")
|
|
458
458
|
assert_equal 3, validators.size
|
|
459
|
-
assert_equal 1, validators.
|
|
460
|
-
assert_equal 1, validators.
|
|
461
|
-
assert_equal 1, validators.
|
|
459
|
+
assert_equal 1, validators.count(&:time?)
|
|
460
|
+
assert_equal 1, validators.count(&:tag?)
|
|
461
|
+
assert_equal 1, validators.count(&:keys?)
|
|
462
462
|
end
|
|
463
463
|
|
|
464
464
|
test 'returns a validator for time if a template has timestamp placeholders' do
|
|
465
465
|
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
|
466
466
|
validators = @i.placeholder_validators(:path, "/my/path/file.%Y-%m-%d.log")
|
|
467
467
|
assert_equal 1, validators.size
|
|
468
|
-
assert_equal 1, validators.
|
|
468
|
+
assert_equal 1, validators.count(&:time?)
|
|
469
469
|
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.%Y-%m-%d.log' has timestamp placeholders, but chunk key 'time' is not configured") do
|
|
470
470
|
validators.first.validate!
|
|
471
471
|
end
|
|
@@ -475,7 +475,7 @@ class OutputTest < Test::Unit::TestCase
|
|
|
475
475
|
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {'timekey' => '30'})]))
|
|
476
476
|
validators = @i.placeholder_validators(:path, "/my/path/to/file.log")
|
|
477
477
|
assert_equal 1, validators.size
|
|
478
|
-
assert_equal 1, validators.
|
|
478
|
+
assert_equal 1, validators.count(&:time?)
|
|
479
479
|
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/to/file.log' doesn't have timestamp placeholders for timekey 30") do
|
|
480
480
|
validators.first.validate!
|
|
481
481
|
end
|
|
@@ -485,7 +485,7 @@ class OutputTest < Test::Unit::TestCase
|
|
|
485
485
|
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
|
486
486
|
validators = @i.placeholder_validators(:path, "/my/path/${tag}/file.log")
|
|
487
487
|
assert_equal 1, validators.size
|
|
488
|
-
assert_equal 1, validators.
|
|
488
|
+
assert_equal 1, validators.count(&:tag?)
|
|
489
489
|
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${tag}/file.log' has tag placeholders, but chunk key 'tag' is not configured") do
|
|
490
490
|
validators.first.validate!
|
|
491
491
|
end
|
|
@@ -495,7 +495,7 @@ class OutputTest < Test::Unit::TestCase
|
|
|
495
495
|
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag')]))
|
|
496
496
|
validators = @i.placeholder_validators(:path, "/my/path/file.log")
|
|
497
497
|
assert_equal 1, validators.size
|
|
498
|
-
assert_equal 1, validators.
|
|
498
|
+
assert_equal 1, validators.count(&:tag?)
|
|
499
499
|
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have tag placeholder") do
|
|
500
500
|
validators.first.validate!
|
|
501
501
|
end
|
|
@@ -505,7 +505,7 @@ class OutputTest < Test::Unit::TestCase
|
|
|
505
505
|
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
|
506
506
|
validators = @i.placeholder_validators(:path, "/my/path/${username}/file.${group}.log")
|
|
507
507
|
assert_equal 1, validators.size
|
|
508
|
-
assert_equal 1, validators.
|
|
508
|
+
assert_equal 1, validators.count(&:keys?)
|
|
509
509
|
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${username}/file.${group}.log' has placeholders, but chunk keys doesn't have keys group,username") do
|
|
510
510
|
validators.first.validate!
|
|
511
511
|
end
|
|
@@ -515,7 +515,7 @@ class OutputTest < Test::Unit::TestCase
|
|
|
515
515
|
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,group')]))
|
|
516
516
|
validators = @i.placeholder_validators(:path, "/my/path/file.log")
|
|
517
517
|
assert_equal 1, validators.size
|
|
518
|
-
assert_equal 1, validators.
|
|
518
|
+
assert_equal 1, validators.count(&:keys?)
|
|
519
519
|
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have enough placeholders for keys group,username") do
|
|
520
520
|
validators.first.validate!
|
|
521
521
|
end
|