fluentd 1.14.1 → 1.14.5

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 (47) 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 +94 -0
  5. data/README.md +3 -22
  6. data/Rakefile +1 -1
  7. data/SECURITY.md +18 -0
  8. data/fluentd.gemspec +5 -4
  9. data/lib/fluent/command/cat.rb +13 -3
  10. data/lib/fluent/config/error.rb +12 -0
  11. data/lib/fluent/env.rb +4 -0
  12. data/lib/fluent/plugin/base.rb +1 -1
  13. data/lib/fluent/plugin/buf_file.rb +2 -2
  14. data/lib/fluent/plugin/buffer.rb +62 -8
  15. data/lib/fluent/plugin/in_http.rb +11 -1
  16. data/lib/fluent/plugin/in_tail.rb +21 -4
  17. data/lib/fluent/plugin/out_file.rb +13 -1
  18. data/lib/fluent/plugin/output.rb +11 -6
  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_helper/socket.rb +13 -2
  22. data/lib/fluent/plugin_id.rb +2 -1
  23. data/lib/fluent/registry.rb +2 -1
  24. data/lib/fluent/supervisor.rb +2 -2
  25. data/lib/fluent/time.rb +21 -20
  26. data/lib/fluent/version.rb +1 -1
  27. data/test/command/test_cat.rb +31 -2
  28. data/test/compat/test_parser.rb +1 -1
  29. data/test/plugin/test_bare_output.rb +1 -1
  30. data/test/plugin/test_buffer.rb +149 -1
  31. data/test/plugin/test_filter.rb +1 -1
  32. data/test/plugin/test_filter_parser.rb +1 -1
  33. data/test/plugin/test_filter_stdout.rb +2 -2
  34. data/test/plugin/test_in_http.rb +23 -0
  35. data/test/plugin/test_in_tail.rb +90 -6
  36. data/test/plugin/test_input.rb +1 -1
  37. data/test/plugin/test_out_exec.rb +6 -4
  38. data/test/plugin/test_out_exec_filter.rb +4 -0
  39. data/test/plugin/test_out_file.rb +29 -13
  40. data/test/plugin/test_out_stdout.rb +2 -2
  41. data/test/plugin/test_output_as_buffered_retries.rb +47 -0
  42. data/test/plugin/test_output_as_buffered_secondary.rb +1 -1
  43. data/test/plugin_helper/test_child_process.rb +9 -9
  44. data/test/plugin_helper/test_timer.rb +2 -2
  45. data/test/test_formatter.rb +1 -1
  46. data/test/test_time_parser.rb +22 -0
  47. metadata +24 -9
@@ -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
@@ -1658,6 +1707,41 @@ class TailInputTest < Test::Unit::TestCase
1658
1707
  mock(plugin.router).emit_stream('pre.foo.bar.log.post', anything).once
1659
1708
  plugin.receive_lines(['foo', 'bar'], DummyWatcher.new('foo.bar.log'))
1660
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
1661
1745
  end
1662
1746
 
1663
1747
  # Ensure that no fatal exception is raised when a file is missing and that
@@ -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
@@ -32,7 +32,7 @@ class StdoutOutputTest < Test::Unit::TestCase
32
32
  assert_kind_of Fluent::Plugin::StdoutFormatter, d.instance.formatter
33
33
  assert_equal 'hash', d.instance.formatter.output_type
34
34
 
35
- assert_raise(Fluent::ConfigError) do
35
+ assert_raise(Fluent::NotFoundPluginError) do
36
36
  d = create_driver(CONFIG + "\noutput_type foo")
37
37
  end
38
38
  end
@@ -126,7 +126,7 @@ class StdoutOutputTest < Test::Unit::TestCase
126
126
  assert_kind_of Fluent::Plugin::StdoutFormatter, d.instance.formatter
127
127
  assert_equal 'hash', d.instance.formatter.output_type
128
128
 
129
- assert_raise(Fluent::ConfigError) do
129
+ assert_raise(Fluent::NotFoundPluginError) do
130
130
  create_driver(config_element("ROOT", "", {"output_type" => "foo"}, [config_element("buffer")]))
131
131
  end
132
132
  end
@@ -701,6 +701,53 @@ class BufferedOutputRetryTest < Test::Unit::TestCase
701
701
  assert{ @i.buffer.stage.size == 1 }
702
702
  assert{ chunks.all?{|c| c.empty? } }
703
703
  end
704
+
705
+ test 'Do not retry when retry_max_times is 0' do
706
+ written_tags = []
707
+
708
+ chunk_key = 'tag'
709
+ hash = {
710
+ 'flush_interval' => 1,
711
+ 'flush_thread_burst_interval' => 0.1,
712
+ 'retry_type' => :periodic,
713
+ 'retry_wait' => 1,
714
+ 'retry_randomize' => false,
715
+ 'retry_max_times' => 0,
716
+ 'queued_chunks_limit_size' => 100
717
+ }
718
+ @i.configure(config_element('ROOT','',{},[config_element('buffer',chunk_key,hash)]))
719
+ @i.register(:prefer_buffered_processing){ true }
720
+ @i.register(:format){|tag,time,record| [tag,time.to_i,record].to_json + "\n" }
721
+ @i.register(:write){|chunk| written_tags << chunk.metadata.tag; raise "yay, your #write must fail" }
722
+ @i.start
723
+ @i.after_start
724
+
725
+ @i.interrupt_flushes
726
+
727
+ now = Time.parse('2016-04-13 18:33:30 -0700')
728
+ Timecop.freeze( now )
729
+
730
+ @i.emit_events("test.tag.1", dummy_event_stream())
731
+
732
+ now = Time.parse('2016-04-13 18:33:31 -0700')
733
+ Timecop.freeze( now )
734
+
735
+ @i.emit_events("test.tag.2", dummy_event_stream())
736
+
737
+ assert_equal(0, @i.write_count)
738
+ assert_equal(0, @i.num_errors)
739
+
740
+ @i.enqueue_thread_wait
741
+ @i.flush_thread_wakeup
742
+ waiting(2){ Thread.pass until @i.write_count == 1 && @i.num_errors == 1 }
743
+
744
+ assert(@i.write_count == 1)
745
+ assert(@i.num_errors == 1)
746
+ assert(@i.log.out.logs.any?{|l| l.include?("[error]: failed to flush the buffer, and hit limit for retries. dropping all chunks in the buffer queue.") && l.include?("retry_times=0") })
747
+ assert(@i.buffer.queue.size == 0)
748
+ assert(@i.buffer.stage.size == 1)
749
+ assert(@i.buffer.queue.all?{|c| c.empty? })
750
+ end
704
751
  end
705
752
 
706
753
  sub_test_case 'buffered output configured as retry_forever' 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
@@ -349,7 +349,7 @@ module FormatterTest
349
349
  include FormatterTest
350
350
 
351
351
  def test_unknown_format
352
- assert_raise ConfigError do
352
+ assert_raise NotFoundPluginError do
353
353
  Fluent::Plugin.new_formatter('unknown')
354
354
  end
355
355
  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.1
4
+ version: 1.14.5
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-09-29 00:00:00.000000000 Z
11
+ date: 2022-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -84,7 +84,7 @@ dependencies:
84
84
  requirements:
85
85
  - - ">="
86
86
  - !ruby/object:Gem::Version
87
- version: 2.2.2
87
+ version: 2.2.5
88
88
  - - "<"
89
89
  - !ruby/object:Gem::Version
90
90
  version: 3.0.0
@@ -94,7 +94,7 @@ dependencies:
94
94
  requirements:
95
95
  - - ">="
96
96
  - !ruby/object:Gem::Version
97
- version: 2.2.2
97
+ version: 2.2.5
98
98
  - - "<"
99
99
  - !ruby/object:Gem::Version
100
100
  version: 3.0.0
@@ -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
@@ -338,6 +338,20 @@ dependencies:
338
338
  - - "<"
339
339
  - !ruby/object:Gem::Version
340
340
  version: '4'
341
+ - !ruby/object:Gem::Dependency
342
+ name: async
343
+ requirement: !ruby/object:Gem::Requirement
344
+ requirements:
345
+ - - "~>"
346
+ - !ruby/object:Gem::Version
347
+ version: '1.23'
348
+ type: :development
349
+ prerelease: false
350
+ version_requirements: !ruby/object:Gem::Requirement
351
+ requirements:
352
+ - - "~>"
353
+ - !ruby/object:Gem::Version
354
+ version: '1.23'
341
355
  - !ruby/object:Gem::Dependency
342
356
  name: async-http
343
357
  requirement: !ruby/object:Gem::Requirement
@@ -395,6 +409,7 @@ files:
395
409
  - MAINTAINERS.md
396
410
  - README.md
397
411
  - Rakefile
412
+ - SECURITY.md
398
413
  - bin/fluent-binlog-reader
399
414
  - bin/fluent-ca-generate
400
415
  - bin/fluent-cap-ctl
@@ -944,7 +959,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
944
959
  - !ruby/object:Gem::Version
945
960
  version: '0'
946
961
  requirements: []
947
- rubygems_version: 3.1.6
962
+ rubygems_version: 3.3.3
948
963
  signing_key:
949
964
  specification_version: 4
950
965
  summary: Fluentd event collector