fluentd 1.12.2-x64-mingw32 → 1.13.2-x64-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 +19 -3
- data/.gitlab-ci.yml +19 -19
- data/CHANGELOG.md +153 -0
- data/CONTRIBUTING.md +2 -2
- data/MAINTAINERS.md +1 -1
- data/README.md +8 -5
- data/bin/fluentd +8 -1
- data/example/counter.conf +1 -1
- data/fluentd.gemspec +4 -3
- data/lib/fluent/command/cat.rb +19 -3
- data/lib/fluent/command/fluentd.rb +1 -2
- data/lib/fluent/command/plugin_generator.rb +42 -2
- 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 +49 -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 +150 -39
- data/lib/fluent/plugin/in_tail/position_file.rb +15 -1
- data/lib/fluent/plugin/out_forward.rb +14 -33
- data/lib/fluent/plugin/output.rb +11 -9
- data/lib/fluent/plugin/parser_csv.rb +2 -2
- data/lib/fluent/plugin/parser_json.rb +2 -3
- data/lib/fluent/plugin/parser_syslog.rb +2 -2
- data/lib/fluent/plugin/service_discovery.rb +0 -15
- data/lib/fluent/plugin/storage_local.rb +1 -1
- data/lib/fluent/plugin_helper/http_server/router.rb +1 -1
- data/lib/fluent/plugin_helper/server.rb +4 -2
- data/lib/fluent/plugin_helper/service_discovery.rb +39 -1
- data/lib/fluent/plugin_helper/service_discovery/manager.rb +11 -5
- data/lib/fluent/plugin_helper/socket_option.rb +2 -2
- 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/fluent-plugin.gemspec.erb +3 -3
- 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 +54 -0
- data/test/plugin/out_forward/test_connection_manager.rb +0 -6
- data/test/plugin/test_file_wrapper.rb +115 -0
- 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 +329 -10
- 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 +138 -105
- data/test/plugin/test_out_stream.rb +18 -8
- data/test/plugin/test_output.rb +15 -3
- data/test/plugin/test_output_as_buffered_backup.rb +2 -0
- data/test/plugin/test_parser_csv.rb +14 -0
- data/test/plugin/test_parser_syslog.rb +14 -0
- data/test/plugin_helper/http_server/test_route.rb +1 -1
- data/test/plugin_helper/service_discovery/test_manager.rb +1 -1
- data/test/plugin_helper/test_child_process.rb +1 -1
- data/test/plugin_helper/test_http_server_helper.rb +34 -27
- data/test/plugin_helper/test_server.rb +144 -139
- 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_output.rb +2 -2
- data/test/test_supervisor.rb +35 -0
- metadata +41 -11
- 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
@@ -156,6 +156,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
156
156
|
assert_equal 2, d.instance.rotate_wait
|
157
157
|
assert_equal "#{TMP_DIR}/tail.pos", d.instance.pos_file
|
158
158
|
assert_equal 1000, d.instance.read_lines_limit
|
159
|
+
assert_equal -1, d.instance.read_bytes_limit_per_second
|
159
160
|
assert_equal false, d.instance.ignore_repeated_permission_error
|
160
161
|
assert_nothing_raised do
|
161
162
|
d.instance.have_read_capability?
|
@@ -195,6 +196,22 @@ class TailInputTest < Test::Unit::TestCase
|
|
195
196
|
end
|
196
197
|
end
|
197
198
|
|
199
|
+
sub_test_case "log throttling per file" do
|
200
|
+
test "w/o watcher timer is invalid" do
|
201
|
+
conf = CONFIG_ENABLE_WATCH_TIMER + config_element("ROOT", "", {"read_bytes_limit_per_second" => "8k"})
|
202
|
+
assert_raise(Fluent::ConfigError) do
|
203
|
+
create_driver(conf)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
test "valid" do
|
208
|
+
conf = config_element("ROOT", "", {"read_bytes_limit_per_second" => "8k"})
|
209
|
+
assert_raise(Fluent::ConfigError) do
|
210
|
+
create_driver(conf)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
198
215
|
test "both enable_watch_timer and enable_stat_watcher are false" do
|
199
216
|
assert_raise(Fluent::ConfigError) do
|
200
217
|
create_driver(CONFIG_ENABLE_WATCH_TIMER + CONFIG_DISABLE_STAT_WATCHER + PARSE_SINGLE_LINE_CONFIG)
|
@@ -323,6 +340,209 @@ class TailInputTest < Test::Unit::TestCase
|
|
323
340
|
assert num_events <= d.emit_count
|
324
341
|
end
|
325
342
|
|
343
|
+
sub_test_case "log throttling per file" do
|
344
|
+
teardown do
|
345
|
+
cleanup_file("#{TMP_DIR}/tail.txt")
|
346
|
+
end
|
347
|
+
|
348
|
+
sub_test_case "reads_bytes_per_second w/o throttled" do
|
349
|
+
data("flat 8192 bytes, 2 events" => [:flat, 100, 8192, 2],
|
350
|
+
"flat 8192 bytes, 2 events w/o stat watcher" => [:flat_without_stat, 100, 8192, 2],
|
351
|
+
"flat #{8192*10} bytes, 20 events" => [:flat, 100, (8192 * 10), 20],
|
352
|
+
"flat #{8192*10} bytes, 20 events w/o stat watcher" => [:flat_without_stat, 100, (8192 * 10), 20],
|
353
|
+
"parse #{8192*4} bytes, 8 events" => [:parse, 100, (8192 * 4), 8],
|
354
|
+
"parse #{8192*4} bytes, 8 events w/o stat watcher" => [:parse_without_stat, 100, (8192 * 4), 8],
|
355
|
+
"parse #{8192*10} bytes, 20 events" => [:parse, 100, (8192 * 10), 20],
|
356
|
+
"parse #{8192*10} bytes, 20 events w/o stat watcher" => [:parse_without_stat, 100, (8192 * 10), 20],
|
357
|
+
"flat 8k bytes with unit, 2 events" => [:flat, 100, "8k", 2])
|
358
|
+
def test_emit_with_read_bytes_limit_per_second(data)
|
359
|
+
config_style, limit, limit_bytes, num_events = data
|
360
|
+
case config_style
|
361
|
+
when :flat
|
362
|
+
config = CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes })
|
363
|
+
when :parse
|
364
|
+
config = CONFIG_READ_FROM_HEAD + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes }) + PARSE_SINGLE_LINE_CONFIG
|
365
|
+
when :flat_without_stat
|
366
|
+
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 })
|
367
|
+
when :parse_without_stat
|
368
|
+
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
|
369
|
+
end
|
370
|
+
|
371
|
+
msg = 'test' * 2000 # in_tail reads 8192 bytes at once.
|
372
|
+
start_time = Fluent::Clock.now
|
373
|
+
|
374
|
+
d = create_driver(config)
|
375
|
+
d.run(expect_emits: 2) do
|
376
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
|
377
|
+
100.times do
|
378
|
+
f.puts msg
|
379
|
+
end
|
380
|
+
}
|
381
|
+
end
|
382
|
+
|
383
|
+
assert_true(Fluent::Clock.now - start_time > 1)
|
384
|
+
assert_equal(num_events.times.map { {"message" => msg} },
|
385
|
+
d.events.collect { |event| event[2] })
|
386
|
+
end
|
387
|
+
|
388
|
+
def test_read_bytes_limit_precede_read_lines_limit
|
389
|
+
config = CONFIG_READ_FROM_HEAD +
|
390
|
+
SINGLE_LINE_CONFIG +
|
391
|
+
config_element("", "", {
|
392
|
+
"read_lines_limit" => 1000,
|
393
|
+
"read_bytes_limit_per_second" => 8192
|
394
|
+
})
|
395
|
+
msg = 'abc'
|
396
|
+
start_time = Fluent::Clock.now
|
397
|
+
d = create_driver(config)
|
398
|
+
d.run(expect_emits: 2) do
|
399
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
|
400
|
+
8000.times do
|
401
|
+
f.puts msg
|
402
|
+
end
|
403
|
+
}
|
404
|
+
end
|
405
|
+
|
406
|
+
assert_true(Fluent::Clock.now - start_time > 1)
|
407
|
+
assert_equal(4096.times.map { {"message" => msg} },
|
408
|
+
d.events.collect { |event| event[2] })
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
sub_test_case "reads_bytes_per_second w/ throttled already" do
|
413
|
+
data("flat 8192 bytes" => [:flat, 100, 8192],
|
414
|
+
"parse 8192 bytes" => [:parse, 100, 8192])
|
415
|
+
def test_emit_with_read_bytes_limit_per_second(data)
|
416
|
+
config_style, limit, limit_bytes = data
|
417
|
+
case config_style
|
418
|
+
when :flat
|
419
|
+
config = CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes })
|
420
|
+
when :parse
|
421
|
+
config = CONFIG_READ_FROM_HEAD + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes }) + PARSE_SINGLE_LINE_CONFIG
|
422
|
+
end
|
423
|
+
d = create_driver(config)
|
424
|
+
msg = 'test' * 2000 # in_tail reads 8192 bytes at once.
|
425
|
+
|
426
|
+
mock.proxy(d.instance).io_handler(anything, anything) do |io_handler|
|
427
|
+
require 'fluent/config/types'
|
428
|
+
limit_bytes_value = Fluent::Config.size_value(limit_bytes)
|
429
|
+
io_handler.instance_variable_set(:@number_bytes_read, limit_bytes_value)
|
430
|
+
if Fluent.linux?
|
431
|
+
mock.proxy(io_handler).handle_notify.at_least(5)
|
432
|
+
else
|
433
|
+
mock.proxy(io_handler).handle_notify.twice
|
434
|
+
end
|
435
|
+
io_handler
|
436
|
+
end
|
437
|
+
|
438
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") do |f|
|
439
|
+
100.times do
|
440
|
+
f.puts msg
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
# We should not do shutdown here due to hard timeout.
|
445
|
+
d.run do
|
446
|
+
start_time = Fluent::Clock.now
|
447
|
+
while Fluent::Clock.now - start_time < 0.8 do
|
448
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") do |f|
|
449
|
+
f.puts msg
|
450
|
+
f.flush
|
451
|
+
end
|
452
|
+
sleep 0.05
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
assert_equal([], d.events)
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
sub_test_case "EOF with reads_bytes_per_second" do
|
461
|
+
def test_longer_than_rotate_wait
|
462
|
+
limit_bytes = 8192
|
463
|
+
num_lines = 1024 * 3
|
464
|
+
msg = "08bytes"
|
465
|
+
|
466
|
+
File.open("#{TMP_DIR}/tail.txt", "wb") do |f|
|
467
|
+
f.write("#{msg}\n" * num_lines)
|
468
|
+
end
|
469
|
+
|
470
|
+
config = CONFIG_READ_FROM_HEAD +
|
471
|
+
SINGLE_LINE_CONFIG +
|
472
|
+
config_element("", "", {
|
473
|
+
"read_bytes_limit_per_second" => limit_bytes,
|
474
|
+
"rotate_wait" => 0.1,
|
475
|
+
"refresh_interval" => 0.5,
|
476
|
+
})
|
477
|
+
|
478
|
+
rotated = false
|
479
|
+
d = create_driver(config)
|
480
|
+
d.run(timeout: 10) do
|
481
|
+
while d.events.size < num_lines do
|
482
|
+
if d.events.size > 0 && !rotated
|
483
|
+
cleanup_file("#{TMP_DIR}/tail.txt")
|
484
|
+
FileUtils.touch("#{TMP_DIR}/tail.txt")
|
485
|
+
rotated = true
|
486
|
+
end
|
487
|
+
sleep 0.3
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
assert_equal(num_lines,
|
492
|
+
d.events.count do |event|
|
493
|
+
event[2]["message"] == msg
|
494
|
+
end)
|
495
|
+
end
|
496
|
+
|
497
|
+
def test_shorter_than_rotate_wait
|
498
|
+
limit_bytes = 8192
|
499
|
+
num_lines = 1024 * 2
|
500
|
+
msg = "08bytes"
|
501
|
+
|
502
|
+
File.open("#{TMP_DIR}/tail.txt", "wb") do |f|
|
503
|
+
f.write("#{msg}\n" * num_lines)
|
504
|
+
end
|
505
|
+
|
506
|
+
config = CONFIG_READ_FROM_HEAD +
|
507
|
+
SINGLE_LINE_CONFIG +
|
508
|
+
config_element("", "", {
|
509
|
+
"read_bytes_limit_per_second" => limit_bytes,
|
510
|
+
"rotate_wait" => 2,
|
511
|
+
"refresh_interval" => 0.5,
|
512
|
+
})
|
513
|
+
|
514
|
+
start_time = Fluent::Clock.now
|
515
|
+
rotated = false
|
516
|
+
detached = false
|
517
|
+
d = create_driver(config)
|
518
|
+
mock.proxy(d.instance).setup_watcher(anything, anything) do |tw|
|
519
|
+
mock.proxy(tw).detach(anything) do |v|
|
520
|
+
detached = true
|
521
|
+
v
|
522
|
+
end
|
523
|
+
tw
|
524
|
+
end.twice
|
525
|
+
|
526
|
+
d.run(timeout: 10) do
|
527
|
+
until detached do
|
528
|
+
if d.events.size > 0 && !rotated
|
529
|
+
cleanup_file("#{TMP_DIR}/tail.txt")
|
530
|
+
FileUtils.touch("#{TMP_DIR}/tail.txt")
|
531
|
+
rotated = true
|
532
|
+
end
|
533
|
+
sleep 0.3
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
assert_true(Fluent::Clock.now - start_time > 2)
|
538
|
+
assert_equal(num_lines,
|
539
|
+
d.events.count do |event|
|
540
|
+
event[2]["message"] == msg
|
541
|
+
end)
|
542
|
+
end
|
543
|
+
end
|
544
|
+
end
|
545
|
+
|
326
546
|
data(flat: CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG,
|
327
547
|
parse: CONFIG_READ_FROM_HEAD + PARSE_SINGLE_LINE_CONFIG)
|
328
548
|
def test_emit_with_read_from_head(data)
|
@@ -589,6 +809,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
589
809
|
File.open("#{TMP_DIR}/tail.txt", "wb") {|f|
|
590
810
|
f.puts "test1"
|
591
811
|
f.puts "test2"
|
812
|
+
f.flush
|
592
813
|
}
|
593
814
|
|
594
815
|
d = create_driver(config)
|
@@ -598,19 +819,23 @@ class TailInputTest < Test::Unit::TestCase
|
|
598
819
|
f.puts "test3\ntest4"
|
599
820
|
f.flush
|
600
821
|
}
|
601
|
-
sleep 1
|
822
|
+
waiting(2) { sleep 0.1 until d.events.length == 2 }
|
602
823
|
File.truncate("#{TMP_DIR}/tail.txt", 6)
|
603
824
|
end
|
604
825
|
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
826
|
+
expected = {
|
827
|
+
emit_count: 2,
|
828
|
+
events: [
|
829
|
+
[Fluent::EventTime, {"message" => "test3"}],
|
830
|
+
[Fluent::EventTime, {"message" => "test4"}],
|
831
|
+
[Fluent::EventTime, {"message" => "test1"}],
|
832
|
+
]
|
833
|
+
}
|
834
|
+
actual = {
|
835
|
+
emit_count: d.emit_count,
|
836
|
+
events: d.events.collect{|event| [event[1].class, event[2]]}
|
837
|
+
}
|
838
|
+
assert_equal(expected, actual)
|
614
839
|
end
|
615
840
|
|
616
841
|
def test_move_truncate_move_back
|
@@ -1914,4 +2139,98 @@ class TailInputTest < Test::Unit::TestCase
|
|
1914
2139
|
waiting(5) { sleep 0.1 until d.instance.instance_variable_get(:@tails).keys.size == 1 }
|
1915
2140
|
d.instance_shutdown
|
1916
2141
|
end
|
2142
|
+
|
2143
|
+
def test_ENOENT_error_after_setup_watcher
|
2144
|
+
path = "#{TMP_DIR}/tail.txt"
|
2145
|
+
FileUtils.touch(path)
|
2146
|
+
config = config_element('', '', {
|
2147
|
+
'format' => 'none',
|
2148
|
+
})
|
2149
|
+
d = create_driver(config)
|
2150
|
+
mock.proxy(d.instance).setup_watcher(anything, anything) do |tw|
|
2151
|
+
cleanup_file(path)
|
2152
|
+
tw
|
2153
|
+
end
|
2154
|
+
assert_nothing_raised do
|
2155
|
+
d.run(shutdown: false) {}
|
2156
|
+
end
|
2157
|
+
d.instance_shutdown
|
2158
|
+
assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed with Errno::ENOENT. Drop tail watcher for now.\n") })
|
2159
|
+
end
|
2160
|
+
|
2161
|
+
def test_EACCES_error_after_setup_watcher
|
2162
|
+
omit "Cannot test with root user" if Process::UID.eid == 0
|
2163
|
+
path = "#{TMP_DIR}/noaccess/tail.txt"
|
2164
|
+
begin
|
2165
|
+
FileUtils.mkdir_p("#{TMP_DIR}/noaccess")
|
2166
|
+
FileUtils.chmod(0755, "#{TMP_DIR}/noaccess")
|
2167
|
+
FileUtils.touch(path)
|
2168
|
+
config = config_element('', '', {
|
2169
|
+
'tag' => "tail",
|
2170
|
+
'path' => path,
|
2171
|
+
'format' => 'none',
|
2172
|
+
})
|
2173
|
+
d = create_driver(config, false)
|
2174
|
+
mock.proxy(d.instance).setup_watcher(anything, anything) do |tw|
|
2175
|
+
FileUtils.chmod(0000, "#{TMP_DIR}/noaccess")
|
2176
|
+
tw
|
2177
|
+
end
|
2178
|
+
assert_nothing_raised do
|
2179
|
+
d.run(shutdown: false) {}
|
2180
|
+
end
|
2181
|
+
d.instance_shutdown
|
2182
|
+
assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed with Errno::EACCES. Drop tail watcher for now.\n") })
|
2183
|
+
end
|
2184
|
+
ensure
|
2185
|
+
if File.exist?("#{TMP_DIR}/noaccess")
|
2186
|
+
FileUtils.chmod(0755, "#{TMP_DIR}/noaccess")
|
2187
|
+
FileUtils.rm_rf("#{TMP_DIR}/noaccess")
|
2188
|
+
end
|
2189
|
+
end unless Fluent.windows?
|
2190
|
+
|
2191
|
+
def test_EACCES
|
2192
|
+
path = "#{TMP_DIR}/tail.txt"
|
2193
|
+
FileUtils.touch(path)
|
2194
|
+
config = config_element('', '', {
|
2195
|
+
'format' => 'none',
|
2196
|
+
})
|
2197
|
+
d = create_driver(config)
|
2198
|
+
mock.proxy(Fluent::FileWrapper).stat(path) do |stat|
|
2199
|
+
raise Errno::EACCES
|
2200
|
+
end.at_least(1)
|
2201
|
+
assert_nothing_raised do
|
2202
|
+
d.run(shutdown: false) {}
|
2203
|
+
end
|
2204
|
+
d.instance_shutdown
|
2205
|
+
assert($log.out.logs.any?{|log| log.include?("expand_paths: stat() for #{path} failed with Errno::EACCES. Skip file.\n") })
|
2206
|
+
end
|
2207
|
+
|
2208
|
+
def test_shutdown_timeout
|
2209
|
+
path = "#{TMP_DIR}/tail.txt"
|
2210
|
+
File.open("#{TMP_DIR}/tail.txt", "wb") do |f|
|
2211
|
+
(1024 * 1024 * 5).times do
|
2212
|
+
f.puts "{\"test\":\"fizzbuzz\"}"
|
2213
|
+
end
|
2214
|
+
end
|
2215
|
+
|
2216
|
+
config =
|
2217
|
+
CONFIG_READ_FROM_HEAD +
|
2218
|
+
config_element('', '', {
|
2219
|
+
'format' => 'json',
|
2220
|
+
'skip_refresh_on_startup' => true,
|
2221
|
+
})
|
2222
|
+
d = create_driver(config)
|
2223
|
+
mock.proxy(d.instance).io_handler(anything, anything) do |io_handler|
|
2224
|
+
io_handler.shutdown_timeout = 0.5
|
2225
|
+
io_handler
|
2226
|
+
end
|
2227
|
+
|
2228
|
+
start_time = Fluent::Clock.now
|
2229
|
+
assert_nothing_raised do
|
2230
|
+
d.run(expect_emits: 1)
|
2231
|
+
end
|
2232
|
+
|
2233
|
+
elapsed = Fluent::Clock.now - start_time
|
2234
|
+
assert_true(elapsed > 0.5 && elapsed < 2.5)
|
2235
|
+
end
|
1917
2236
|
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
|