fluentd 0.14.13-x86-mingw32 → 0.14.17-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of fluentd might be problematic. Click here for more details.

Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -5
  3. data/ChangeLog +106 -0
  4. data/MAINTAINERS.md +5 -0
  5. data/README.md +25 -0
  6. data/example/worker_section.conf +36 -0
  7. data/fluentd.gemspec +1 -1
  8. data/lib/fluent/agent.rb +5 -2
  9. data/lib/fluent/command/binlog_reader.rb +1 -0
  10. data/lib/fluent/command/fluentd.rb +28 -12
  11. data/lib/fluent/command/plugin_config_formatter.rb +0 -1
  12. data/lib/fluent/command/plugin_generator.rb +1 -1
  13. data/lib/fluent/compat/detach_process_mixin.rb +8 -0
  14. data/lib/fluent/compat/input.rb +0 -10
  15. data/lib/fluent/compat/output.rb +0 -10
  16. data/lib/fluent/config/element.rb +22 -0
  17. data/lib/fluent/config/literal_parser.rb +2 -0
  18. data/lib/fluent/config/types.rb +2 -2
  19. data/lib/fluent/engine.rb +27 -10
  20. data/lib/fluent/env.rb +3 -3
  21. data/lib/fluent/log.rb +4 -1
  22. data/lib/fluent/plugin/base.rb +3 -0
  23. data/lib/fluent/plugin/filter.rb +2 -2
  24. data/lib/fluent/plugin/filter_parser.rb +17 -6
  25. data/lib/fluent/plugin/in_forward.rb +1 -1
  26. data/lib/fluent/plugin/in_http.rb +4 -0
  27. data/lib/fluent/plugin/in_monitor_agent.rb +8 -3
  28. data/lib/fluent/plugin/in_syslog.rb +3 -2
  29. data/lib/fluent/plugin/in_tail.rb +14 -3
  30. data/lib/fluent/plugin/in_udp.rb +6 -2
  31. data/lib/fluent/plugin/out_file.rb +5 -0
  32. data/lib/fluent/plugin/out_forward.rb +5 -2
  33. data/lib/fluent/plugin/output.rb +13 -8
  34. data/lib/fluent/plugin/parser_apache2.rb +1 -1
  35. data/lib/fluent/plugin/parser_syslog.rb +40 -1
  36. data/lib/fluent/plugin_helper/cert_option.rb +2 -2
  37. data/lib/fluent/plugin_helper/compat_parameters.rb +1 -1
  38. data/lib/fluent/plugin_helper/storage.rb +1 -1
  39. data/lib/fluent/root_agent.rb +36 -4
  40. data/lib/fluent/supervisor.rb +37 -6
  41. data/lib/fluent/system_config.rb +7 -0
  42. data/lib/fluent/time.rb +1 -0
  43. data/lib/fluent/version.rb +1 -1
  44. data/lib/fluent/winsvc.rb +25 -11
  45. data/test/command/test_fluentd.rb +253 -4
  46. data/test/config/test_element.rb +63 -0
  47. data/test/config/test_literal_parser.rb +1 -1
  48. data/test/config/test_system_config.rb +36 -6
  49. data/test/config/test_types.rb +19 -0
  50. data/test/plugin/test_filter_parser.rb +35 -0
  51. data/test/plugin/test_in_http.rb +58 -4
  52. data/test/plugin/test_in_monitor_agent.rb +90 -9
  53. data/test/plugin/test_in_tail.rb +16 -0
  54. data/test/plugin/test_in_udp.rb +11 -1
  55. data/test/plugin/test_out_file.rb +9 -0
  56. data/test/plugin/test_out_forward.rb +45 -0
  57. data/test/plugin/test_output.rb +15 -15
  58. data/test/plugin/test_output_as_buffered.rb +30 -2
  59. data/test/plugin/test_parser_apache2.rb +8 -0
  60. data/test/plugin/test_parser_syslog.rb +176 -0
  61. data/test/plugin_helper/test_server.rb +37 -31
  62. data/test/plugin_helper/test_storage.rb +9 -0
  63. data/test/test_log.rb +6 -0
  64. data/test/test_plugin_classes.rb +50 -0
  65. data/test/test_root_agent.rb +245 -14
  66. data/test/test_time_parser.rb +12 -0
  67. metadata +13 -5
@@ -662,4 +662,39 @@ class ParserFilterTest < Test::Unit::TestCase
662
662
  end
663
663
  end
664
664
  end
665
+
666
+ class EmitInvalidRecordToErrorTest < self
667
+ def test_pattern_is_mismached_with_emit_invalid_record_to_error
668
+ d = create_driver(CONFIG_UNMATCHED_PATTERN_LOG + "emit_invalid_record_to_error false")
669
+ flexmock(d.instance.router).should_receive(:emit_error_event).never
670
+ assert_nothing_raised {
671
+ d.run do
672
+ d.feed(@tag, Fluent::EventTime.now.to_i, {'message' => INVALID_MESSAGE})
673
+ end
674
+ }
675
+ assert_equal 0, d.filtered.length
676
+ end
677
+
678
+ def test_parser_error_with_emit_invalid_record_to_error
679
+ d = create_driver(CONFIG_INVALID_TIME_VALUE + "emit_invalid_record_to_error false")
680
+ flexmock(d.instance.router).should_receive(:emit_error_event).never
681
+ assert_nothing_raised {
682
+ d.run do
683
+ d.feed(@tag, Fluent::EventTime.now.to_i, {'data' => '{"time":[], "f1":"v1"}'})
684
+ end
685
+ }
686
+ assert_equal 0, d.filtered.length
687
+ end
688
+
689
+ def test_key_not_exist_with_emit_invalid_record_to_error
690
+ d = create_driver(CONFIG_NOT_IGNORE + "emit_invalid_record_to_error false")
691
+ flexmock(d.instance.router).should_receive(:emit_error_event).never
692
+ assert_nothing_raised {
693
+ d.run do
694
+ d.feed(@tag, Fluent::EventTime.now.to_i, {'foo' => 'bar'})
695
+ end
696
+ }
697
+ assert_equal 0, d.filtered.length
698
+ end
699
+ end
665
700
  end
@@ -215,14 +215,14 @@ class HttpInputTest < Test::Unit::TestCase
215
215
  def test_multi_json_with_add_remote_addr_given_x_forwarded_for
216
216
  d = create_driver(CONFIG + "add_remote_addr true")
217
217
 
218
+ tag = "tag1"
218
219
  time = event_time("2011-01-02 13:14:15 UTC")
219
220
  time_i = time.to_i
220
221
  records = [{"a"=>1},{"a"=>2}]
221
222
  events = [
222
- ["tag1", time, {"REMOTE_ADDR"=>"129.78.138.66", "a"=>1}],
223
- ["tag1", time, {"REMOTE_ADDR"=>"129.78.138.66", "a"=>2}],
223
+ [tag, time, {"REMOTE_ADDR"=>"129.78.138.66", "a"=>1}],
224
+ [tag, time, {"REMOTE_ADDR"=>"129.78.138.66", "a"=>2}],
224
225
  ]
225
- tag = "tag1"
226
226
  res_codes = []
227
227
 
228
228
  d.run(expect_records: 2, timeout: 5) do
@@ -235,6 +235,37 @@ class HttpInputTest < Test::Unit::TestCase
235
235
  assert_equal_event_time time, d.events[1][1]
236
236
  end
237
237
 
238
+ def test_add_remote_addr_given_multi_x_forwarded_for
239
+ d = create_driver(CONFIG + "add_remote_addr true")
240
+
241
+ tag = "tag1"
242
+ time = event_time("2011-01-02 13:14:15 UTC")
243
+ time_i = time.to_i
244
+ record = {"a" => 1}
245
+ event = ["tag1", time, {"REMOTE_ADDR" => "129.78.138.66", "a" => 1}]
246
+ res_code = nil
247
+
248
+ d.run(expect_records: 1, timeout: 5) do
249
+ res = post("/#{tag}", {"json" => record.to_json, "time" => time_i.to_s}) { |http, req|
250
+ # net/http can't send multiple headers so overwrite it.
251
+ def req.each_capitalized
252
+ block_given? or return enum_for(__method__) { @header.size }
253
+ @header.each do |k, vs|
254
+ vs.each { |v|
255
+ yield capitalize(k), v
256
+ }
257
+ end
258
+ end
259
+ req.add_field("X-Forwarded-For", "129.78.138.66, 127.0.0.1")
260
+ req.add_field("X-Forwarded-For", "8.8.8.8")
261
+ }
262
+ res_code = res.code
263
+ end
264
+ assert_equal "200", res_code
265
+ assert_equal event, d.events.first
266
+ assert_equal_event_time time, d.events.first[1]
267
+ end
268
+
238
269
  def test_multi_json_with_add_http_headers
239
270
  d = create_driver(CONFIG + "add_http_headers true")
240
271
  time = event_time("2011-01-02 13:14:15 UTC")
@@ -313,6 +344,28 @@ class HttpInputTest < Test::Unit::TestCase
313
344
  assert_equal_event_time time, d.events[1][1]
314
345
  end
315
346
 
347
+ def test_application_msgpack
348
+ d = create_driver
349
+ time = event_time("2011-01-02 13:14:15 UTC")
350
+ time_i = time.to_i
351
+ events = [
352
+ ["tag1", time, {"a"=>1}],
353
+ ["tag2", time, {"a"=>2}],
354
+ ]
355
+ res_codes = []
356
+
357
+ d.run(expect_records: 2) do
358
+ events.each do |tag, t, record|
359
+ res = post("/#{tag}?time=#{time_i.to_s}", record.to_msgpack, {"Content-Type"=>"application/msgpack"})
360
+ res_codes << res.code
361
+ end
362
+ end
363
+ assert_equal ["200", "200"], res_codes
364
+ assert_equal events, d.events
365
+ assert_equal_event_time time, d.events[0][1]
366
+ assert_equal_event_time time, d.events[1][1]
367
+ end
368
+
316
369
  def test_msgpack
317
370
  d = create_driver
318
371
  time = event_time("2011-01-02 13:14:15 UTC")
@@ -543,9 +596,10 @@ class HttpInputTest < Test::Unit::TestCase
543
596
  assert_equal $test_in_http_connection_object_ids[0], $test_in_http_connection_object_ids[1]
544
597
  end
545
598
 
546
- def post(path, params, header = {})
599
+ def post(path, params, header = {}, &block)
547
600
  http = Net::HTTP.new("127.0.0.1", PORT)
548
601
  req = Net::HTTP::Post.new(path, header)
602
+ block.call(http, req) if block
549
603
  if params.is_a?(String)
550
604
  unless header.has_key?('Content-Type')
551
605
  header['Content-Type'] = 'application/octet-stream'
@@ -204,10 +204,9 @@ EOC
204
204
  unless header.has_key?('Content-Type')
205
205
  header['Content-Type'] = 'application/octet-stream'
206
206
  end
207
- res = Net::HTTP.start(url.host, url.port) {|http|
207
+ Net::HTTP.start(url.host, url.port) {|http|
208
208
  http.request(req)
209
209
  }
210
- res.body
211
210
  end
212
211
 
213
212
  sub_test_case "servlets" do
@@ -268,7 +267,7 @@ plugin_id:test_in\tplugin_category:input\ttype:test_in\toutput_plugin:false\tret
268
267
  expected_test_filter_response = "\
269
268
  plugin_id:test_filter\tplugin_category:filter\ttype:test_filter\toutput_plugin:false\tretry_count:"
270
269
 
271
- response = get("http://127.0.0.1:#{@port}/api/plugins")
270
+ response = get("http://127.0.0.1:#{@port}/api/plugins").body
272
271
  test_in = response.split("\n")[0]
273
272
  test_filter = response.split("\n")[3]
274
273
  assert_equal(expected_test_in_response, test_in)
@@ -306,7 +305,7 @@ plugin_id:test_filter\tplugin_category:filter\ttype:test_filter\toutput_plugin:f
306
305
  }
307
306
  expected_null_response.merge!("config" => {"@id" => "null", "@type" => "null"}) if with_config
308
307
  expected_null_response.merge!("retry" => {}) if with_retry
309
- response = JSON.parse(get("http://127.0.0.1:#{@port}/api/plugins.json"))
308
+ response = JSON.parse(get("http://127.0.0.1:#{@port}/api/plugins.json").body)
310
309
  test_in_response = response["plugins"][0]
311
310
  null_response = response["plugins"][5]
312
311
  assert_equal(expected_test_in_response, test_in_response)
@@ -343,7 +342,7 @@ plugin_id:test_filter\tplugin_category:filter\ttype:test_filter\toutput_plugin:f
343
342
  }
344
343
  expected_null_response.merge!("config" => {"@id" => "null", "@type" => "null"}) if with_config
345
344
  expected_null_response.merge!("retry" => {}) if with_retry
346
- response = JSON.parse(get("http://127.0.0.1:#{@port}/api/plugins.json#{query_param}"))
345
+ response = JSON.parse(get("http://127.0.0.1:#{@port}/api/plugins.json#{query_param}").body)
347
346
  test_in_response = response["plugins"][0]
348
347
  null_response = response["plugins"][5]
349
348
  assert_equal(expected_test_in_response, test_in_response)
@@ -376,7 +375,7 @@ plugin_id:test_filter\tplugin_category:filter\ttype:test_filter\toutput_plugin:f
376
375
  "type" => "null",
377
376
  "instance_variables" => {"id" => "null", "num_errors" => 0}
378
377
  }
379
- response = JSON.parse(get("http://127.0.0.1:#{@port}/api/plugins.json?with_config=no&with_retry=no&with_ivars=id,num_errors"))
378
+ response = JSON.parse(get("http://127.0.0.1:#{@port}/api/plugins.json?with_config=no&with_retry=no&with_ivars=id,num_errors").body)
380
379
  test_in_response = response["plugins"][0]
381
380
  null_response = response["plugins"][5]
382
381
  assert_equal(expected_test_in_response, test_in_response)
@@ -394,7 +393,7 @@ plugin_id:test_filter\tplugin_category:filter\ttype:test_filter\toutput_plugin:f
394
393
  expected_response_regex = /pid:\d+\tppid:\d+\tconfig_path:\/etc\/fluent\/fluent.conf\tpid_file:\tplugin_dirs:\[\"\/etc\/fluent\/plugin\"\]\tlog_path:/
395
394
 
396
395
  assert_match(expected_response_regex,
397
- get("http://127.0.0.1:#{@port}/api/config"))
396
+ get("http://127.0.0.1:#{@port}/api/config").body)
398
397
  end
399
398
 
400
399
  test "/api/config.json" do
@@ -405,7 +404,7 @@ plugin_id:test_filter\tplugin_category:filter\ttype:test_filter\toutput_plugin:f
405
404
  tag monitor
406
405
  ")
407
406
  d.instance.start
408
- res = JSON.parse(get("http://127.0.0.1:#{@port}/api/config.json"))
407
+ res = JSON.parse(get("http://127.0.0.1:#{@port}/api/config.json").body)
409
408
  assert_equal("/etc/fluent/fluent.conf", res["config_path"])
410
409
  assert_nil(res["pid_file"])
411
410
  assert_equal(["/etc/fluent/plugin"], res["plugin_dirs"])
@@ -474,7 +473,7 @@ plugin_id:test_filter\tplugin_category:filter\ttype:test_filter\toutput_plugin:f
474
473
  output.submit_flush_once
475
474
  sleep 0.1 until output.buffer.queued?
476
475
  end
477
- response = JSON.parse(get("http://127.0.0.1:#{@port}/api/plugins.json"))
476
+ response = JSON.parse(get("http://127.0.0.1:#{@port}/api/plugins.json").body)
478
477
  test_out_fail_write_response = response["plugins"][1]
479
478
  # remove dynamic keys
480
479
  response_retry_count = test_out_fail_write_response.delete("retry_count")
@@ -486,4 +485,86 @@ plugin_id:test_filter\tplugin_category:filter\ttype:test_filter\toutput_plugin:f
486
485
  assert{ response_retry_count == response_retry["steps"] + 1 }
487
486
  end
488
487
  end
488
+
489
+ sub_test_case "check the port number of http server" do
490
+ test "on single worker environment" do
491
+ port = unused_port
492
+ d = create_driver("
493
+ @type monitor_agent
494
+ bind '127.0.0.1'
495
+ port #{port}
496
+ ")
497
+ d.instance.start
498
+ assert_equal("200", get("http://127.0.0.1:#{port}/api/plugins").code)
499
+ end
500
+
501
+ test "worker_id = 2 on multi worker environment" do
502
+ port = unused_port
503
+ Fluent::SystemConfig.overwrite_system_config('workers' => 4) do
504
+ d = Fluent::Test::Driver::Input.new(Fluent::Plugin::MonitorAgentInput)
505
+ d.instance.instance_eval{ @_fluentd_worker_id = 2 }
506
+ d.configure("
507
+ @type monitor_agent
508
+ bind '127.0.0.1'
509
+ port #{port - 2}
510
+ ")
511
+ d.instance.start
512
+ end
513
+ assert_equal("200", get("http://127.0.0.1:#{port}/api/plugins").code)
514
+ end
515
+ end
516
+
517
+ sub_test_case "check NoMethodError does not happen" do
518
+ class FluentTestBufferVariableOutput < ::Fluent::Plugin::Output
519
+ ::Fluent::Plugin.register_output('test_out_buffer_variable', self)
520
+ def configure(conf)
521
+ super
522
+ @buffer = []
523
+ end
524
+
525
+ def write(chunk)
526
+ end
527
+ end
528
+ class FluentTestBufferVariableFilter < ::Fluent::Plugin::Filter
529
+ ::Fluent::Plugin.register_filter("test_filter_buffer_variable", self)
530
+ def initialize
531
+ super
532
+ @buffer = {}
533
+ end
534
+ def filter(tag, time, record)
535
+ record
536
+ end
537
+ end
538
+
539
+ setup do
540
+ conf = <<-EOC
541
+ <match **>
542
+ @type test_out_buffer_variable
543
+ @id test_out_buffer_variable
544
+ </match>
545
+ <filter **>
546
+ @type test_filter_buffer_variable
547
+ @id test_filter_buffer_variable
548
+ </filter>
549
+ EOC
550
+ @ra = Fluent::RootAgent.new(log: $log)
551
+ stub(Fluent::Engine).root_agent { @ra }
552
+ @ra = configure_ra(@ra, conf)
553
+ end
554
+
555
+ test "plugins have a variable named buffer does not throws NoMethodError" do
556
+ port = unused_port
557
+ d = create_driver("
558
+ @type monitor_agent
559
+ bind '127.0.0.1'
560
+ port #{port}
561
+ include_config no
562
+ ")
563
+ d.instance.start
564
+
565
+ assert_equal("200", get("http://127.0.0.1:#{port}/api/plugins.json").code)
566
+ assert{ d.logs.none?{|log| log.include?("NoMethodError") } }
567
+ assert_equal(false, d.instance.instance_variable_get(:@first_warn))
568
+ end
569
+ end
489
570
  end
@@ -72,6 +72,7 @@ class TailInputTest < Test::Unit::TestCase
72
72
  assert_equal 2, d.instance.rotate_wait
73
73
  assert_equal "#{TMP_DIR}/tail.pos", d.instance.pos_file
74
74
  assert_equal 1000, d.instance.read_lines_limit
75
+ assert_equal false, d.instance.ignore_repeated_permission_error
75
76
  end
76
77
 
77
78
  data("empty" => config_element,
@@ -1198,4 +1199,19 @@ class TailInputTest < Test::Unit::TestCase
1198
1199
  assert_equal expected_files, plugin.expand_paths.sort
1199
1200
  end
1200
1201
  end
1202
+
1203
+ def test_skip_refresh_on_startup
1204
+ FileUtils.touch("#{TMP_DIR}/tail.txt")
1205
+ config = config_element('', '', {
1206
+ 'format' => 'none',
1207
+ 'refresh_interval' => 1,
1208
+ 'skip_refresh_on_startup' => true
1209
+ })
1210
+ d = create_driver(config)
1211
+ d.run(shutdown: false) {}
1212
+ assert_equal 0, d.instance.instance_variable_get(:@tails).keys.size
1213
+ # detect a file at first execution of in_tail_refresh_watchers timer
1214
+ waiting(5) { sleep 0.1 until d.instance.instance_variable_get(:@tails).keys.size == 1 }
1215
+ d.instance_shutdown
1216
+ end
1201
1217
  end
@@ -54,7 +54,7 @@ class UdpInputTest < Test::Unit::TestCase
54
54
  d = create_driver(conf)
55
55
  assert_equal PORT, d.instance.port
56
56
  assert_equal bind, d.instance.bind
57
- assert_equal 4096, d.instance.body_size_limit
57
+ assert_equal 4096, d.instance.message_length_limit
58
58
  end
59
59
 
60
60
  data(
@@ -86,6 +86,16 @@ class UdpInputTest < Test::Unit::TestCase
86
86
  end
87
87
  end
88
88
 
89
+ data(
90
+ 'message_length_limit' => 'message_length_limit 2048',
91
+ 'body_size_limit' => 'body_size_limit 2048'
92
+ )
93
+ test 'message_length_limit/body_size_limit compatibility' do |param|
94
+
95
+ d = create_driver(CONFIG + param)
96
+ assert_equal 2048, d.instance.message_length_limit
97
+ end
98
+
89
99
  data(
90
100
  'none' => {
91
101
  'format' => 'none',
@@ -20,6 +20,9 @@ class FileOutputTest < Test::Unit::TestCase
20
20
  path #{TMP_DIR}/out_file_test
21
21
  compress gz
22
22
  utc
23
+ <buffer>
24
+ timekey_use_utc true
25
+ </buffer>
23
26
  ]
24
27
 
25
28
  def create_driver(conf = CONFIG, opts = {})
@@ -405,6 +408,9 @@ class FileOutputTest < Test::Unit::TestCase
405
408
  path #{TMP_DIR_WITH_SYSTEM}/out_file_test
406
409
  compress gz
407
410
  utc
411
+ <buffer>
412
+ timekey_use_utc true
413
+ </buffer>
408
414
  <system>
409
415
  file_permission #{OVERRIDE_FILE_PERMISSION}
410
416
  dir_permission #{OVERRIDE_DIR_PERMISSION}
@@ -527,6 +533,9 @@ class FileOutputTest < Test::Unit::TestCase
527
533
  compress gz
528
534
  utc
529
535
  append true
536
+ <buffer>
537
+ timekey_use_utc true
538
+ </buffer>
530
539
  ]
531
540
  d.run(default_tag: 'test'){
532
541
  d.feed(time, {"a"=>1})
@@ -430,6 +430,51 @@ EOL
430
430
  assert_empty d.instance.exceptions
431
431
  end
432
432
 
433
+ data('ack true' => true,
434
+ 'ack false' => false)
435
+ test 'TLS transport and ack parameter combination' do |ack|
436
+ omit "TLS and 'ack false' always fails on AppVeyor. Need to debug" if Fluent.windows? && !ack
437
+
438
+ input_conf = TARGET_CONFIG + %[
439
+ <transport tls>
440
+ insecure true
441
+ </transport>
442
+ ]
443
+ target_input_driver = create_target_input_driver(conf: input_conf)
444
+
445
+ output_conf = %[
446
+ send_timeout 5
447
+ require_ack_response #{ack}
448
+ transport tls
449
+ tls_insecure_mode true
450
+ <server>
451
+ host #{TARGET_HOST}
452
+ port #{TARGET_PORT}
453
+ </server>
454
+ <buffer>
455
+ #flush_mode immediate
456
+ flush_interval 0s
457
+ flush_at_shutdown false # suppress errors in d.instance_shutdown
458
+ </buffer>
459
+ ]
460
+ @d = d = create_driver(output_conf)
461
+
462
+ time = event_time("2011-01-02 13:14:15 UTC")
463
+ records = [{"a" => 1}, {"a" => 2}]
464
+ target_input_driver.run(expect_records: 2, timeout: 3) do
465
+ d.run(default_tag: 'test', wait_flush_completion: false, shutdown: false) do
466
+ records.each do |record|
467
+ d.feed(time, record)
468
+ end
469
+ end
470
+ end
471
+
472
+ events = target_input_driver.events
473
+ assert{ events != [] }
474
+ assert_equal(['test', time, records[0]], events[0])
475
+ assert_equal(['test', time, records[1]], events[1])
476
+ end
477
+
433
478
  test 'a destination node not supporting responses by just ignoring' do
434
479
  target_input_driver = create_target_input_driver(response_stub: ->(_option) { nil }, disconnect: false)
435
480
 
@@ -315,7 +315,7 @@ class OutputTest < Test::Unit::TestCase
315
315
  validators = @i.placeholder_validators(:path, "/my/path/file.%Y-%m-%d.log")
316
316
  assert_equal 1, validators.size
317
317
  assert_equal 1, validators.select(&:time?).size
318
- assert_raise Fluent::ConfigError.new("Parameter 'path' has timestamp placeholders, but chunk key 'time' is not configured") do
318
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.%Y-%m-%d.log' has timestamp placeholders, but chunk key 'time' is not configured") do
319
319
  validators.first.validate!
320
320
  end
321
321
  end
@@ -325,7 +325,7 @@ class OutputTest < Test::Unit::TestCase
325
325
  validators = @i.placeholder_validators(:path, "/my/path/to/file.log")
326
326
  assert_equal 1, validators.size
327
327
  assert_equal 1, validators.select(&:time?).size
328
- assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have timestamp placeholders for timekey 30") do
328
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/to/file.log' doesn't have timestamp placeholders for timekey 30") do
329
329
  validators.first.validate!
330
330
  end
331
331
  end
@@ -335,7 +335,7 @@ class OutputTest < Test::Unit::TestCase
335
335
  validators = @i.placeholder_validators(:path, "/my/path/${tag}/file.log")
336
336
  assert_equal 1, validators.size
337
337
  assert_equal 1, validators.select(&:tag?).size
338
- assert_raise Fluent::ConfigError.new("Parameter 'path' has tag placeholders, but chunk key 'tag' is not configured") do
338
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${tag}/file.log' has tag placeholders, but chunk key 'tag' is not configured") do
339
339
  validators.first.validate!
340
340
  end
341
341
  end
@@ -345,7 +345,7 @@ class OutputTest < Test::Unit::TestCase
345
345
  validators = @i.placeholder_validators(:path, "/my/path/file.log")
346
346
  assert_equal 1, validators.size
347
347
  assert_equal 1, validators.select(&:tag?).size
348
- assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have tag placeholder") do
348
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have tag placeholder") do
349
349
  validators.first.validate!
350
350
  end
351
351
  end
@@ -355,7 +355,7 @@ class OutputTest < Test::Unit::TestCase
355
355
  validators = @i.placeholder_validators(:path, "/my/path/${username}/file.${group}.log")
356
356
  assert_equal 1, validators.size
357
357
  assert_equal 1, validators.select(&:keys?).size
358
- assert_raise Fluent::ConfigError.new("Parameter 'path' has placeholders, but chunk keys doesn't have keys group,username") do
358
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${username}/file.${group}.log' has placeholders, but chunk keys doesn't have keys group,username") do
359
359
  validators.first.validate!
360
360
  end
361
361
  end
@@ -365,7 +365,7 @@ class OutputTest < Test::Unit::TestCase
365
365
  validators = @i.placeholder_validators(:path, "/my/path/file.log")
366
366
  assert_equal 1, validators.size
367
367
  assert_equal 1, validators.select(&:keys?).size
368
- assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have enough placeholders for keys group,username") do
368
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have enough placeholders for keys group,username") do
369
369
  validators.first.validate!
370
370
  end
371
371
  end
@@ -374,14 +374,14 @@ class OutputTest < Test::Unit::TestCase
374
374
  sub_test_case '#placeholder_validate!' do
375
375
  test 'raises configuration error for a templace when timestamp placeholders exist but time key is missing' do
376
376
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
377
- assert_raise Fluent::ConfigError.new("Parameter 'path' has timestamp placeholders, but chunk key 'time' is not configured") do
377
+ 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
378
  @i.placeholder_validate!(:path, "/path/without/timestamp/file.%Y%m%d-%H%M.log")
379
379
  end
380
380
  end
381
381
 
382
382
  test 'raises configuration error for a template without timestamp placeholders when timekey is configured' do
383
383
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {"timekey" => 180})]))
384
- assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have timestamp placeholders for timekey 180") do
384
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have timestamp placeholders for timekey 180") do
385
385
  @i.placeholder_validate!(:path, "/my/path/file.log")
386
386
  end
387
387
  assert_nothing_raised do
@@ -391,7 +391,7 @@ class OutputTest < Test::Unit::TestCase
391
391
 
392
392
  test 'raises configuration error for a template with timestamp placeholders when plugin is configured more fine timekey' do
393
393
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {"timekey" => 180})]))
394
- assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have timestamp placeholder for hour('%H') for timekey 180") do
394
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.%Y%m%d_%H.log' doesn't have timestamp placeholder for hour('%H') for timekey 180") do
395
395
  @i.placeholder_validate!(:path, "/my/path/file.%Y%m%d_%H.log")
396
396
  end
397
397
  assert_nothing_raised do
@@ -401,14 +401,14 @@ class OutputTest < Test::Unit::TestCase
401
401
 
402
402
  test 'raises configuration error for a template when tag placeholders exist but tag key is missing' do
403
403
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
404
- assert_raise Fluent::ConfigError.new("Parameter 'path' has tag placeholders, but chunk key 'tag' is not configured") do
404
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${tag}/file.${tag[2]}.log' has tag placeholders, but chunk key 'tag' is not configured") do
405
405
  @i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[2]}.log")
406
406
  end
407
407
  end
408
408
 
409
409
  test 'raises configuration error for a template without tag placeholders when tagkey is configured' do
410
410
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag')]))
411
- assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have tag placeholder") do
411
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have tag placeholder") do
412
412
  @i.placeholder_validate!(:path, "/my/path/file.log")
413
413
  end
414
414
  assert_nothing_raised do
@@ -418,14 +418,14 @@ class OutputTest < Test::Unit::TestCase
418
418
 
419
419
  test 'raises configuration error for a template when variable key placeholders exist but chunk keys are missing' do
420
420
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
421
- assert_raise Fluent::ConfigError.new("Parameter 'path' has placeholders, but chunk keys doesn't have keys service,username") do
421
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${service}/file.${username}.log' has placeholders, but chunk keys doesn't have keys service,username") do
422
422
  @i.placeholder_validate!(:path, "/my/path/${service}/file.${username}.log")
423
423
  end
424
424
  end
425
425
 
426
426
  test 'raises configuration error for a template without variable key placeholders when chunk keys are configured' do
427
427
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,service')]))
428
- assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have enough placeholders for keys service,username") do
428
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have enough placeholders for keys service,username") do
429
429
  @i.placeholder_validate!(:path, "/my/path/file.log")
430
430
  end
431
431
  assert_nothing_raised do
@@ -435,10 +435,10 @@ class OutputTest < Test::Unit::TestCase
435
435
 
436
436
  test 'raise configuration error for a template and configuration with keys mismatch' do
437
437
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,service')]))
438
- assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have enough placeholders for keys service") do
438
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.${username}.log' doesn't have enough placeholders for keys service") do
439
439
  @i.placeholder_validate!(:path, "/my/path/file.${username}.log")
440
440
  end
441
- assert_raise Fluent::ConfigError.new("Parameter 'path' doesn't have enough placeholders for keys username") do
441
+ assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${service}/file.log' doesn't have enough placeholders for keys username") do
442
442
  @i.placeholder_validate!(:path, "/my/path/${service}/file.log")
443
443
  end
444
444
  assert_nothing_raised do