fluentd 0.14.17-x64-mingw32 → 1.3.1-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.

Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +16 -5
  3. data/ADOPTERS.md +5 -0
  4. data/{ChangeLog → CHANGELOG.md} +495 -6
  5. data/CONTRIBUTING.md +5 -2
  6. data/GOVERNANCE.md +55 -0
  7. data/LICENSE +202 -0
  8. data/MAINTAINERS.md +7 -5
  9. data/README.md +17 -10
  10. data/bin/fluent-ca-generate +6 -0
  11. data/example/counter.conf +18 -0
  12. data/example/secondary_file.conf +3 -2
  13. data/fluentd.gemspec +3 -3
  14. data/lib/fluent/agent.rb +1 -1
  15. data/lib/fluent/command/binlog_reader.rb +11 -2
  16. data/lib/fluent/command/ca_generate.rb +181 -0
  17. data/lib/fluent/command/cat.rb +28 -15
  18. data/lib/fluent/command/debug.rb +4 -4
  19. data/lib/fluent/command/fluentd.rb +2 -2
  20. data/lib/fluent/command/plugin_config_formatter.rb +24 -2
  21. data/lib/fluent/command/plugin_generator.rb +26 -8
  22. data/lib/fluent/config/configure_proxy.rb +7 -1
  23. data/lib/fluent/config/dsl.rb +8 -5
  24. data/lib/fluent/config/element.rb +5 -0
  25. data/lib/fluent/config/literal_parser.rb +7 -1
  26. data/lib/fluent/config/types.rb +28 -2
  27. data/lib/fluent/config/v1_parser.rb +1 -2
  28. data/lib/fluent/configurable.rb +1 -0
  29. data/lib/fluent/counter.rb +23 -0
  30. data/lib/fluent/counter/base_socket.rb +46 -0
  31. data/lib/fluent/counter/client.rb +297 -0
  32. data/lib/fluent/counter/error.rb +86 -0
  33. data/lib/fluent/counter/mutex_hash.rb +163 -0
  34. data/lib/fluent/counter/server.rb +273 -0
  35. data/lib/fluent/counter/store.rb +205 -0
  36. data/lib/fluent/counter/validator.rb +145 -0
  37. data/lib/fluent/env.rb +1 -0
  38. data/lib/fluent/event_router.rb +1 -1
  39. data/lib/fluent/log.rb +119 -29
  40. data/lib/fluent/plugin/base.rb +12 -0
  41. data/lib/fluent/plugin/buf_file.rb +20 -16
  42. data/lib/fluent/plugin/buffer.rb +130 -32
  43. data/lib/fluent/plugin/buffer/file_chunk.rb +23 -4
  44. data/lib/fluent/plugin/compressable.rb +1 -1
  45. data/lib/fluent/plugin/filter_grep.rb +135 -21
  46. data/lib/fluent/plugin/filter_parser.rb +13 -2
  47. data/lib/fluent/plugin/filter_record_transformer.rb +16 -14
  48. data/lib/fluent/plugin/formatter_stdout.rb +3 -2
  49. data/lib/fluent/plugin/formatter_tsv.rb +5 -1
  50. data/lib/fluent/plugin/in_debug_agent.rb +8 -1
  51. data/lib/fluent/plugin/in_forward.rb +1 -1
  52. data/lib/fluent/plugin/in_http.rb +84 -3
  53. data/lib/fluent/plugin/in_monitor_agent.rb +7 -1
  54. data/lib/fluent/plugin/in_syslog.rb +31 -10
  55. data/lib/fluent/plugin/in_tail.rb +142 -53
  56. data/lib/fluent/plugin/in_tcp.rb +5 -6
  57. data/lib/fluent/plugin/in_udp.rb +6 -2
  58. data/lib/fluent/plugin/in_unix.rb +1 -1
  59. data/lib/fluent/plugin/multi_output.rb +1 -0
  60. data/lib/fluent/plugin/out_copy.rb +25 -2
  61. data/lib/fluent/plugin/out_file.rb +26 -7
  62. data/lib/fluent/plugin/out_forward.rb +81 -42
  63. data/lib/fluent/plugin/out_secondary_file.rb +2 -2
  64. data/lib/fluent/plugin/out_stdout.rb +0 -1
  65. data/lib/fluent/plugin/out_stream.rb +1 -1
  66. data/lib/fluent/plugin/output.rb +221 -57
  67. data/lib/fluent/plugin/parser_apache.rb +1 -1
  68. data/lib/fluent/plugin/parser_apache2.rb +5 -1
  69. data/lib/fluent/plugin/parser_apache_error.rb +1 -1
  70. data/lib/fluent/plugin/parser_json.rb +10 -3
  71. data/lib/fluent/plugin/parser_ltsv.rb +7 -0
  72. data/lib/fluent/plugin/parser_multiline.rb +2 -1
  73. data/lib/fluent/plugin/parser_nginx.rb +1 -1
  74. data/lib/fluent/plugin/parser_none.rb +1 -0
  75. data/lib/fluent/plugin/parser_regexp.rb +15 -14
  76. data/lib/fluent/plugin/parser_syslog.rb +9 -5
  77. data/lib/fluent/plugin_helper.rb +2 -0
  78. data/lib/fluent/plugin_helper/cert_option.rb +28 -9
  79. data/lib/fluent/plugin_helper/compat_parameters.rb +3 -1
  80. data/lib/fluent/plugin_helper/counter.rb +51 -0
  81. data/lib/fluent/plugin_helper/event_loop.rb +9 -0
  82. data/lib/fluent/plugin_helper/record_accessor.rb +210 -0
  83. data/lib/fluent/plugin_helper/retry_state.rb +15 -7
  84. data/lib/fluent/plugin_helper/server.rb +87 -25
  85. data/lib/fluent/plugin_helper/socket_option.rb +5 -2
  86. data/lib/fluent/plugin_helper/timer.rb +8 -7
  87. data/lib/fluent/root_agent.rb +18 -9
  88. data/lib/fluent/supervisor.rb +63 -23
  89. data/lib/fluent/system_config.rb +30 -2
  90. data/lib/fluent/test/helpers.rb +1 -1
  91. data/lib/fluent/time.rb +15 -7
  92. data/lib/fluent/timezone.rb +26 -2
  93. data/lib/fluent/version.rb +1 -1
  94. data/templates/new_gem/README.md.erb +2 -2
  95. data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +1 -1
  96. data/templates/new_gem/lib/fluent/plugin/input.rb.erb +1 -1
  97. data/templates/new_gem/lib/fluent/plugin/output.rb.erb +1 -1
  98. data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +4 -4
  99. data/test/command/test_ca_generate.rb +70 -0
  100. data/test/command/test_fluentd.rb +2 -2
  101. data/test/command/test_plugin_config_formatter.rb +8 -7
  102. data/test/command/test_plugin_generator.rb +65 -39
  103. data/test/config/test_config_parser.rb +7 -2
  104. data/test/config/test_configurable.rb +7 -2
  105. data/test/config/test_configure_proxy.rb +41 -3
  106. data/test/config/test_dsl.rb +10 -10
  107. data/test/config/test_element.rb +10 -0
  108. data/test/config/test_literal_parser.rb +8 -0
  109. data/test/config/test_plugin_configuration.rb +56 -0
  110. data/test/config/test_system_config.rb +19 -1
  111. data/test/config/test_types.rb +37 -0
  112. data/test/counter/test_client.rb +559 -0
  113. data/test/counter/test_error.rb +44 -0
  114. data/test/counter/test_mutex_hash.rb +179 -0
  115. data/test/counter/test_server.rb +589 -0
  116. data/test/counter/test_store.rb +258 -0
  117. data/test/counter/test_validator.rb +137 -0
  118. data/test/plugin/test_buf_file.rb +124 -0
  119. data/test/plugin/test_buffer.rb +3 -2
  120. data/test/plugin/test_filter_grep.rb +580 -2
  121. data/test/plugin/test_filter_parser.rb +33 -2
  122. data/test/plugin/test_filter_record_transformer.rb +22 -1
  123. data/test/plugin/test_formatter_ltsv.rb +3 -0
  124. data/test/plugin/test_formatter_tsv.rb +68 -0
  125. data/test/plugin/test_in_debug_agent.rb +21 -0
  126. data/test/plugin/test_in_exec.rb +3 -5
  127. data/test/plugin/test_in_http.rb +178 -0
  128. data/test/plugin/test_in_monitor_agent.rb +1 -1
  129. data/test/plugin/test_in_syslog.rb +64 -0
  130. data/test/plugin/test_in_tail.rb +116 -6
  131. data/test/plugin/test_in_tcp.rb +21 -0
  132. data/test/plugin/test_in_udp.rb +78 -0
  133. data/test/plugin/test_metadata.rb +89 -0
  134. data/test/plugin/test_out_copy.rb +31 -0
  135. data/test/plugin/test_out_file.rb +108 -2
  136. data/test/plugin/test_out_forward.rb +195 -2
  137. data/test/plugin/test_out_secondary_file.rb +14 -0
  138. data/test/plugin/test_output.rb +159 -45
  139. data/test/plugin/test_output_as_buffered.rb +19 -0
  140. data/test/plugin/test_output_as_buffered_backup.rb +307 -0
  141. data/test/plugin/test_output_as_buffered_retries.rb +70 -0
  142. data/test/plugin/test_output_as_buffered_secondary.rb +1 -1
  143. data/test/plugin/test_parser_apache2.rb +1 -0
  144. data/test/plugin/test_parser_labeled_tsv.rb +17 -0
  145. data/test/plugin/test_parser_nginx.rb +40 -0
  146. data/test/plugin/test_parser_regexp.rb +6 -7
  147. data/test/plugin/test_parser_syslog.rb +155 -5
  148. data/test/plugin_helper/test_child_process.rb +4 -4
  149. data/test/plugin_helper/test_compat_parameters.rb +22 -0
  150. data/test/plugin_helper/test_record_accessor.rb +197 -0
  151. data/test/plugin_helper/test_retry_state.rb +20 -0
  152. data/test/plugin_helper/test_server.rb +30 -2
  153. data/test/test_config.rb +3 -3
  154. data/test/test_configdsl.rb +2 -2
  155. data/test/test_log.rb +51 -1
  156. data/test/test_root_agent.rb +33 -0
  157. data/test/test_supervisor.rb +105 -0
  158. metadata +68 -8
  159. data/COPYING +0 -14
@@ -156,5 +156,36 @@ class CopyOutputTest < Test::Unit::TestCase
156
156
  end
157
157
  end
158
158
  end
159
+
160
+ IGNORE_ERROR_CONFIG = %[
161
+ <store ignore_error>
162
+ @type test
163
+ name c0
164
+ </store>
165
+ <store ignore_error>
166
+ @type test
167
+ name c1
168
+ </store>
169
+ <store>
170
+ @type test
171
+ name c2
172
+ </store>
173
+ ]
174
+
175
+ def test_ignore_error
176
+ d = create_driver(IGNORE_ERROR_CONFIG)
177
+
178
+ # override to raise an error
179
+ d.instance.outputs[0].define_singleton_method(:process) do |tag, es|
180
+ raise ArgumentError, 'Failed'
181
+ end
182
+
183
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
184
+ assert_nothing_raised do
185
+ d.run(default_tag: 'test') do
186
+ d.feed(time, {"a"=>1})
187
+ end
188
+ end
189
+ end
159
190
  end
160
191
 
@@ -304,7 +304,11 @@ class FileOutputTest < Test::Unit::TestCase
304
304
  assert_equal r4, d.formatted[3]
305
305
  assert_equal r5, d.formatted[4]
306
306
 
307
- read_gunzip = ->(path){ File.open(path){|fio| Zlib::GzipReader.open(fio){|io| io.read } } }
307
+ read_gunzip = ->(path){
308
+ File.open(path){ |fio|
309
+ Zlib::GzipReader.new(StringIO.new(fio.read)).read
310
+ }
311
+ }
308
312
  assert_equal r1 + r2, read_gunzip.call("#{TMP_DIR}/my.data/a/full.20161003.2345.log.gz")
309
313
  assert_equal r3, read_gunzip.call("#{TMP_DIR}/your.data/a/full.20161003.2345.log.gz")
310
314
  assert_equal r4, read_gunzip.call("#{TMP_DIR}/my.data/a/full.20161004.0000.log.gz")
@@ -370,7 +374,7 @@ class FileOutputTest < Test::Unit::TestCase
370
374
  result = ''
371
375
  File.open(path, "rb") { |io|
372
376
  loop do
373
- gzr = Zlib::GzipReader.new(io)
377
+ gzr = Zlib::GzipReader.new(StringIO.new(io.read))
374
378
  result << gzr.read
375
379
  unused = gzr.unused
376
380
  gzr.finish
@@ -557,6 +561,108 @@ class FileOutputTest < Test::Unit::TestCase
557
561
  check_gzipped_result(path, formatted_lines * 3)
558
562
  end
559
563
 
564
+ test 'append when JST' do
565
+ with_timezone(Fluent.windows? ? "JST-9" : "Asia/Tokyo") do
566
+ time = event_time("2011-01-02 03:14:15+09:00")
567
+ formatted_lines = %[2011-01-02T03:14:15+09:00\ttest\t{"a":1}\n] + %[2011-01-02T03:14:15+09:00\ttest\t{"a":2}\n]
568
+
569
+ write_once = ->(){
570
+ d = create_driver %[
571
+ path #{TMP_DIR}/out_file_test
572
+ compress gz
573
+ append true
574
+ <buffer>
575
+ timekey_use_utc false
576
+ timekey_zone Asia/Tokyo
577
+ </buffer>
578
+ ]
579
+ d.run(default_tag: 'test'){
580
+ d.feed(time, {"a"=>1})
581
+ d.feed(time, {"a"=>2})
582
+ }
583
+ d.instance.last_written_path
584
+ }
585
+
586
+ path = write_once.call
587
+ assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
588
+ check_gzipped_result(path, formatted_lines)
589
+
590
+ path = write_once.call
591
+ assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
592
+ check_gzipped_result(path, formatted_lines * 2)
593
+
594
+ path = write_once.call
595
+ assert_equal "#{TMP_DIR}/out_file_test.20110102.log.gz", path
596
+ check_gzipped_result(path, formatted_lines * 3)
597
+ end
598
+ end
599
+
600
+ test 'append when UTC-02 but timekey_zone is +0900' do
601
+ with_timezone("UTC-02") do # +0200
602
+ time = event_time("2011-01-02 17:14:15+02:00")
603
+ formatted_lines = %[2011-01-02T17:14:15+02:00\ttest\t{"a":1}\n] + %[2011-01-02T17:14:15+02:00\ttest\t{"a":2}\n]
604
+
605
+ write_once = ->(){
606
+ d = create_driver %[
607
+ path #{TMP_DIR}/out_file_test
608
+ compress gz
609
+ append true
610
+ <buffer>
611
+ timekey_use_utc false
612
+ timekey_zone +0900
613
+ </buffer>
614
+ ]
615
+ d.run(default_tag: 'test'){
616
+ d.feed(time, {"a"=>1})
617
+ d.feed(time, {"a"=>2})
618
+ }
619
+ d.instance.last_written_path
620
+ }
621
+
622
+ path = write_once.call
623
+ # Rotated at 2011-01-02 17:00:00+02:00
624
+ assert_equal "#{TMP_DIR}/out_file_test.20110103.log.gz", path
625
+ check_gzipped_result(path, formatted_lines)
626
+
627
+ path = write_once.call
628
+ assert_equal "#{TMP_DIR}/out_file_test.20110103.log.gz", path
629
+ check_gzipped_result(path, formatted_lines * 2)
630
+
631
+ path = write_once.call
632
+ assert_equal "#{TMP_DIR}/out_file_test.20110103.log.gz", path
633
+ check_gzipped_result(path, formatted_lines * 3)
634
+ end
635
+ end
636
+
637
+ test '${chunk_id}' do
638
+ time = event_time("2011-01-02 13:14:15 UTC")
639
+ formatted_lines = %[2011-01-02T13:14:15Z\ttest\t{"a":1}\n] + %[2011-01-02T13:14:15Z\ttest\t{"a":2}\n]
640
+
641
+ write_once = ->(){
642
+ d = create_driver %[
643
+ path #{TMP_DIR}/out_file_chunk_id_${chunk_id}
644
+ utc
645
+ append true
646
+ <buffer>
647
+ timekey_use_utc true
648
+ </buffer>
649
+ ]
650
+ d.run(default_tag: 'test'){
651
+ d.feed(time, {"a"=>1})
652
+ d.feed(time, {"a"=>2})
653
+ }
654
+ d.instance.last_written_path
655
+ }
656
+
657
+ path = write_once.call
658
+ if File.basename(path) =~ /out_file_chunk_id_([-_.@a-zA-Z0-9].*).20110102.log/
659
+ unique_id = Fluent::UniqueId.hex(Fluent::UniqueId.generate)
660
+ assert_equal unique_id.size, $1.size, "chunk_id size is mismatched"
661
+ else
662
+ flunk "chunk_id is not included in the path"
663
+ end
664
+ end
665
+
560
666
  test 'symlink' do
561
667
  omit "Windows doesn't support symlink" if Fluent.windows?
562
668
  conf = CONFIG + %[
@@ -9,6 +9,8 @@ require 'fluent/plugin/in_forward'
9
9
  class ForwardOutputTest < Test::Unit::TestCase
10
10
  def setup
11
11
  Fluent::Test.setup
12
+ FileUtils.rm_rf(TMP_DIR)
13
+ FileUtils.mkdir_p(TMP_DIR)
12
14
  @d = nil
13
15
  end
14
16
 
@@ -16,6 +18,8 @@ class ForwardOutputTest < Test::Unit::TestCase
16
18
  @d.instance_shutdown if @d
17
19
  end
18
20
 
21
+ TMP_DIR = File.join(__dir__, "../tmp/out_forward#{ENV['TEST_ENV_NUMBER']}")
22
+
19
23
  TARGET_HOST = '127.0.0.1'
20
24
  TARGET_PORT = unused_port
21
25
  CONFIG = %[
@@ -153,6 +157,27 @@ EOL
153
157
  assert{ logs.any?{|log| log.include?(expected_log) && log.include?(expected_detail) } }
154
158
  end
155
159
 
160
+ data('CA cert' => 'tls_ca_cert_path',
161
+ 'non CA cert' => 'tls_cert_path')
162
+ test 'configure tls_cert_path/tls_ca_cert_path' do |param|
163
+ dummy_cert_path = File.join(TMP_DIR, "dummy_cert.pem")
164
+ FileUtils.touch(dummy_cert_path)
165
+ conf = %[
166
+ send_timeout 5
167
+ transport tls
168
+ tls_insecure_mode true
169
+ #{param} #{dummy_cert_path}
170
+ <server>
171
+ host #{TARGET_HOST}
172
+ port #{TARGET_PORT}
173
+ </server>
174
+ ]
175
+
176
+ @d = d = create_driver(conf)
177
+ # In the plugin, tls_ca_cert_path is used for both cases
178
+ assert_equal([dummy_cert_path], d.instance.tls_ca_cert_path)
179
+ end
180
+
156
181
  test 'compress_default_value' do
157
182
  @d = d = create_driver
158
183
  assert_equal :text, d.instance.compress
@@ -217,6 +242,18 @@ EOL
217
242
  assert_equal 2, d.instance.ack_response_timeout
218
243
  end
219
244
 
245
+ test 'verify_connection_at_startup is disabled in default' do
246
+ @d = d = create_driver(CONFIG)
247
+ assert_false d.instance.verify_connection_at_startup
248
+ end
249
+
250
+ test 'verify_connection_at_startup can be enabled' do
251
+ @d = d = create_driver(CONFIG + %[
252
+ verify_connection_at_startup true
253
+ ])
254
+ assert_true d.instance.verify_connection_at_startup
255
+ end
256
+
220
257
  test 'send tags in str (utf-8 strings)' do
221
258
  target_input_driver = create_target_input_driver
222
259
 
@@ -486,6 +523,7 @@ EOL
486
523
  retry_type periodic
487
524
  retry_wait 30s
488
525
  flush_at_shutdown false # suppress errors in d.instance_shutdown
526
+ flush_thread_interval 30s
489
527
  </buffer>
490
528
  ])
491
529
 
@@ -501,7 +539,7 @@ EOL
501
539
  target_input_driver.end_if{ d.instance.rollback_count > 0 }
502
540
  target_input_driver.end_if{ !node.available }
503
541
  target_input_driver.run(expect_records: 2, timeout: 25) do
504
- d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false) do
542
+ d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false, flush: false) do
505
543
  delayed_commit_timeout_value = d.instance.delayed_commit_timeout
506
544
  d.feed([[time, records[0]], [time,records[1]]])
507
545
  end
@@ -530,6 +568,7 @@ EOL
530
568
  retry_type periodic
531
569
  retry_wait 30s
532
570
  flush_at_shutdown false # suppress errors in d.instance_shutdown
571
+ flush_thread_interval 30s
533
572
  </buffer>
534
573
  ])
535
574
 
@@ -545,7 +584,7 @@ EOL
545
584
  target_input_driver.end_if{ d.instance.rollback_count > 0 }
546
585
  target_input_driver.end_if{ !node.available }
547
586
  target_input_driver.run(expect_records: 2, timeout: 25) do
548
- d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false) do
587
+ d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false, flush: false) do
549
588
  delayed_commit_timeout_value = d.instance.delayed_commit_timeout
550
589
  d.feed([[time, records[0]], [time,records[1]]])
551
590
  end
@@ -664,6 +703,51 @@ EOL
664
703
  assert_equal(['test', time, records[1]], events[1])
665
704
  end
666
705
 
706
+ # This test is not 100% but test failed with previous Node implementation which has race condition
707
+ test 'Node with security is thread-safe on multi threads' do
708
+ input_conf = TARGET_CONFIG + %[
709
+ <security>
710
+ self_hostname in.localhost
711
+ shared_key fluentd-sharedkey
712
+ <client>
713
+ host 127.0.0.1
714
+ </client>
715
+ </security>
716
+ ]
717
+ target_input_driver = create_target_input_driver(conf: input_conf)
718
+ output_conf = %[
719
+ send_timeout 51
720
+ <security>
721
+ self_hostname localhost
722
+ shared_key fluentd-sharedkey
723
+ </security>
724
+ <server>
725
+ name test
726
+ host #{TARGET_HOST}
727
+ port #{TARGET_PORT}
728
+ shared_key fluentd-sharedkey
729
+ </server>
730
+ ]
731
+ @d = d = create_driver(output_conf)
732
+
733
+ chunk = Fluent::Plugin::Buffer::MemoryChunk.new(Fluent::Plugin::Buffer::Metadata.new(nil, nil, nil))
734
+ target_input_driver.run(timeout: 15) do
735
+ d.run(shutdown: false) do
736
+ node = d.instance.nodes.first
737
+ arr = []
738
+ 4.times {
739
+ arr << Thread.new {
740
+ node.send_data('test', chunk) rescue nil
741
+ }
742
+ }
743
+ arr.each { |a| a.join }
744
+ end
745
+ end
746
+
747
+ logs = d.logs
748
+ assert_false(logs.any? { |log| log.include?("invalid format for PONG message") || log.include?("shared key mismatch") }, "'#{logs.last.strip}' happens")
749
+ end
750
+
667
751
  def create_target_input_driver(response_stub: nil, disconnect: false, conf: TARGET_CONFIG)
668
752
  require 'fluent/plugin/in_forward'
669
753
 
@@ -727,4 +811,113 @@ EOL
727
811
  i.configure(conf)
728
812
  end
729
813
  end
814
+
815
+ sub_test_case 'verify_connection_at_startup' do
816
+ test 'nodes are not available' do
817
+ @d = d = create_driver(CONFIG + %[
818
+ verify_connection_at_startup true
819
+ <buffer tag>
820
+ flush_mode immediate
821
+ retry_type periodic
822
+ retry_wait 30s
823
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
824
+ </buffer>
825
+ ])
826
+ assert_raise Fluent::UnrecoverableError do
827
+ d.instance_start
828
+ end
829
+ d.instance_shutdown
830
+ end
831
+
832
+ test 'nodes_shared_key_miss_match' do
833
+ input_conf = TARGET_CONFIG + %[
834
+ <security>
835
+ self_hostname in.localhost
836
+ shared_key fluentd-sharedkey
837
+ </security>
838
+ ]
839
+ target_input_driver = create_target_input_driver(conf: input_conf)
840
+ output_conf = %[
841
+ send_timeout 30
842
+ heartbeat_type transport
843
+ transport tls
844
+ tls_verify_hostname false
845
+ verify_connection_at_startup true
846
+ require_ack_response true
847
+ ack_response_timeout 5s
848
+ <security>
849
+ self_hostname localhost
850
+ shared_key key_miss_match
851
+ </security>
852
+ <buffer tag>
853
+ flush_mode immediate
854
+ retry_type periodic
855
+ retry_wait 30s
856
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
857
+ flush_thread_interval 31s
858
+ </buffer>
859
+
860
+ <server>
861
+ host #{TARGET_HOST}
862
+ port #{TARGET_PORT}
863
+ </server>
864
+ ]
865
+ @d = d = create_driver(output_conf)
866
+
867
+ target_input_driver.run(expect_records: 1, timeout: 15) do
868
+ assert_raise Fluent::UnrecoverableError do
869
+ d.instance_start
870
+ end
871
+ d.instance_shutdown
872
+ end
873
+ end
874
+
875
+ test 'nodes_shared_key_match' do
876
+ input_conf = TARGET_CONFIG + %[
877
+ <security>
878
+ self_hostname in.localhost
879
+ shared_key fluentd-sharedkey
880
+ <client>
881
+ host 127.0.0.1
882
+ </client>
883
+ </security>
884
+ ]
885
+ target_input_driver = create_target_input_driver(conf: input_conf)
886
+
887
+ output_conf = %[
888
+ send_timeout 51
889
+ verify_connection_at_startup true
890
+ <security>
891
+ self_hostname localhost
892
+ shared_key fluentd-sharedkey
893
+ </security>
894
+ <server>
895
+ name test
896
+ host #{TARGET_HOST}
897
+ port #{TARGET_PORT}
898
+ shared_key fluentd-sharedkey
899
+ </server>
900
+ ]
901
+ @d = d = create_driver(output_conf)
902
+
903
+ time = event_time("2011-01-02 13:14:15 UTC")
904
+ records = [
905
+ {"a" => 1},
906
+ {"a" => 2}
907
+ ]
908
+
909
+ target_input_driver.run(expect_records: 2, timeout: 15) do
910
+ d.run(default_tag: 'test') do
911
+ records.each do |record|
912
+ d.feed(time, record)
913
+ end
914
+ end
915
+ end
916
+
917
+ events = target_input_driver.events
918
+ assert{ events != [] }
919
+ assert_equal(['test', time, records[0]], events[0])
920
+ assert_equal(['test', time, records[1]], events[1])
921
+ end
922
+ end
730
923
  end
@@ -260,6 +260,20 @@ class FileOutputSecondaryTest < Test::Unit::TestCase
260
260
  assert_equal "#{TMP_DIR}/dump.bin", path
261
261
  end
262
262
 
263
+ test 'path with ${chunk_id}' do
264
+ d = create_driver %[
265
+ directory #{TMP_DIR}
266
+ basename out_file_chunk_id_${chunk_id}
267
+ ]
268
+ path = d.instance.write(@c)
269
+ if File.basename(path) =~ /out_file_chunk_id_([-_.@a-zA-Z0-9].*).0/
270
+ unique_id = Fluent::UniqueId.hex(Fluent::UniqueId.generate)
271
+ assert_equal unique_id.size, $1.size, "chunk_id size is mismatched"
272
+ else
273
+ flunk "chunk_id is not included in the path"
274
+ end
275
+ end
276
+
263
277
  data(
264
278
  invalid_tag: [/tag/, '${tag}'],
265
279
  invalid_tag0: [/tag\[0\]/, '${tag[0]}'],
@@ -125,6 +125,10 @@ class OutputTest < Test::Unit::TestCase
125
125
  def create_metadata(timekey: nil, tag: nil, variables: nil)
126
126
  Fluent::Plugin::Buffer::Metadata.new(timekey, tag, variables)
127
127
  end
128
+ def create_chunk(timekey: nil, tag: nil, variables: nil)
129
+ m = Fluent::Plugin::Buffer::Metadata.new(timekey, tag, variables)
130
+ Fluent::Plugin::Buffer::MemoryChunk.new(m)
131
+ end
128
132
  def waiting(seconds)
129
133
  begin
130
134
  Timeout.timeout(seconds) do
@@ -219,7 +223,9 @@ class OutputTest < Test::Unit::TestCase
219
223
  assert @i.terminated?
220
224
  end
221
225
 
222
- test '#extract_placeholders does nothing if chunk key is not specified' do
226
+ data(:new_api => :chunk,
227
+ :old_api => :metadata)
228
+ test '#extract_placeholders does nothing if chunk key is not specified' do |api|
223
229
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
224
230
  assert !@i.chunk_key_time
225
231
  assert !@i.chunk_key_tag
@@ -227,11 +233,17 @@ class OutputTest < Test::Unit::TestCase
227
233
  tmpl = "/mypath/%Y/%m/%d/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
228
234
  t = event_time('2016-04-11 20:30:00 +0900')
229
235
  v = {key1: "value1", key2: "value2"}
230
- m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
231
- assert_equal tmpl, @i.extract_placeholders(tmpl, m)
236
+ c = if api == :chunk
237
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
238
+ else
239
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
240
+ end
241
+ assert_equal tmpl, @i.extract_placeholders(tmpl, c)
232
242
  end
233
243
 
234
- test '#extract_placeholders can extract time if time key and range are configured' do
244
+ data(:new_api => :chunk,
245
+ :old_api => :metadata)
246
+ test '#extract_placeholders can extract time if time key and range are configured' do |api|
235
247
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
236
248
  assert @i.chunk_key_time
237
249
  assert !@i.chunk_key_tag
@@ -239,11 +251,17 @@ class OutputTest < Test::Unit::TestCase
239
251
  tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
240
252
  t = event_time('2016-04-11 20:30:00 +0900')
241
253
  v = {key1: "value1", key2: "value2"}
242
- m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
243
- assert_equal "/mypath/2016/04/11/20-30/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail", @i.extract_placeholders(tmpl, m)
254
+ c = if api == :chunk
255
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
256
+ else
257
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
258
+ end
259
+ assert_equal "/mypath/2016/04/11/20-30/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail", @i.extract_placeholders(tmpl, c)
244
260
  end
245
261
 
246
- test '#extract_placeholders can extract tag and parts of tag if tag is configured' do
262
+ data(:new_api => :chunk,
263
+ :old_api => :metadata)
264
+ test '#extract_placeholders can extract tag and parts of tag if tag is configured' do |api|
247
265
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag', {})]))
248
266
  assert !@i.chunk_key_time
249
267
  assert @i.chunk_key_tag
@@ -251,11 +269,17 @@ class OutputTest < Test::Unit::TestCase
251
269
  tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
252
270
  t = event_time('2016-04-11 20:30:00 +0900')
253
271
  v = {key1: "value1", key2: "value2"}
254
- m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
255
- assert_equal "/mypath/%Y/%m/%d/%H-%M/fluentd.test.output/test/output/${key1}/${key2}/tail", @i.extract_placeholders(tmpl, m)
272
+ c = if api == :chunk
273
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
274
+ else
275
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
276
+ end
277
+ assert_equal "/mypath/%Y/%m/%d/%H-%M/fluentd.test.output/test/output/${key1}/${key2}/tail", @i.extract_placeholders(tmpl, c)
256
278
  end
257
279
 
258
- test '#extract_placeholders can extract variables if variables are configured' do
280
+ data(:new_api => :chunk,
281
+ :old_api => :metadata)
282
+ test '#extract_placeholders can extract variables if variables are configured' do |api|
259
283
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'key1,key2', {})]))
260
284
  assert !@i.chunk_key_time
261
285
  assert !@i.chunk_key_tag
@@ -263,32 +287,95 @@ class OutputTest < Test::Unit::TestCase
263
287
  tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
264
288
  t = event_time('2016-04-11 20:30:00 +0900')
265
289
  v = {key1: "value1", key2: "value2"}
266
- m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
267
- assert_equal "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/value1/value2/tail", @i.extract_placeholders(tmpl, m)
290
+ c = if api == :chunk
291
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
292
+ else
293
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
294
+ end
295
+ assert_equal "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/value1/value2/tail", @i.extract_placeholders(tmpl, c)
296
+ end
297
+
298
+ data(:new_api => :chunk,
299
+ :old_api => :metadata)
300
+ test '#extract_placeholders can extract nested variables if variables are configured with dot notation' do |api|
301
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'key,$.nest.key', {})]))
302
+ assert !@i.chunk_key_time
303
+ assert !@i.chunk_key_tag
304
+ assert_equal ['key','$.nest.key'], @i.chunk_keys
305
+ tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key}/${$.nest.key}/tail"
306
+ t = event_time('2016-04-11 20:30:00 +0900')
307
+ v = {:key => "value1", :"$.nest.key" => "value2"}
308
+ c = if api == :chunk
309
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
310
+ else
311
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
312
+ end
313
+ assert_equal "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/value1/value2/tail", @i.extract_placeholders(tmpl, c)
314
+ end
315
+
316
+ data(:new_api => :chunk,
317
+ :old_api => :metadata)
318
+ test '#extract_placeholders can extract all chunk keys if configured' do |api|
319
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
320
+ assert @i.chunk_key_time
321
+ assert @i.chunk_key_tag
322
+ assert_equal ['key1','key2'], @i.chunk_keys
323
+ tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
324
+ t = event_time('2016-04-11 20:30:00 +0900')
325
+ v = {key1: "value1", key2: "value2"}
326
+ c = if api == :chunk
327
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
328
+ else
329
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
330
+ end
331
+ assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/test/output/value1/value2/tail", @i.extract_placeholders(tmpl, c)
268
332
  end
269
333
 
270
- test '#extract_placeholders can extract all chunk keys if configured' do
334
+ data(:new_api => :chunk,
335
+ :old_api => :metadata)
336
+ test '#extract_placeholders can extract negative index with tag' do |api|
271
337
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
272
338
  assert @i.chunk_key_time
273
339
  assert @i.chunk_key_tag
274
340
  assert_equal ['key1','key2'], @i.chunk_keys
275
- tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
341
+ tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[-1]}/${tag[-2]}/${key1}/${key2}/tail"
276
342
  t = event_time('2016-04-11 20:30:00 +0900')
277
343
  v = {key1: "value1", key2: "value2"}
278
- m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
279
- assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/test/output/value1/value2/tail", @i.extract_placeholders(tmpl, m)
344
+ c = if api == :chunk
345
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
346
+ else
347
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
348
+ end
349
+ assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/output/test/value1/value2/tail", @i.extract_placeholders(tmpl, c)
280
350
  end
281
351
 
282
- test '#extract_placeholders removes out-of-range tag part and unknown variable placeholders' do
352
+ data(:new_api => :chunk,
353
+ :old_api => :metadata)
354
+ test '#extract_placeholders removes out-of-range tag part and unknown variable placeholders' do |api|
283
355
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
284
356
  assert @i.chunk_key_time
285
357
  assert @i.chunk_key_tag
286
358
  assert_equal ['key1','key2'], @i.chunk_keys
287
- tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[3]}/${tag[4]}/${key3}/${key4}/tail"
359
+ tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[3]}/${tag[-4]}/${key3}/${key4}/tail"
360
+ t = event_time('2016-04-11 20:30:00 +0900')
361
+ v = {key1: "value1", key2: "value2"}
362
+ c = if api == :chunk
363
+ create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
364
+ else
365
+ create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
366
+ end
367
+ assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/////tail", @i.extract_placeholders(tmpl, c)
368
+ end
369
+
370
+ test '#extract_placeholders logs warn message if metadata is passed for ${chunk_id} placeholder' do
371
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
372
+ tmpl = "/mypath/${chunk_id}/tail"
288
373
  t = event_time('2016-04-11 20:30:00 +0900')
289
374
  v = {key1: "value1", key2: "value2"}
290
375
  m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
291
- assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/////tail", @i.extract_placeholders(tmpl, m)
376
+ @i.extract_placeholders(tmpl, m)
377
+ logs = @i.log.out.logs
378
+ assert { logs.any? { |log| log.include?("${chunk_id} is not allowed in this plugin") } }
292
379
  end
293
380
 
294
381
  sub_test_case '#placeholder_validators' do
@@ -372,7 +459,7 @@ class OutputTest < Test::Unit::TestCase
372
459
  end
373
460
 
374
461
  sub_test_case '#placeholder_validate!' do
375
- test 'raises configuration error for a templace when timestamp placeholders exist but time key is missing' do
462
+ test 'raises configuration error for a template when timestamp placeholders exist but time key is missing' do
376
463
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
377
464
  assert_raise Fluent::ConfigError.new("Parameter 'path: /path/without/timestamp/file.%Y%m%d-%H%M.log' has timestamp placeholders, but chunk key 'time' is not configured") do
378
465
  @i.placeholder_validate!(:path, "/path/without/timestamp/file.%Y%m%d-%H%M.log")
@@ -414,6 +501,9 @@ class OutputTest < Test::Unit::TestCase
414
501
  assert_nothing_raised do
415
502
  @i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[2]}.log")
416
503
  end
504
+ assert_nothing_raised do
505
+ @i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[-1]}.log")
506
+ end
417
507
  end
418
508
 
419
509
  test 'raises configuration error for a template when variable key placeholders exist but chunk keys are missing' do
@@ -493,11 +583,21 @@ class OutputTest < Test::Unit::TestCase
493
583
  assert_equal ['.hidden', '0001', '@timestamp', 'a_key', 'my-domain'], @i.get_placeholders_keys("http://${my-domain}/${.hidden}/${0001}/${a_key}?timestamp=${@timestamp}")
494
584
  end
495
585
 
586
+ data('include space' => 'ke y',
587
+ 'bracket notation' => "$['key']",
588
+ 'invalid notation' => "$.ke y")
589
+ test 'configure checks invalid chunk keys' do |chunk_keys|
590
+ i = create_output(:buffered)
591
+ assert_raise Fluent::ConfigError do
592
+ i.configure(config_element('ROOT' , '', {}, [config_element('buffer', chunk_keys)]))
593
+ end
594
+ end
595
+
496
596
  test '#metadata returns object which contains tag/timekey/variables from records as specified in configuration' do
497
597
  tag = 'test.output'
498
598
  time = event_time('2016-04-12 15:31:23 -0700')
499
599
  timekey = event_time('2016-04-12 15:00:00 -0700')
500
- record = {"key1" => "value1", "num1" => 1, "message" => "my message"}
600
+ record = {"key1" => "value1", "num1" => 1, "message" => "my message", "nest" => {"key" => "nested value"}}
501
601
 
502
602
  i1 = create_output(:buffered)
503
603
  i1.configure(config_element('ROOT','',{},[config_element('buffer', '')]))
@@ -530,6 +630,10 @@ class OutputTest < Test::Unit::TestCase
530
630
  i8 = create_output(:buffered)
531
631
  i8.configure(config_element('ROOT','',{},[config_element('buffer', 'time,tag,key1', {"timekey" => 3600, "timekey_zone" => "-0700"})]))
532
632
  assert_equal create_metadata(timekey: timekey, tag: tag, variables: {key1: "value1"}), i8.metadata(tag, time, record)
633
+
634
+ i9 = create_output(:buffered)
635
+ i9.configure(config_element('ROOT','',{},[config_element('buffer', 'key1,$.nest.key', {})]))
636
+ assert_equal create_metadata(variables: {:key1 => "value1", :"$.nest.key" => 'nested value'}), i9.metadata(tag, time, record)
533
637
  end
534
638
 
535
639
  test '#emit calls #process via #emit_sync for non-buffered output' do
@@ -724,34 +828,43 @@ class OutputTest < Test::Unit::TestCase
724
828
  assert_equal :interval, @i.instance_variable_get(:@flush_mode)
725
829
  end
726
830
 
727
- test "Warn if primary type is different from secondary type and either primary or secondary has custom_format" do
728
- o = create_output(:buffered)
729
- mock(o.log).warn("secondary type should be same with primary one",
730
- { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" })
831
+ sub_test_case 'configure secondary' do
832
+ test "Warn if primary type is different from secondary type and either primary or secondary has custom_format" do
833
+ o = create_output(:buffered)
834
+ mock(o.log).warn("secondary type should be same with primary one",
835
+ { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" })
731
836
 
732
- o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
733
- assert_not_nil o.instance_variable_get(:@secondary)
734
- end
837
+ o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
838
+ assert_not_nil o.instance_variable_get(:@secondary)
839
+ end
735
840
 
736
- test "don't warn if primary type is the same as secondary type" do
737
- o = Fluent::Plugin::TestOutput.new
738
- mock(o.log).warn("secondary type should be same with primary one",
739
- { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
841
+ test "don't warn if primary type is the same as secondary type" do
842
+ o = Fluent::Plugin::TestOutput.new
843
+ mock(o.log).warn("secondary type should be same with primary one",
844
+ { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
740
845
 
741
- o.configure(config_element('ROOT','',{'name' => "cool2"},
742
- [config_element('secondary','',{'@type'=>'test', 'name' => "cool"}),
743
- config_element('buffer','',{'@type'=>'memory'})]
744
- ))
745
- assert_not_nil o.instance_variable_get(:@secondary)
746
- end
846
+ o.configure(config_element('ROOT','',{'name' => "cool2"},
847
+ [config_element('secondary','',{'@type'=>'test', 'name' => "cool"}),
848
+ config_element('buffer','',{'@type'=>'memory'})]
849
+ ))
850
+ assert_not_nil o.instance_variable_get(:@secondary)
851
+ end
747
852
 
748
- test "don't warn if primary type is different from secondary type and both don't have custom_format" do
749
- o = create_output(:standard)
750
- mock(o.log).warn("secondary type should be same with primary one",
751
- { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
853
+ test "don't warn if primary type is different from secondary type and both don't have custom_format" do
854
+ o = create_output(:standard)
855
+ mock(o.log).warn("secondary type should be same with primary one",
856
+ { primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
752
857
 
753
- o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
754
- assert_not_nil o.instance_variable_get(:@secondary)
858
+ o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
859
+ assert_not_nil o.instance_variable_get(:@secondary)
860
+ end
861
+
862
+ test "raise configuration error if secondary type specifies non buffered output" do
863
+ o = create_output(:standard)
864
+ assert_raise Fluent::ConfigError do
865
+ o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'copy'})]))
866
+ end
867
+ end
755
868
  end
756
869
  end
757
870
 
@@ -824,7 +937,8 @@ class OutputTest < Test::Unit::TestCase
824
937
 
825
938
  sub_test_case 'slow_flush_log_threshold' do
826
939
  def invoke_slow_flush_log_threshold_test(i)
827
- i.configure(config_element('ROOT', '', {'slow_flush_log_threshold' => 0.5}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
940
+ i.configure(config_element('ROOT', '', {'slow_flush_log_threshold' => 0.5},
941
+ [config_element('buffer', '', {"flush_mode" => "immediate", "flush_thread_interval" => 30})]))
828
942
  i.start
829
943
  i.after_start
830
944