fluentd 1.12.4-x86-mingw32 → 1.13.3-x86-mingw32
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/ISSUE_TEMPLATE/bug_report.yaml +69 -0
- data/.github/ISSUE_TEMPLATE/feature_request.yaml +38 -0
- data/.github/workflows/linux-test.yaml +1 -1
- data/.github/workflows/windows-test.yaml +14 -3
- data/.gitlab-ci.yml +0 -22
- data/CHANGELOG.md +129 -0
- data/CONTRIBUTING.md +2 -2
- data/MAINTAINERS.md +1 -1
- data/README.md +3 -3
- data/bin/fluentd +8 -1
- data/example/counter.conf +1 -1
- data/example/v0_12_filter.conf +2 -2
- data/fluentd.gemspec +1 -1
- data/lib/fluent/command/cat.rb +19 -3
- data/lib/fluent/command/fluentd.rb +1 -2
- data/lib/fluent/command/plugin_generator.rb +15 -5
- data/lib/fluent/config.rb +1 -1
- data/lib/fluent/config/section.rb +5 -0
- data/lib/fluent/config/types.rb +15 -0
- data/lib/fluent/config/v1_parser.rb +3 -2
- data/lib/fluent/env.rb +2 -1
- data/lib/fluent/log.rb +1 -0
- data/lib/fluent/oj_options.rb +62 -0
- data/lib/fluent/plugin/file_wrapper.rb +35 -4
- data/lib/fluent/plugin/formatter.rb +1 -0
- data/lib/fluent/plugin/formatter_json.rb +9 -7
- data/lib/fluent/plugin/in_http.rb +10 -0
- data/lib/fluent/plugin/in_tail.rb +159 -41
- data/lib/fluent/plugin/in_tail/position_file.rb +20 -18
- data/lib/fluent/plugin/out_forward.rb +14 -33
- data/lib/fluent/plugin/parser_json.rb +2 -3
- data/lib/fluent/plugin/service_discovery.rb +0 -15
- data/lib/fluent/plugin_helper/http_server/router.rb +1 -1
- data/lib/fluent/plugin_helper/service_discovery.rb +39 -1
- data/lib/fluent/plugin_helper/service_discovery/manager.rb +11 -5
- data/lib/fluent/supervisor.rb +15 -0
- data/lib/fluent/system_config.rb +14 -0
- data/lib/fluent/test/driver/storage.rb +30 -0
- data/lib/fluent/version.rb +1 -1
- data/templates/new_gem/lib/fluent/plugin/storage.rb.erb +40 -0
- data/templates/new_gem/test/plugin/test_storage.rb.erb +18 -0
- data/test/command/test_cat.rb +99 -0
- data/test/command/test_plugin_generator.rb +2 -1
- data/test/config/test_section.rb +9 -0
- data/test/config/test_system_config.rb +46 -0
- data/test/config/test_types.rb +7 -0
- data/test/plugin/in_tail/test_io_handler.rb +4 -4
- data/test/plugin/in_tail/test_position_file.rb +23 -5
- data/test/plugin/test_file_wrapper.rb +22 -1
- data/test/plugin/test_in_forward.rb +59 -83
- data/test/plugin/test_in_http.rb +58 -40
- data/test/plugin/test_in_syslog.rb +66 -56
- data/test/plugin/test_in_tail.rb +341 -1
- data/test/plugin/test_in_tcp.rb +45 -32
- data/test/plugin/test_in_udp.rb +47 -33
- data/test/plugin/test_out_forward.rb +114 -95
- data/test/plugin/test_out_stream.rb +18 -8
- data/test/plugin_helper/http_server/test_route.rb +1 -1
- data/test/plugin_helper/test_child_process.rb +1 -1
- data/test/plugin_helper/test_http_server_helper.rb +33 -26
- data/test/plugin_helper/test_server.rb +137 -138
- data/test/plugin_helper/test_service_discovery.rb +74 -14
- data/test/plugin_helper/test_socket.rb +16 -9
- data/test/test_config.rb +2 -1
- data/test/test_event_time.rb +2 -2
- data/test/test_oj_options.rb +55 -0
- data/test/test_supervisor.rb +35 -0
- metadata +15 -7
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -23
data/test/plugin/test_in_tail.rb
CHANGED
@@ -109,6 +109,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
109
109
|
"refresh_interval" => "1s",
|
110
110
|
"read_from_head" => "true",
|
111
111
|
"format" => "none",
|
112
|
+
"rotate_wait" => "1s",
|
112
113
|
"follow_inodes" => "true"
|
113
114
|
})
|
114
115
|
SINGLE_LINE_CONFIG = config_element("", "", { "format" => "/(?<message>.*)/" })
|
@@ -156,6 +157,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
156
157
|
assert_equal 2, d.instance.rotate_wait
|
157
158
|
assert_equal "#{TMP_DIR}/tail.pos", d.instance.pos_file
|
158
159
|
assert_equal 1000, d.instance.read_lines_limit
|
160
|
+
assert_equal -1, d.instance.read_bytes_limit_per_second
|
159
161
|
assert_equal false, d.instance.ignore_repeated_permission_error
|
160
162
|
assert_nothing_raised do
|
161
163
|
d.instance.have_read_capability?
|
@@ -195,6 +197,22 @@ class TailInputTest < Test::Unit::TestCase
|
|
195
197
|
end
|
196
198
|
end
|
197
199
|
|
200
|
+
sub_test_case "log throttling per file" do
|
201
|
+
test "w/o watcher timer is invalid" do
|
202
|
+
conf = CONFIG_ENABLE_WATCH_TIMER + config_element("ROOT", "", {"read_bytes_limit_per_second" => "8k"})
|
203
|
+
assert_raise(Fluent::ConfigError) do
|
204
|
+
create_driver(conf)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
test "valid" do
|
209
|
+
conf = config_element("ROOT", "", {"read_bytes_limit_per_second" => "8k"})
|
210
|
+
assert_raise(Fluent::ConfigError) do
|
211
|
+
create_driver(conf)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
198
216
|
test "both enable_watch_timer and enable_stat_watcher are false" do
|
199
217
|
assert_raise(Fluent::ConfigError) do
|
200
218
|
create_driver(CONFIG_ENABLE_WATCH_TIMER + CONFIG_DISABLE_STAT_WATCHER + PARSE_SINGLE_LINE_CONFIG)
|
@@ -323,6 +341,209 @@ class TailInputTest < Test::Unit::TestCase
|
|
323
341
|
assert num_events <= d.emit_count
|
324
342
|
end
|
325
343
|
|
344
|
+
sub_test_case "log throttling per file" do
|
345
|
+
teardown do
|
346
|
+
cleanup_file("#{TMP_DIR}/tail.txt")
|
347
|
+
end
|
348
|
+
|
349
|
+
sub_test_case "reads_bytes_per_second w/o throttled" do
|
350
|
+
data("flat 8192 bytes, 2 events" => [:flat, 100, 8192, 2],
|
351
|
+
"flat 8192 bytes, 2 events w/o stat watcher" => [:flat_without_stat, 100, 8192, 2],
|
352
|
+
"flat #{8192*10} bytes, 20 events" => [:flat, 100, (8192 * 10), 20],
|
353
|
+
"flat #{8192*10} bytes, 20 events w/o stat watcher" => [:flat_without_stat, 100, (8192 * 10), 20],
|
354
|
+
"parse #{8192*4} bytes, 8 events" => [:parse, 100, (8192 * 4), 8],
|
355
|
+
"parse #{8192*4} bytes, 8 events w/o stat watcher" => [:parse_without_stat, 100, (8192 * 4), 8],
|
356
|
+
"parse #{8192*10} bytes, 20 events" => [:parse, 100, (8192 * 10), 20],
|
357
|
+
"parse #{8192*10} bytes, 20 events w/o stat watcher" => [:parse_without_stat, 100, (8192 * 10), 20],
|
358
|
+
"flat 8k bytes with unit, 2 events" => [:flat, 100, "8k", 2])
|
359
|
+
def test_emit_with_read_bytes_limit_per_second(data)
|
360
|
+
config_style, limit, limit_bytes, num_events = data
|
361
|
+
case config_style
|
362
|
+
when :flat
|
363
|
+
config = CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes })
|
364
|
+
when :parse
|
365
|
+
config = CONFIG_READ_FROM_HEAD + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes }) + PARSE_SINGLE_LINE_CONFIG
|
366
|
+
when :flat_without_stat
|
367
|
+
config = CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG + CONFIG_DISABLE_STAT_WATCHER + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes })
|
368
|
+
when :parse_without_stat
|
369
|
+
config = CONFIG_READ_FROM_HEAD + CONFIG_DISABLE_STAT_WATCHER + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes }) + PARSE_SINGLE_LINE_CONFIG
|
370
|
+
end
|
371
|
+
|
372
|
+
msg = 'test' * 2000 # in_tail reads 8192 bytes at once.
|
373
|
+
start_time = Fluent::Clock.now
|
374
|
+
|
375
|
+
d = create_driver(config)
|
376
|
+
d.run(expect_emits: 2) do
|
377
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
|
378
|
+
100.times do
|
379
|
+
f.puts msg
|
380
|
+
end
|
381
|
+
}
|
382
|
+
end
|
383
|
+
|
384
|
+
assert_true(Fluent::Clock.now - start_time > 1)
|
385
|
+
assert_equal(num_events.times.map { {"message" => msg} },
|
386
|
+
d.events.collect { |event| event[2] })
|
387
|
+
end
|
388
|
+
|
389
|
+
def test_read_bytes_limit_precede_read_lines_limit
|
390
|
+
config = CONFIG_READ_FROM_HEAD +
|
391
|
+
SINGLE_LINE_CONFIG +
|
392
|
+
config_element("", "", {
|
393
|
+
"read_lines_limit" => 1000,
|
394
|
+
"read_bytes_limit_per_second" => 8192
|
395
|
+
})
|
396
|
+
msg = 'abc'
|
397
|
+
start_time = Fluent::Clock.now
|
398
|
+
d = create_driver(config)
|
399
|
+
d.run(expect_emits: 2) do
|
400
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
|
401
|
+
8000.times do
|
402
|
+
f.puts msg
|
403
|
+
end
|
404
|
+
}
|
405
|
+
end
|
406
|
+
|
407
|
+
assert_true(Fluent::Clock.now - start_time > 1)
|
408
|
+
assert_equal(4096.times.map { {"message" => msg} },
|
409
|
+
d.events.collect { |event| event[2] })
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
sub_test_case "reads_bytes_per_second w/ throttled already" do
|
414
|
+
data("flat 8192 bytes" => [:flat, 100, 8192],
|
415
|
+
"parse 8192 bytes" => [:parse, 100, 8192])
|
416
|
+
def test_emit_with_read_bytes_limit_per_second(data)
|
417
|
+
config_style, limit, limit_bytes = data
|
418
|
+
case config_style
|
419
|
+
when :flat
|
420
|
+
config = CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes })
|
421
|
+
when :parse
|
422
|
+
config = CONFIG_READ_FROM_HEAD + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes }) + PARSE_SINGLE_LINE_CONFIG
|
423
|
+
end
|
424
|
+
d = create_driver(config)
|
425
|
+
msg = 'test' * 2000 # in_tail reads 8192 bytes at once.
|
426
|
+
|
427
|
+
mock.proxy(d.instance).io_handler(anything, anything) do |io_handler|
|
428
|
+
require 'fluent/config/types'
|
429
|
+
limit_bytes_value = Fluent::Config.size_value(limit_bytes)
|
430
|
+
io_handler.instance_variable_set(:@number_bytes_read, limit_bytes_value)
|
431
|
+
if Fluent.linux?
|
432
|
+
mock.proxy(io_handler).handle_notify.at_least(5)
|
433
|
+
else
|
434
|
+
mock.proxy(io_handler).handle_notify.twice
|
435
|
+
end
|
436
|
+
io_handler
|
437
|
+
end
|
438
|
+
|
439
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") do |f|
|
440
|
+
100.times do
|
441
|
+
f.puts msg
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
# We should not do shutdown here due to hard timeout.
|
446
|
+
d.run do
|
447
|
+
start_time = Fluent::Clock.now
|
448
|
+
while Fluent::Clock.now - start_time < 0.8 do
|
449
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") do |f|
|
450
|
+
f.puts msg
|
451
|
+
f.flush
|
452
|
+
end
|
453
|
+
sleep 0.05
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
assert_equal([], d.events)
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
sub_test_case "EOF with reads_bytes_per_second" do
|
462
|
+
def test_longer_than_rotate_wait
|
463
|
+
limit_bytes = 8192
|
464
|
+
num_lines = 1024 * 3
|
465
|
+
msg = "08bytes"
|
466
|
+
|
467
|
+
File.open("#{TMP_DIR}/tail.txt", "wb") do |f|
|
468
|
+
f.write("#{msg}\n" * num_lines)
|
469
|
+
end
|
470
|
+
|
471
|
+
config = CONFIG_READ_FROM_HEAD +
|
472
|
+
SINGLE_LINE_CONFIG +
|
473
|
+
config_element("", "", {
|
474
|
+
"read_bytes_limit_per_second" => limit_bytes,
|
475
|
+
"rotate_wait" => 0.1,
|
476
|
+
"refresh_interval" => 0.5,
|
477
|
+
})
|
478
|
+
|
479
|
+
rotated = false
|
480
|
+
d = create_driver(config)
|
481
|
+
d.run(timeout: 10) do
|
482
|
+
while d.events.size < num_lines do
|
483
|
+
if d.events.size > 0 && !rotated
|
484
|
+
cleanup_file("#{TMP_DIR}/tail.txt")
|
485
|
+
FileUtils.touch("#{TMP_DIR}/tail.txt")
|
486
|
+
rotated = true
|
487
|
+
end
|
488
|
+
sleep 0.3
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
assert_equal(num_lines,
|
493
|
+
d.events.count do |event|
|
494
|
+
event[2]["message"] == msg
|
495
|
+
end)
|
496
|
+
end
|
497
|
+
|
498
|
+
def test_shorter_than_rotate_wait
|
499
|
+
limit_bytes = 8192
|
500
|
+
num_lines = 1024 * 2
|
501
|
+
msg = "08bytes"
|
502
|
+
|
503
|
+
File.open("#{TMP_DIR}/tail.txt", "wb") do |f|
|
504
|
+
f.write("#{msg}\n" * num_lines)
|
505
|
+
end
|
506
|
+
|
507
|
+
config = CONFIG_READ_FROM_HEAD +
|
508
|
+
SINGLE_LINE_CONFIG +
|
509
|
+
config_element("", "", {
|
510
|
+
"read_bytes_limit_per_second" => limit_bytes,
|
511
|
+
"rotate_wait" => 2,
|
512
|
+
"refresh_interval" => 0.5,
|
513
|
+
})
|
514
|
+
|
515
|
+
start_time = Fluent::Clock.now
|
516
|
+
rotated = false
|
517
|
+
detached = false
|
518
|
+
d = create_driver(config)
|
519
|
+
mock.proxy(d.instance).setup_watcher(anything, anything) do |tw|
|
520
|
+
mock.proxy(tw).detach(anything) do |v|
|
521
|
+
detached = true
|
522
|
+
v
|
523
|
+
end
|
524
|
+
tw
|
525
|
+
end.twice
|
526
|
+
|
527
|
+
d.run(timeout: 10) do
|
528
|
+
until detached do
|
529
|
+
if d.events.size > 0 && !rotated
|
530
|
+
cleanup_file("#{TMP_DIR}/tail.txt")
|
531
|
+
FileUtils.touch("#{TMP_DIR}/tail.txt")
|
532
|
+
rotated = true
|
533
|
+
end
|
534
|
+
sleep 0.3
|
535
|
+
end
|
536
|
+
end
|
537
|
+
|
538
|
+
assert_true(Fluent::Clock.now - start_time > 2)
|
539
|
+
assert_equal(num_lines,
|
540
|
+
d.events.count do |event|
|
541
|
+
event[2]["message"] == msg
|
542
|
+
end)
|
543
|
+
end
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
326
547
|
data(flat: CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG,
|
327
548
|
parse: CONFIG_READ_FROM_HEAD + PARSE_SINGLE_LINE_CONFIG)
|
328
549
|
def test_emit_with_read_from_head(data)
|
@@ -1764,6 +1985,49 @@ class TailInputTest < Test::Unit::TestCase
|
|
1764
1985
|
assert_equal({"message" => "test4"}, events[3][2])
|
1765
1986
|
d.instance_shutdown
|
1766
1987
|
end
|
1988
|
+
|
1989
|
+
# issue #3464
|
1990
|
+
def test_should_replace_target_info
|
1991
|
+
File.open("#{TMP_DIR}/tail.txt", "wb") {|f|
|
1992
|
+
f.puts "test1\n"
|
1993
|
+
}
|
1994
|
+
target_info = create_target_info("#{TMP_DIR}/tail.txt")
|
1995
|
+
inodes = []
|
1996
|
+
|
1997
|
+
config = config_element("ROOT", "", {
|
1998
|
+
"path" => "#{TMP_DIR}/tail.txt*",
|
1999
|
+
"pos_file" => "#{TMP_DIR}/tail.pos",
|
2000
|
+
"tag" => "t1",
|
2001
|
+
"refresh_interval" => "60s",
|
2002
|
+
"read_from_head" => "true",
|
2003
|
+
"format" => "none",
|
2004
|
+
"rotate_wait" => "1s",
|
2005
|
+
"follow_inodes" => "true"
|
2006
|
+
})
|
2007
|
+
d = create_driver(config, false)
|
2008
|
+
d.run(timeout: 5) do
|
2009
|
+
while d.events.size < 1 do
|
2010
|
+
sleep 0.1
|
2011
|
+
end
|
2012
|
+
inodes = d.instance.instance_variable_get(:@tails).keys.collect do |key|
|
2013
|
+
key.ino
|
2014
|
+
end
|
2015
|
+
assert_equal([target_info.ino], inodes)
|
2016
|
+
|
2017
|
+
cleanup_file("#{TMP_DIR}/tail.txt")
|
2018
|
+
File.open("#{TMP_DIR}/tail.txt", "wb") {|f| f.puts "test2\n"}
|
2019
|
+
|
2020
|
+
while d.events.size < 2 do
|
2021
|
+
sleep 0.1
|
2022
|
+
end
|
2023
|
+
inodes = d.instance.instance_variable_get(:@tails).keys.collect do |key|
|
2024
|
+
key.ino
|
2025
|
+
end
|
2026
|
+
new_target_info = create_target_info("#{TMP_DIR}/tail.txt")
|
2027
|
+
assert_not_equal(target_info.ino, new_target_info.ino)
|
2028
|
+
assert_equal([new_target_info.ino], inodes)
|
2029
|
+
end
|
2030
|
+
end
|
1767
2031
|
end
|
1768
2032
|
|
1769
2033
|
sub_test_case "tail_path" do
|
@@ -1935,6 +2199,82 @@ class TailInputTest < Test::Unit::TestCase
|
|
1935
2199
|
d.run(shutdown: false) {}
|
1936
2200
|
end
|
1937
2201
|
d.instance_shutdown
|
1938
|
-
assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed with ENOENT. Drop tail watcher for now.\n") })
|
2202
|
+
assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed with Errno::ENOENT. Drop tail watcher for now.\n") })
|
2203
|
+
end
|
2204
|
+
|
2205
|
+
def test_EACCES_error_after_setup_watcher
|
2206
|
+
omit "Cannot test with root user" if Process::UID.eid == 0
|
2207
|
+
path = "#{TMP_DIR}/noaccess/tail.txt"
|
2208
|
+
begin
|
2209
|
+
FileUtils.mkdir_p("#{TMP_DIR}/noaccess")
|
2210
|
+
FileUtils.chmod(0755, "#{TMP_DIR}/noaccess")
|
2211
|
+
FileUtils.touch(path)
|
2212
|
+
config = config_element('', '', {
|
2213
|
+
'tag' => "tail",
|
2214
|
+
'path' => path,
|
2215
|
+
'format' => 'none',
|
2216
|
+
})
|
2217
|
+
d = create_driver(config, false)
|
2218
|
+
mock.proxy(d.instance).setup_watcher(anything, anything) do |tw|
|
2219
|
+
FileUtils.chmod(0000, "#{TMP_DIR}/noaccess")
|
2220
|
+
tw
|
2221
|
+
end
|
2222
|
+
assert_nothing_raised do
|
2223
|
+
d.run(shutdown: false) {}
|
2224
|
+
end
|
2225
|
+
d.instance_shutdown
|
2226
|
+
assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed with Errno::EACCES. Drop tail watcher for now.\n") })
|
2227
|
+
end
|
2228
|
+
ensure
|
2229
|
+
if File.exist?("#{TMP_DIR}/noaccess")
|
2230
|
+
FileUtils.chmod(0755, "#{TMP_DIR}/noaccess")
|
2231
|
+
FileUtils.rm_rf("#{TMP_DIR}/noaccess")
|
2232
|
+
end
|
2233
|
+
end unless Fluent.windows?
|
2234
|
+
|
2235
|
+
def test_EACCES
|
2236
|
+
path = "#{TMP_DIR}/tail.txt"
|
2237
|
+
FileUtils.touch(path)
|
2238
|
+
config = config_element('', '', {
|
2239
|
+
'format' => 'none',
|
2240
|
+
})
|
2241
|
+
d = create_driver(config)
|
2242
|
+
mock.proxy(Fluent::FileWrapper).stat(path) do |stat|
|
2243
|
+
raise Errno::EACCES
|
2244
|
+
end.at_least(1)
|
2245
|
+
assert_nothing_raised do
|
2246
|
+
d.run(shutdown: false) {}
|
2247
|
+
end
|
2248
|
+
d.instance_shutdown
|
2249
|
+
assert($log.out.logs.any?{|log| log.include?("expand_paths: stat() for #{path} failed with Errno::EACCES. Skip file.\n") })
|
2250
|
+
end
|
2251
|
+
|
2252
|
+
def test_shutdown_timeout
|
2253
|
+
path = "#{TMP_DIR}/tail.txt"
|
2254
|
+
File.open("#{TMP_DIR}/tail.txt", "wb") do |f|
|
2255
|
+
(1024 * 1024 * 5).times do
|
2256
|
+
f.puts "{\"test\":\"fizzbuzz\"}"
|
2257
|
+
end
|
2258
|
+
end
|
2259
|
+
|
2260
|
+
config =
|
2261
|
+
CONFIG_READ_FROM_HEAD +
|
2262
|
+
config_element('', '', {
|
2263
|
+
'format' => 'json',
|
2264
|
+
'skip_refresh_on_startup' => true,
|
2265
|
+
})
|
2266
|
+
d = create_driver(config)
|
2267
|
+
mock.proxy(d.instance).io_handler(anything, anything) do |io_handler|
|
2268
|
+
io_handler.shutdown_timeout = 0.5
|
2269
|
+
io_handler
|
2270
|
+
end
|
2271
|
+
|
2272
|
+
start_time = Fluent::Clock.now
|
2273
|
+
assert_nothing_raised do
|
2274
|
+
d.run(expect_emits: 1)
|
2275
|
+
end
|
2276
|
+
|
2277
|
+
elapsed = Fluent::Clock.now - start_time
|
2278
|
+
assert_true(elapsed > 0.5 && elapsed < 2.5)
|
1939
2279
|
end
|
1940
2280
|
end
|
data/test/plugin/test_in_tcp.rb
CHANGED
@@ -5,21 +5,33 @@ 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
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
11
|
+
def teardown
|
12
|
+
@port = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def base_config
|
16
|
+
%[
|
17
|
+
port #{@port}
|
18
|
+
tag tcp
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
def ipv4_config
|
23
|
+
base_config + %[
|
24
|
+
bind 127.0.0.1
|
25
|
+
format none
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
def ipv6_config
|
30
|
+
base_config + %[
|
31
|
+
bind ::1
|
32
|
+
format none
|
33
|
+
]
|
34
|
+
end
|
23
35
|
|
24
36
|
def create_driver(conf)
|
25
37
|
Fluent::Test::Driver::Input.new(Fluent::Plugin::TcpInput).configure(conf)
|
@@ -35,22 +47,23 @@ class TcpInputTest < Test::Unit::TestCase
|
|
35
47
|
|
36
48
|
|
37
49
|
data(
|
38
|
-
'ipv4' => [
|
39
|
-
'ipv6' => [
|
50
|
+
'ipv4' => ['127.0.0.1', :ipv4],
|
51
|
+
'ipv6' => ['::1', :ipv6],
|
40
52
|
)
|
41
53
|
test 'configure' do |data|
|
42
|
-
|
54
|
+
bind, protocol = data
|
55
|
+
conf = send("#{protocol}_config")
|
43
56
|
omit "IPv6 is not supported on this environment" if protocol == :ipv6 && !ipv6_enabled?
|
44
57
|
|
45
58
|
d = create_driver(conf)
|
46
|
-
assert_equal
|
59
|
+
assert_equal @port, d.instance.port
|
47
60
|
assert_equal bind, d.instance.bind
|
48
61
|
assert_equal "\n", d.instance.delimiter
|
49
62
|
end
|
50
63
|
|
51
64
|
test ' configure w/o parse section' do
|
52
65
|
assert_raise(Fluent::ConfigError.new("<parse> section is required.")) {
|
53
|
-
create_driver(
|
66
|
+
create_driver(base_config)
|
54
67
|
}
|
55
68
|
end
|
56
69
|
|
@@ -82,10 +95,10 @@ class TcpInputTest < Test::Unit::TestCase
|
|
82
95
|
payloads = data['payloads']
|
83
96
|
expecteds = data['expecteds']
|
84
97
|
|
85
|
-
d = create_driver(
|
98
|
+
d = create_driver(base_config + "format #{format}")
|
86
99
|
d.run(expect_records: 2) do
|
87
100
|
payloads.each do |payload|
|
88
|
-
create_tcp_socket('127.0.0.1',
|
101
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
89
102
|
sock.send(payload, 0)
|
90
103
|
end
|
91
104
|
end
|
@@ -105,9 +118,9 @@ class TcpInputTest < Test::Unit::TestCase
|
|
105
118
|
payloads = data['payloads']
|
106
119
|
expecteds = data['expecteds']
|
107
120
|
|
108
|
-
d = create_driver(
|
121
|
+
d = create_driver(base_config + "format #{format}")
|
109
122
|
d.run(expect_records: 2) do
|
110
|
-
create_tcp_socket('127.0.0.1',
|
123
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
111
124
|
payloads.each do |payload|
|
112
125
|
sock.send(payload, 0)
|
113
126
|
end
|
@@ -123,13 +136,13 @@ class TcpInputTest < Test::Unit::TestCase
|
|
123
136
|
end
|
124
137
|
|
125
138
|
test 'source_hostname_key' do
|
126
|
-
d = create_driver(
|
139
|
+
d = create_driver(base_config + %!
|
127
140
|
format none
|
128
141
|
source_hostname_key host
|
129
142
|
!)
|
130
143
|
hostname = nil
|
131
144
|
d.run(expect_records: 1) do
|
132
|
-
create_tcp_socket('127.0.0.1',
|
145
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
133
146
|
sock.do_not_reverse_lookup = false
|
134
147
|
hostname = sock.peeraddr[2]
|
135
148
|
sock.send("test\n", 0)
|
@@ -144,13 +157,13 @@ class TcpInputTest < Test::Unit::TestCase
|
|
144
157
|
end
|
145
158
|
|
146
159
|
test 'source_address_key' do
|
147
|
-
d = create_driver(
|
160
|
+
d = create_driver(base_config + %!
|
148
161
|
format none
|
149
162
|
source_address_key addr
|
150
163
|
!)
|
151
164
|
address = nil
|
152
165
|
d.run(expect_records: 1) do
|
153
|
-
create_tcp_socket('127.0.0.1',
|
166
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
154
167
|
address = sock.peeraddr[3]
|
155
168
|
sock.send("test\n", 0)
|
156
169
|
end
|
@@ -165,7 +178,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
165
178
|
|
166
179
|
sub_test_case '<security>' do
|
167
180
|
test 'accept from allowed client' do
|
168
|
-
d = create_driver(
|
181
|
+
d = create_driver(ipv4_config + %!
|
169
182
|
<security>
|
170
183
|
<client>
|
171
184
|
network 127.0.0.1
|
@@ -173,7 +186,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
173
186
|
</security>
|
174
187
|
!)
|
175
188
|
d.run(expect_records: 1) do
|
176
|
-
create_tcp_socket('127.0.0.1',
|
189
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
177
190
|
sock.send("hello\n", 0)
|
178
191
|
end
|
179
192
|
end
|
@@ -185,7 +198,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
185
198
|
end
|
186
199
|
|
187
200
|
test 'deny from disallowed client' do
|
188
|
-
d = create_driver(
|
201
|
+
d = create_driver(ipv4_config + %!
|
189
202
|
<security>
|
190
203
|
<client>
|
191
204
|
network 200.0.0.0
|
@@ -193,7 +206,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
193
206
|
</security>
|
194
207
|
!)
|
195
208
|
d.run(shutdown: false, expect_records: 1, timeout: 2) do
|
196
|
-
create_tcp_socket('127.0.0.1',
|
209
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
197
210
|
sock.send("hello\n", 0)
|
198
211
|
end
|
199
212
|
end
|
@@ -205,7 +218,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
205
218
|
|
206
219
|
sub_test_case '<extract>' do
|
207
220
|
test 'extract tag from record field' do
|
208
|
-
d = create_driver(
|
221
|
+
d = create_driver(base_config + %!
|
209
222
|
<parse>
|
210
223
|
@type json
|
211
224
|
</parse>
|
@@ -214,7 +227,7 @@ class TcpInputTest < Test::Unit::TestCase
|
|
214
227
|
</extract>
|
215
228
|
!)
|
216
229
|
d.run(expect_records: 1) do
|
217
|
-
create_tcp_socket('127.0.0.1',
|
230
|
+
create_tcp_socket('127.0.0.1', @port) do |sock|
|
218
231
|
data = {'msg' => 'hello', 'tag' => 'helper_test'}
|
219
232
|
sock.send("#{data.to_json}\n", 0)
|
220
233
|
end
|