fluentd 1.14.0 → 1.14.4

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.

Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.drone.yml +6 -6
  3. data/.github/ISSUE_TEMPLATE/bug_report.yaml +1 -0
  4. data/CHANGELOG.md +101 -0
  5. data/README.md +2 -0
  6. data/SECURITY.md +18 -0
  7. data/fluentd.gemspec +3 -3
  8. data/lib/fluent/command/cat.rb +13 -3
  9. data/lib/fluent/config/parser.rb +1 -1
  10. data/lib/fluent/config/v1_parser.rb +1 -1
  11. data/lib/fluent/env.rb +4 -0
  12. data/lib/fluent/plugin/buf_file.rb +2 -2
  13. data/lib/fluent/plugin/buffer.rb +62 -8
  14. data/lib/fluent/plugin/in_tail.rb +53 -7
  15. data/lib/fluent/plugin/out_copy.rb +1 -1
  16. data/lib/fluent/plugin/out_file.rb +13 -1
  17. data/lib/fluent/plugin/out_forward.rb +15 -7
  18. data/lib/fluent/plugin/output.rb +6 -5
  19. data/lib/fluent/plugin/parser_apache2.rb +1 -1
  20. data/lib/fluent/plugin/storage_local.rb +3 -5
  21. data/lib/fluent/plugin_id.rb +2 -1
  22. data/lib/fluent/supervisor.rb +2 -2
  23. data/lib/fluent/time.rb +21 -20
  24. data/lib/fluent/version.rb +1 -1
  25. data/test/command/test_cat.rb +31 -2
  26. data/test/plugin/in_tail/test_io_handler.rb +12 -4
  27. data/test/plugin/test_bare_output.rb +1 -1
  28. data/test/plugin/test_buffer.rb +149 -1
  29. data/test/plugin/test_filter.rb +1 -1
  30. data/test/plugin/test_in_tail.rb +109 -9
  31. data/test/plugin/test_input.rb +1 -1
  32. data/test/plugin/test_out_exec.rb +6 -4
  33. data/test/plugin/test_out_exec_filter.rb +4 -0
  34. data/test/plugin/test_out_file.rb +29 -13
  35. data/test/plugin/test_output_as_buffered_secondary.rb +1 -1
  36. data/test/plugin_helper/test_child_process.rb +9 -9
  37. data/test/plugin_helper/test_timer.rb +2 -2
  38. data/test/test_time_parser.rb +22 -0
  39. metadata +8 -7
@@ -99,7 +99,7 @@ class TailInputTest < Test::Unit::TestCase
99
99
  })
100
100
  COMMON_CONFIG = CONFIG + config_element("", "", { "pos_file" => "#{TMP_DIR}/tail.pos" })
101
101
  CONFIG_READ_FROM_HEAD = config_element("", "", { "read_from_head" => true })
102
- CONFIG_ENABLE_WATCH_TIMER = config_element("", "", { "enable_watch_timer" => false })
102
+ CONFIG_DISABLE_WATCH_TIMER = config_element("", "", { "enable_watch_timer" => false })
103
103
  CONFIG_DISABLE_STAT_WATCHER = config_element("", "", { "enable_stat_watcher" => false })
104
104
  CONFIG_OPEN_ON_EVERY_UPDATE = config_element("", "", { "open_on_every_update" => true })
105
105
  COMMON_FOLLOW_INODE_CONFIG = config_element("ROOT", "", {
@@ -199,7 +199,7 @@ class TailInputTest < Test::Unit::TestCase
199
199
 
200
200
  sub_test_case "log throttling per file" do
201
201
  test "w/o watcher timer is invalid" do
202
- conf = CONFIG_ENABLE_WATCH_TIMER + config_element("ROOT", "", {"read_bytes_limit_per_second" => "8k"})
202
+ conf = CONFIG_DISABLE_WATCH_TIMER + config_element("ROOT", "", {"read_bytes_limit_per_second" => "8k"})
203
203
  assert_raise(Fluent::ConfigError) do
204
204
  create_driver(conf)
205
205
  end
@@ -215,7 +215,7 @@ class TailInputTest < Test::Unit::TestCase
215
215
 
216
216
  test "both enable_watch_timer and enable_stat_watcher are false" do
217
217
  assert_raise(Fluent::ConfigError) do
218
- create_driver(CONFIG_ENABLE_WATCH_TIMER + CONFIG_DISABLE_STAT_WATCHER + PARSE_SINGLE_LINE_CONFIG)
218
+ create_driver(CONFIG_DISABLE_WATCH_TIMER + CONFIG_DISABLE_STAT_WATCHER + PARSE_SINGLE_LINE_CONFIG)
219
219
  end
220
220
  end
221
221
 
@@ -570,9 +570,9 @@ class TailInputTest < Test::Unit::TestCase
570
570
  assert_equal({"message" => "test4"}, events[3][2])
571
571
  end
572
572
 
573
- data(flat: CONFIG_ENABLE_WATCH_TIMER + SINGLE_LINE_CONFIG,
574
- parse: CONFIG_ENABLE_WATCH_TIMER + PARSE_SINGLE_LINE_CONFIG)
575
- def test_emit_with_enable_watch_timer(data)
573
+ data(flat: CONFIG_DISABLE_WATCH_TIMER + SINGLE_LINE_CONFIG,
574
+ parse: CONFIG_DISABLE_WATCH_TIMER + PARSE_SINGLE_LINE_CONFIG)
575
+ def test_emit_without_watch_timer(data)
576
576
  config = data
577
577
  File.open("#{TMP_DIR}/tail.txt", "wb") {|f|
578
578
  f.puts "test1"
@@ -596,6 +596,38 @@ class TailInputTest < Test::Unit::TestCase
596
596
  assert_equal({"message" => "test4"}, events[1][2])
597
597
  end
598
598
 
599
+ # https://github.com/fluent/fluentd/pull/3541#discussion_r740197711
600
+ def test_watch_wildcard_path_without_watch_timer
601
+ omit "need inotify" unless Fluent.linux?
602
+
603
+ config = config_element("ROOT", "", {
604
+ "path" => "#{TMP_DIR}/tail*.txt",
605
+ "tag" => "t1",
606
+ })
607
+ config = config + CONFIG_DISABLE_WATCH_TIMER + SINGLE_LINE_CONFIG
608
+
609
+ File.open("#{TMP_DIR}/tail.txt", "wb") {|f|
610
+ f.puts "test1"
611
+ f.puts "test2"
612
+ }
613
+
614
+ d = create_driver(config, false)
615
+
616
+ d.run(expect_emits: 1, timeout: 1) do
617
+ File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
618
+ f.puts "test3"
619
+ f.puts "test4"
620
+ }
621
+ end
622
+
623
+ assert_equal(
624
+ [
625
+ {"message" => "test3"},
626
+ {"message" => "test4"},
627
+ ],
628
+ d.events.collect { |event| event[2] })
629
+ end
630
+
599
631
  data(flat: CONFIG_DISABLE_STAT_WATCHER + SINGLE_LINE_CONFIG,
600
632
  parse: CONFIG_DISABLE_STAT_WATCHER + PARSE_SINGLE_LINE_CONFIG)
601
633
  def test_emit_with_disable_stat_watcher(data)
@@ -619,6 +651,23 @@ class TailInputTest < Test::Unit::TestCase
619
651
  assert_equal({"message" => "test3"}, events[0][2])
620
652
  assert_equal({"message" => "test4"}, events[1][2])
621
653
  end
654
+
655
+ def test_always_read_from_head_on_detecting_a_new_file
656
+ d = create_driver(SINGLE_LINE_CONFIG)
657
+
658
+ d.run(expect_emits: 1, timeout: 3) do
659
+ File.open("#{TMP_DIR}/tail.txt", "wb") {|f|
660
+ f.puts "test1\ntest2\n"
661
+ }
662
+ end
663
+
664
+ assert_equal(
665
+ [
666
+ {"message" => "test1"},
667
+ {"message" => "test2"},
668
+ ],
669
+ d.events.collect { |event| event[2] })
670
+ end
622
671
  end
623
672
 
624
673
  class TestWithSystem < self
@@ -1524,11 +1573,18 @@ class TailInputTest < Test::Unit::TestCase
1524
1573
  plugin.instance_eval do
1525
1574
  @pf = Fluent::Plugin::TailInput::PositionFile.load(sio, EX_FOLLOW_INODES, {}, logger: $log)
1526
1575
  @loop = Coolio::Loop.new
1576
+ opened_file_metrics = Fluent::Plugin::LocalMetrics.new
1577
+ opened_file_metrics.configure(config_element('metrics', '', {}))
1578
+ closed_file_metrics = Fluent::Plugin::LocalMetrics.new
1579
+ closed_file_metrics.configure(config_element('metrics', '', {}))
1580
+ rotated_file_metrics = Fluent::Plugin::LocalMetrics.new
1581
+ rotated_file_metrics.configure(config_element('metrics', '', {}))
1582
+ @metrics = Fluent::Plugin::TailInput::MetricsInfo.new(opened_file_metrics, closed_file_metrics, rotated_file_metrics)
1527
1583
  end
1528
1584
 
1529
1585
  Timecop.freeze(2010, 1, 2, 3, 4, 5) do
1530
1586
  ex_paths.each do |target_info|
1531
- mock.proxy(Fluent::Plugin::TailInput::TailWatcher).new(target_info, anything, anything, true, false, anything, nil, anything).once
1587
+ mock.proxy(Fluent::Plugin::TailInput::TailWatcher).new(target_info, anything, anything, true, false, anything, nil, anything, anything).once
1532
1588
  end
1533
1589
 
1534
1590
  plugin.refresh_watchers
@@ -1542,7 +1598,7 @@ class TailInputTest < Test::Unit::TestCase
1542
1598
  path = "test/plugin/data/2010/01/20100102-030406.log"
1543
1599
  inode = Fluent::FileWrapper.stat(path).ino
1544
1600
  target_info = Fluent::Plugin::TailInput::TargetInfo.new(path, inode)
1545
- mock.proxy(Fluent::Plugin::TailInput::TailWatcher).new(target_info, anything, anything, true, false, anything, nil, anything).once
1601
+ mock.proxy(Fluent::Plugin::TailInput::TailWatcher).new(target_info, anything, anything, true, false, anything, nil, anything, anything).once
1546
1602
  plugin.refresh_watchers
1547
1603
 
1548
1604
  flexstub(Fluent::Plugin::TailInput::TailWatcher) do |watcherclass|
@@ -1651,6 +1707,41 @@ class TailInputTest < Test::Unit::TestCase
1651
1707
  mock(plugin.router).emit_stream('pre.foo.bar.log.post', anything).once
1652
1708
  plugin.receive_lines(['foo', 'bar'], DummyWatcher.new('foo.bar.log'))
1653
1709
  end
1710
+
1711
+ data(
1712
+ small: ["128", 128],
1713
+ KiB: ["1k", 1024]
1714
+ )
1715
+ test 'max_line_size' do |(label, size)|
1716
+ config = config_element("", "", {
1717
+ "tag" => "max_line_size",
1718
+ "path" => "#{TMP_DIR}/with_long_lines.txt",
1719
+ "format" => "none",
1720
+ "read_from_head" => true,
1721
+ "max_line_size" => label,
1722
+ "log_level" => "debug"
1723
+ })
1724
+ File.open("#{TMP_DIR}/with_long_lines.txt", "w+") do |f|
1725
+ f.puts "foo"
1726
+ f.puts "x" * size # 'x' * size + \n > @max_line_size
1727
+ f.puts "bar"
1728
+ end
1729
+ d = create_driver(config, false)
1730
+ timestamp = Time.parse("Mon Nov 29 11:22:33 UTC 2021")
1731
+ Timecop.freeze(timestamp)
1732
+ d.run(expect_records: 2)
1733
+ assert_equal([
1734
+ [{"message" => "foo"},{"message" => "bar"}],
1735
+ [
1736
+ "2021-11-29 11:22:33 +0000 [warn]: received line length is longer than #{size}\n",
1737
+ "2021-11-29 11:22:33 +0000 [debug]: skipped line: #{'x' * size}\n"
1738
+ ]
1739
+ ],
1740
+ [
1741
+ d.events.collect { |event| event.last },
1742
+ d.logs[-2..]
1743
+ ])
1744
+ end
1654
1745
  end
1655
1746
 
1656
1747
  # Ensure that no fatal exception is raised when a file is missing and that
@@ -1885,13 +1976,22 @@ class TailInputTest < Test::Unit::TestCase
1885
1976
  config = COMMON_FOLLOW_INODE_CONFIG + config_element('', '', {"rotate_wait" => "1s", "limit_recently_modified" => "1s"})
1886
1977
 
1887
1978
  d = create_driver(config, false)
1979
+ d.instance.instance_eval do
1980
+ opened_file_metrics = Fluent::Plugin::LocalMetrics.new
1981
+ opened_file_metrics.configure(config_element('metrics', '', {}))
1982
+ closed_file_metrics = Fluent::Plugin::LocalMetrics.new
1983
+ closed_file_metrics.configure(config_element('metrics', '', {}))
1984
+ rotated_file_metrics = Fluent::Plugin::LocalMetrics.new
1985
+ rotated_file_metrics.configure(config_element('metrics', '', {}))
1986
+ @metrics = Fluent::Plugin::TailInput::MetricsInfo.new(opened_file_metrics, closed_file_metrics, rotated_file_metrics)
1987
+ end
1888
1988
 
1889
1989
  File.open("#{TMP_DIR}/tail.txt", "wb") {|f|
1890
1990
  f.puts "test1"
1891
1991
  f.puts "test2"
1892
1992
  }
1893
1993
  target_info = create_target_info("#{TMP_DIR}/tail.txt")
1894
- mock.proxy(Fluent::Plugin::TailInput::TailWatcher).new(target_info, anything, anything, true, true, anything, nil, anything).once
1994
+ mock.proxy(Fluent::Plugin::TailInput::TailWatcher).new(target_info, anything, anything, true, true, anything, nil, anything, anything).once
1895
1995
  d.run(shutdown: false)
1896
1996
  assert d.instance.instance_variable_get(:@tails)[target_info]
1897
1997
 
@@ -73,7 +73,7 @@ class InputTest < Test::Unit::TestCase
73
73
 
74
74
  @p.configure(config_element('ROOT', '', {'@log_level' => 'debug'}))
75
75
 
76
- assert{ @p.log.object_id != original_logger.object_id }
76
+ assert(@p.log.object_id != original_logger.object_id)
77
77
  assert_equal Fluent::Log::LEVEL_DEBUG, @p.log.level
78
78
  end
79
79
 
@@ -243,7 +243,7 @@ class ExecOutputTest < Test::Unit::TestCase
243
243
  sub_test_case 'when executed process dies unexpectedly' do
244
244
  setup do
245
245
  @gen_config = ->(num){ <<EOC
246
- command ruby -e "ARGV.first.to_i == 0 ? open(ARGV[1]){|f| STDOUT.write f.read} : (sleep 1 ; exit ARGV.first.to_i)" #{num} >#{TMP_DIR}/fail_out
246
+ command ruby -e "ARGV.first.to_i == 0 ? open(ARGV[1]){|f| STDOUT.write(f.read); STDOUT.flush} : (sleep 1 ; exit ARGV.first.to_i)" #{num} >#{TMP_DIR}/fail_out
247
247
  <inject>
248
248
  tag_key tag
249
249
  time_key time
@@ -265,7 +265,7 @@ EOC
265
265
  expect_path = "#{TMP_DIR}/fail_out"
266
266
 
267
267
  d.end_if{ File.exist?(expect_path) }
268
- d.run(default_tag: 'test', flush: true, wait_flush_completion: false, shutdown: false) do
268
+ d.run(default_tag: 'test', flush: true, wait_flush_completion: true, shutdown: false) do
269
269
  d.feed(time, records[0])
270
270
  d.feed(time, records[1])
271
271
  end
@@ -281,7 +281,8 @@ EOC
281
281
  assert{ d.instance.buffer.queue.empty? }
282
282
  assert{ d.instance.dequeued_chunks.empty? }
283
283
 
284
- d.instance_shutdown
284
+ ensure
285
+ d.instance_shutdown if d && d.instance
285
286
  end
286
287
 
287
288
  test 'flushed chunk will be taken back after child process unexpectedly exits' do
@@ -304,7 +305,8 @@ EOC
304
305
 
305
306
  assert{ File.exist?(expect_path) && File.size(expect_path) == 0 }
306
307
 
307
- d.instance_shutdown
308
+ ensure
309
+ d.instance_shutdown if d && d.instance
308
310
  end
309
311
  end
310
312
  end
@@ -524,6 +524,9 @@ class ExecFilterOutputTest < Test::Unit::TestCase
524
524
  assert_equal pid_list[1], events[1][2]['child_pid']
525
525
  assert_equal pid_list[0], events[2][2]['child_pid']
526
526
  assert_equal pid_list[1], events[3][2]['child_pid']
527
+
528
+ ensure
529
+ d.run(start: false, shutdown: true)
527
530
  end
528
531
 
529
532
  # child process exits per 3 lines
@@ -597,6 +600,7 @@ class ExecFilterOutputTest < Test::Unit::TestCase
597
600
  assert_equal 2, logs.select { |l| l.include?('child process exits with error code') }.size
598
601
  assert_equal 2, logs.select { |l| l.include?('respawning child process') }.size
599
602
 
603
+ ensure
600
604
  d.run(start: false, shutdown: true)
601
605
  end
602
606
  end
@@ -394,6 +394,11 @@ class FileOutputTest < Test::Unit::TestCase
394
394
  assert_equal expect, result
395
395
  end
396
396
 
397
+ def check_result(path, expect)
398
+ result = File.read(path, mode: "rb")
399
+ assert_equal expect, result
400
+ end
401
+
397
402
  sub_test_case 'write' do
398
403
  test 'basic case' do
399
404
  d = create_driver
@@ -535,20 +540,27 @@ class FileOutputTest < Test::Unit::TestCase
535
540
  assert_equal 3, Dir.glob("#{TMP_DIR}/out_file_test.*").size
536
541
  end
537
542
 
538
- test 'append' do
543
+ data(
544
+ "with compression" => true,
545
+ "without compression" => false,
546
+ )
547
+ test 'append' do |compression|
539
548
  time = event_time("2011-01-02 13:14:15 UTC")
540
549
  formatted_lines = %[2011-01-02T13:14:15Z\ttest\t{"a":1}#{@default_newline}] + %[2011-01-02T13:14:15Z\ttest\t{"a":2}#{@default_newline}]
541
550
 
542
551
  write_once = ->(){
543
- d = create_driver %[
552
+ config = %[
544
553
  path #{TMP_DIR}/out_file_test
545
- compress gz
546
554
  utc
547
555
  append true
548
556
  <buffer>
549
557
  timekey_use_utc true
550
558
  </buffer>
551
559
  ]
560
+ if compression
561
+ config << " compress gz"
562
+ end
563
+ d = create_driver(config)
552
564
  d.run(default_tag: 'test'){
553
565
  d.feed(time, {"a"=>1})
554
566
  d.feed(time, {"a"=>2})
@@ -556,17 +568,21 @@ class FileOutputTest < Test::Unit::TestCase
556
568
  d.instance.last_written_path
557
569
  }
558
570
 
559
- path = write_once.call
560
- assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
561
- check_gzipped_result(path, formatted_lines)
562
-
563
- path = write_once.call
564
- assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
565
- check_gzipped_result(path, formatted_lines * 2)
571
+ log_file_name = "out_file_test.20110102.log"
572
+ if compression
573
+ log_file_name << ".gz"
574
+ end
566
575
 
567
- path = write_once.call
568
- assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
569
- check_gzipped_result(path, formatted_lines * 3)
576
+ 1.upto(3) do |i|
577
+ path = write_once.call
578
+ assert_equal "#{TMP_DIR}/#{log_file_name}", path
579
+ expect = formatted_lines * i
580
+ if compression
581
+ check_gzipped_result(path, expect)
582
+ else
583
+ check_result(path, expect)
584
+ end
585
+ end
570
586
  end
571
587
 
572
588
  test 'append when JST' do
@@ -775,7 +775,7 @@ class BufferedOutputSecondaryTest < Test::Unit::TestCase
775
775
  assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:13').to_i, {"name" => "moris", "age" => 36, "message" => "data2"} ], written[1]
776
776
  assert_equal [ 'test.tag.1', event_time('2016-04-13 18:33:32').to_i, {"name" => "moris", "age" => 36, "message" => "data3"} ], written[2]
777
777
 
778
- assert{ @i.log.out.logs.any?{|l| l.include?("[warn]: retry succeeded by secondary.") } }
778
+ assert(@i.log.out.logs.any?{|l| l.include?("[warn]: retry succeeded by secondary.") })
779
779
  end
780
780
 
781
781
  test 'exponential backoff interval will be initialized when switched to secondary' do
@@ -319,12 +319,12 @@ class ChildProcessTest < Test::Unit::TestCase
319
319
 
320
320
  test 'can execute external command many times, which finishes immediately' do
321
321
  ary = []
322
- arguments = ["-e", "puts 'okay'; STDOUT.flush rescue nil"]
322
+ arguments = ["okay"]
323
323
  Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
324
- @d.child_process_execute(:t5, "ruby", arguments: arguments, interval: 1, mode: [:read]) do |io|
324
+ @d.child_process_execute(:t5, "echo", arguments: arguments, interval: 1, mode: [:read]) do |io|
325
325
  ary << io.read.split("\n").map(&:chomp).join
326
326
  end
327
- sleep 2.5 # 2sec(second invocation) + 0.5sec
327
+ sleep 2.9 # 2sec(second invocation) + 0.9sec
328
328
  assert_equal [], @d.log.out.logs
329
329
  @d.stop
330
330
  assert_equal [], @d.log.out.logs
@@ -335,12 +335,12 @@ class ChildProcessTest < Test::Unit::TestCase
335
335
 
336
336
  test 'can execute external command many times, with leading once executed immediately' do
337
337
  ary = []
338
- arguments = ["-e", "puts 'okay'; STDOUT.flush rescue nil"]
338
+ arguments = ["okay"]
339
339
  Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
340
- @d.child_process_execute(:t6, "ruby", arguments: arguments, interval: 1, immediate: true, mode: [:read]) do |io|
340
+ @d.child_process_execute(:t6, "echo", arguments: arguments, interval: 1, immediate: true, mode: [:read]) do |io|
341
341
  ary << io.read.split("\n").map(&:chomp).join
342
342
  end
343
- sleep 1.5 # 2sec(second invocation) + 0.5sec
343
+ sleep 1.9 # 1sec(second invocation) + 0.9sec
344
344
  @d.stop; @d.shutdown; @d.close; @d.terminate
345
345
  assert_equal 2, ary.size
346
346
  assert_equal [], @d.log.out.logs
@@ -722,14 +722,14 @@ class ChildProcessTest < Test::Unit::TestCase
722
722
  read_data_list = []
723
723
  exit_status_list = []
724
724
 
725
- args = ['-e', 'puts "yay"']
725
+ args = ['yay']
726
726
  cb = ->(status){ exit_status_list << status }
727
727
 
728
728
  Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
729
- @d.child_process_execute(:st1, "ruby", arguments: args, immediate: true, interval: 1, mode: [:read], on_exit_callback: cb) do |readio|
729
+ @d.child_process_execute(:st1, "echo", arguments: args, immediate: true, interval: 1, mode: [:read], on_exit_callback: cb) do |readio|
730
730
  read_data_list << readio.read.chomp
731
731
  end
732
- sleep 2
732
+ sleep 2.5
733
733
  end
734
734
 
735
735
  assert { read_data_list.size >= 2 }
@@ -90,8 +90,8 @@ class TimerTest < Test::Unit::TestCase
90
90
  assert{ counter1 >= 4 && counter1 <= 5 }
91
91
  assert{ counter2 == 2 }
92
92
  msg = "Unexpected error raised. Stopping the timer. title=:t2"
93
- assert{ d1.log.out.logs.any?{|line| line.include?("[error]:") && line.include?(msg) && line.include?("abort!!!!!!") } }
94
- assert{ d1.log.out.logs.any?{|line| line.include?("[error]:") && line.include?("Timer detached. title=:t2") } }
93
+ assert(d1.log.out.logs.any?{|line| line.include?("[error]:") && line.include?(msg) && line.include?("abort!!!!!!") })
94
+ assert(d1.log.out.logs.any?{|line| line.include?("[error]:") && line.include?("Timer detached. title=:t2") })
95
95
 
96
96
  d1.shutdown; d1.close; d1.terminate
97
97
  end
@@ -337,4 +337,26 @@ class TimeParserTest < ::Test::Unit::TestCase
337
337
  assert_equal_event_time(time, parser.parse('2021-01-01T12:00:00+0900'))
338
338
  end
339
339
  end
340
+
341
+ # https://github.com/fluent/fluentd/issues/3195
342
+ test 'change timezone without zone specifier in a format' do
343
+ expected = 1607457600 # 2020-12-08T20:00:00Z
344
+ time1 = time2 = nil
345
+
346
+ with_timezone("UTC-05") do # EST
347
+ i = DummyForTimeParser.new
348
+ i.configure(config_element('parse', '', {'time_type' => 'string',
349
+ 'time_format' => '%Y-%m-%dT%H:%M:%SZ',
350
+ 'utc' => true}))
351
+ parser = i.time_parser_create
352
+
353
+ time1 = parser.parse('2020-12-08T20:00:00Z').to_i
354
+ time2 = with_timezone("UTC-04") do # EDT
355
+ # to avoid using cache, increment 1 sec
356
+ parser.parse('2020-12-08T20:00:01Z').to_i
357
+ end
358
+ end
359
+
360
+ assert_equal([expected, expected + 1], [time1, time2])
361
+ end
340
362
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluentd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.14.0
4
+ version: 1.14.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-30 00:00:00.000000000 Z
11
+ date: 2022-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -107,7 +107,7 @@ dependencies:
107
107
  version: 0.5.1
108
108
  - - "<"
109
109
  - !ruby/object:Gem::Version
110
- version: 0.8.0
110
+ version: 0.9.0
111
111
  type: :runtime
112
112
  prerelease: false
113
113
  version_requirements: !ruby/object:Gem::Requirement
@@ -117,7 +117,7 @@ dependencies:
117
117
  version: 0.5.1
118
118
  - - "<"
119
119
  - !ruby/object:Gem::Version
120
- version: 0.8.0
120
+ version: 0.9.0
121
121
  - !ruby/object:Gem::Dependency
122
122
  name: sigdump
123
123
  requirement: !ruby/object:Gem::Requirement
@@ -172,7 +172,7 @@ dependencies:
172
172
  requirements:
173
173
  - - ">="
174
174
  - !ruby/object:Gem::Version
175
- version: 0.2.2
175
+ version: 0.2.4
176
176
  - - "<"
177
177
  - !ruby/object:Gem::Version
178
178
  version: 1.0.0
@@ -182,7 +182,7 @@ dependencies:
182
182
  requirements:
183
183
  - - ">="
184
184
  - !ruby/object:Gem::Version
185
- version: 0.2.2
185
+ version: 0.2.4
186
186
  - - "<"
187
187
  - !ruby/object:Gem::Version
188
188
  version: 1.0.0
@@ -395,6 +395,7 @@ files:
395
395
  - MAINTAINERS.md
396
396
  - README.md
397
397
  - Rakefile
398
+ - SECURITY.md
398
399
  - bin/fluent-binlog-reader
399
400
  - bin/fluent-ca-generate
400
401
  - bin/fluent-cap-ctl
@@ -944,7 +945,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
944
945
  - !ruby/object:Gem::Version
945
946
  version: '0'
946
947
  requirements: []
947
- rubygems_version: 3.1.6
948
+ rubygems_version: 3.1.2
948
949
  signing_key:
949
950
  specification_version: 4
950
951
  summary: Fluentd event collector