fluentd 1.16.5-x64-mingw32 → 1.16.7-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +8 -1
  3. data/CHANGELOG.md +50 -0
  4. data/README.md +0 -2
  5. data/fluentd.gemspec +9 -1
  6. data/lib/fluent/command/fluentd.rb +1 -1
  7. data/lib/fluent/config/yaml_parser/parser.rb +4 -0
  8. data/lib/fluent/plugin/out_file.rb +8 -0
  9. data/lib/fluent/plugin/parser_json.rb +4 -12
  10. data/lib/fluent/supervisor.rb +1 -1
  11. data/lib/fluent/version.rb +1 -1
  12. data/lib/fluent/winsvc.rb +28 -3
  13. data/test/command/test_cat.rb +2 -2
  14. data/test/command/test_fluentd.rb +57 -10
  15. data/test/helper.rb +27 -7
  16. data/test/plugin/in_tail/test_io_handler.rb +13 -14
  17. data/test/plugin/in_tail/test_position_file.rb +6 -7
  18. data/test/plugin/out_forward/test_ack_handler.rb +3 -3
  19. data/test/plugin/out_forward/test_socket_cache.rb +3 -3
  20. data/test/plugin/test_in_forward.rb +2 -1
  21. data/test/plugin/test_in_http.rb +1 -1
  22. data/test/plugin/test_in_monitor_agent.rb +6 -6
  23. data/test/plugin/test_in_syslog.rb +25 -18
  24. data/test/plugin/test_in_tail.rb +4 -12
  25. data/test/plugin/test_in_tcp.rb +1 -1
  26. data/test/plugin/test_in_udp.rb +16 -10
  27. data/test/plugin/test_out_exec_filter.rb +12 -7
  28. data/test/plugin/test_out_file.rb +22 -2
  29. data/test/plugin/test_out_forward.rb +2 -3
  30. data/test/plugin/test_out_stream.rb +1 -1
  31. data/test/plugin/test_parser_json.rb +31 -0
  32. data/test/plugin_helper/test_http_server_helper.rb +1 -1
  33. data/test/plugin_helper/test_server.rb +64 -41
  34. data/test/plugin_helper/test_socket.rb +1 -1
  35. data/test/test_config.rb +6 -0
  36. data/test/test_event_router.rb +2 -2
  37. metadata +37 -9
@@ -5,24 +5,24 @@ require 'fluent/plugin/in_syslog'
5
5
  class SyslogInputTest < Test::Unit::TestCase
6
6
  def setup
7
7
  Fluent::Test.setup
8
- @port = unused_port
8
+ @port = unused_port(protocol: :udp)
9
9
  end
10
10
 
11
11
  def teardown
12
12
  @port = nil
13
13
  end
14
14
 
15
- def ipv4_config
15
+ def ipv4_config(port = @port)
16
16
  %[
17
- port #{@port}
17
+ port #{port}
18
18
  bind 127.0.0.1
19
19
  tag syslog
20
20
  ]
21
21
  end
22
22
 
23
- def ipv6_config
23
+ def ipv6_config(port = @port)
24
24
  %[
25
- port #{@port}
25
+ port #{port}
26
26
  bind ::1
27
27
  tag syslog
28
28
  ]
@@ -69,7 +69,8 @@ EOS
69
69
  'Use transport and protocol' => ["protocol_type udp\n<transport tcp>\n </transport>", :udp, :tcp])
70
70
  def test_configure_protocol(param)
71
71
  conf, proto_type, transport_proto_type = *param
72
- d = create_driver([ipv4_config, conf].join("\n"))
72
+ port = unused_port(protocol: proto_type ? proto_type : transport_proto_type)
73
+ d = create_driver([ipv4_config(port), conf].join("\n"))
73
74
 
74
75
  assert_equal(d.instance.protocol_type, proto_type)
75
76
  assert_equal(d.instance.transport_config.protocol, transport_proto_type)
@@ -158,12 +159,13 @@ EOS
158
159
  end
159
160
 
160
161
  def test_msg_size_with_tcp
161
- d = create_driver([ipv4_config, "<transport tcp> \n</transport>"].join("\n"))
162
+ port = unused_port(protocol: :tcp)
163
+ d = create_driver([ipv4_config(port), "<transport tcp> \n</transport>"].join("\n"))
162
164
  tests = create_test_case
163
165
 
164
166
  d.run(expect_emits: 2) do
165
167
  tests.each {|test|
166
- TCPSocket.open('127.0.0.1', @port) do |s|
168
+ TCPSocket.open('127.0.0.1', port) do |s|
167
169
  s.send(test['msg'], 0)
168
170
  end
169
171
  }
@@ -189,11 +191,12 @@ EOS
189
191
  end
190
192
 
191
193
  def test_msg_size_with_same_tcp_connection
192
- d = create_driver([ipv4_config, "<transport tcp> \n</transport>"].join("\n"))
194
+ port = unused_port(protocol: :tcp)
195
+ d = create_driver([ipv4_config(port), "<transport tcp> \n</transport>"].join("\n"))
193
196
  tests = create_test_case
194
197
 
195
198
  d.run(expect_emits: 2) do
196
- TCPSocket.open('127.0.0.1', @port) do |s|
199
+ TCPSocket.open('127.0.0.1', port) do |s|
197
200
  tests.each {|test|
198
201
  s.send(test['msg'], 0)
199
202
  }
@@ -347,12 +350,13 @@ EOS
347
350
 
348
351
  sub_test_case 'octet counting frame' do
349
352
  def test_msg_size_with_tcp
350
- d = create_driver([ipv4_config, "<transport tcp> \n</transport>", 'frame_type octet_count'].join("\n"))
353
+ port = unused_port(protocol: :tcp)
354
+ d = create_driver([ipv4_config(port), "<transport tcp> \n</transport>", 'frame_type octet_count'].join("\n"))
351
355
  tests = create_test_case
352
356
 
353
357
  d.run(expect_emits: 2) do
354
358
  tests.each {|test|
355
- TCPSocket.open('127.0.0.1', @port) do |s|
359
+ TCPSocket.open('127.0.0.1', port) do |s|
356
360
  s.send(test['msg'], 0)
357
361
  end
358
362
  }
@@ -363,11 +367,12 @@ EOS
363
367
  end
364
368
 
365
369
  def test_msg_size_with_same_tcp_connection
366
- d = create_driver([ipv4_config, "<transport tcp> \n</transport>", 'frame_type octet_count'].join("\n"))
370
+ port = unused_port(protocol: :tcp)
371
+ d = create_driver([ipv4_config(port), "<transport tcp> \n</transport>", 'frame_type octet_count'].join("\n"))
367
372
  tests = create_test_case
368
373
 
369
374
  d.run(expect_emits: 2) do
370
- TCPSocket.open('127.0.0.1', @port) do |s|
375
+ TCPSocket.open('127.0.0.1', port) do |s|
371
376
  tests.each {|test|
372
377
  s.send(test['msg'], 0)
373
378
  }
@@ -469,7 +474,8 @@ EOS
469
474
  end
470
475
 
471
476
  def test_send_keepalive_packet_is_disabled_by_default
472
- d = create_driver(ipv4_config + %[
477
+ port = unused_port(protocol: :tcp)
478
+ d = create_driver(ipv4_config(port) + %[
473
479
  <transport tcp>
474
480
  </transport>
475
481
  protocol tcp
@@ -479,19 +485,20 @@ EOS
479
485
 
480
486
  def test_send_keepalive_packet_can_be_enabled
481
487
  addr = "127.0.0.1"
482
- d = create_driver(ipv4_config + %[
488
+ port = unused_port(protocol: :tcp)
489
+ d = create_driver(ipv4_config(port) + %[
483
490
  <transport tcp>
484
491
  </transport>
485
492
  send_keepalive_packet true
486
493
  ])
487
494
  assert_true d.instance.send_keepalive_packet
488
495
  mock.proxy(d.instance).server_create_connection(
489
- :in_syslog_tcp_server, @port,
496
+ :in_syslog_tcp_server, port,
490
497
  bind: addr,
491
498
  resolve_name: nil,
492
499
  send_keepalive_packet: true)
493
500
  d.run do
494
- TCPSocket.open(addr, @port)
501
+ TCPSocket.open(addr, port)
495
502
  end
496
503
  end
497
504
 
@@ -3172,9 +3172,7 @@ class TailInputTest < Test::Unit::TestCase
3172
3172
  Fluent::FileWrapper.open("#{@tmp_dir}/tail.txt0", "ab") {|f| f.puts "file3 log2"}
3173
3173
  end
3174
3174
 
3175
- inode_0 = tail_watchers[0]&.ino
3176
- inode_1 = tail_watchers[1]&.ino
3177
- inode_2 = tail_watchers[2]&.ino
3175
+ pos_file_inode = tail_watchers[2].pe.read_inode
3178
3176
  record_values = d.events.collect { |event| event[2]["message"] }.sort
3179
3177
  position_entries = []
3180
3178
  Fluent::FileWrapper.open("#{@tmp_dir}/tail.pos", "r") do |f|
@@ -3188,17 +3186,15 @@ class TailInputTest < Test::Unit::TestCase
3188
3186
  {
3189
3187
  record_values: ["file1 log1", "file1 log2", "file2 log1", "file2 log2", "file3 log1", "file3 log2"],
3190
3188
  tail_watcher_paths: ["#{@tmp_dir}/tail.txt0", "#{@tmp_dir}/tail.txt0", "#{@tmp_dir}/tail.txt0"],
3191
- tail_watcher_inodes: [inode_0, inode_1, inode_2],
3192
3189
  tail_watcher_io_handler_opened_statuses: [false, false, false],
3193
3190
  position_entries: [
3194
3191
  # The recorded path is old, but it is no problem. The path is not used when using follow_inodes.
3195
- ["#{@tmp_dir}/tail.txt0", "0000000000000016", inode_2],
3192
+ ["#{@tmp_dir}/tail.txt0", "0000000000000016", pos_file_inode],
3196
3193
  ],
3197
3194
  },
3198
3195
  {
3199
3196
  record_values: record_values,
3200
3197
  tail_watcher_paths: tail_watchers.collect { |tw| tw.path },
3201
- tail_watcher_inodes: tail_watchers.collect { |tw| tw.ino },
3202
3198
  tail_watcher_io_handler_opened_statuses: tail_watchers.collect { |tw| tw.instance_variable_get(:@io_handler)&.opened? || false },
3203
3199
  position_entries: position_entries
3204
3200
  },
@@ -3253,9 +3249,7 @@ class TailInputTest < Test::Unit::TestCase
3253
3249
  sleep 4
3254
3250
  end
3255
3251
 
3256
- inode_0 = tail_watchers[0]&.ino
3257
- inode_1 = tail_watchers[1]&.ino
3258
- inode_2 = tail_watchers[2]&.ino
3252
+ pos_file_inode = tail_watchers[2].pe.read_inode
3259
3253
  record_values = d.events.collect { |event| event[2]["message"] }.sort
3260
3254
  position_entries = []
3261
3255
  Fluent::FileWrapper.open("#{@tmp_dir}/tail.pos", "r") do |f|
@@ -3269,16 +3263,14 @@ class TailInputTest < Test::Unit::TestCase
3269
3263
  {
3270
3264
  record_values: ["file1 log1", "file1 log2", "file2 log1", "file2 log2", "file3 log1", "file3 log2"],
3271
3265
  tail_watcher_paths: ["#{@tmp_dir}/tail.txt0", "#{@tmp_dir}/tail.txt0", "#{@tmp_dir}/tail.txt0"],
3272
- tail_watcher_inodes: [inode_0, inode_1, inode_2],
3273
3266
  tail_watcher_io_handler_opened_statuses: [false, false, false],
3274
3267
  position_entries: [
3275
- ["#{@tmp_dir}/tail.txt0", "0000000000000016", inode_2],
3268
+ ["#{@tmp_dir}/tail.txt0", "0000000000000016", pos_file_inode],
3276
3269
  ],
3277
3270
  },
3278
3271
  {
3279
3272
  record_values: record_values,
3280
3273
  tail_watcher_paths: tail_watchers.collect { |tw| tw.path },
3281
- tail_watcher_inodes: tail_watchers.collect { |tw| tw.ino },
3282
3274
  tail_watcher_io_handler_opened_statuses: tail_watchers.collect { |tw| tw.instance_variable_get(:@io_handler)&.opened? || false },
3283
3275
  position_entries: position_entries
3284
3276
  },
@@ -5,7 +5,7 @@ require 'fluent/plugin/in_tcp'
5
5
  class TcpInputTest < Test::Unit::TestCase
6
6
  def setup
7
7
  Fluent::Test.setup
8
- @port = unused_port
8
+ @port = unused_port(protocol: :tcp)
9
9
  end
10
10
 
11
11
  def teardown
@@ -5,7 +5,7 @@ require 'fluent/plugin/in_udp'
5
5
  class UdpInputTest < Test::Unit::TestCase
6
6
  def setup
7
7
  Fluent::Test.setup
8
- @port = unused_port
8
+ @port = unused_port(protocol: :udp)
9
9
  end
10
10
 
11
11
  def teardown
@@ -268,25 +268,31 @@ class UdpInputTest < Test::Unit::TestCase
268
268
 
269
269
  test 'message_length_limit' do
270
270
  message_length_limit = 32
271
+
272
+ if Fluent.windows?
273
+ expected_records = ["0" * 30, "4" * 30]
274
+ else
275
+ expected_records = 1.upto(3).collect do |i|
276
+ "#{i}" * message_length_limit
277
+ end
278
+ expected_records.prepend("0" * 30)
279
+ expected_records.append("4" * 30)
280
+ end
281
+
271
282
  d = create_driver(base_config + %!
272
283
  format none
273
284
  message_length_limit #{message_length_limit}
274
285
  !)
275
- d.run(expect_records: 3) do
286
+ d.run(expect_records: expected_records.size, timeout: 5) do
276
287
  create_udp_socket('127.0.0.1', @port) do |u|
277
- 3.times do |i|
288
+ u.send("0" * 30 + "\n", 0)
289
+ 1.upto(3) do |i|
278
290
  u.send("#{i}" * 40 + "\n", 0)
279
291
  end
292
+ u.send("4" * 30 + "\n", 0)
280
293
  end
281
294
  end
282
295
 
283
- if Fluent.windows?
284
- expected_records = []
285
- else
286
- expected_records = 3.times.collect do |i|
287
- "#{i}" * message_length_limit
288
- end
289
- end
290
296
  actual_records = d.events.collect do |event|
291
297
  event[2]["message"]
292
298
  end
@@ -500,10 +500,18 @@ class ExecFilterOutputTest < Test::Unit::TestCase
500
500
  d = create_driver(conf)
501
501
  time = event_time('2011-01-02 13:14:15')
502
502
 
503
- d.run(default_tag: 'test', expect_emits: 1, timeout: 10, start: true, shutdown: false){ d.feed(time, {"k1" => 0}) }
504
- d.run(default_tag: 'test', expect_emits: 1, timeout: 10, start: false, shutdown: false){ d.feed(time, {"k1" => 1}) }
505
- d.run(default_tag: 'test', expect_emits: 1, timeout: 10, start: false, shutdown: false){ d.feed(time, {"k1" => 2}) }
506
- d.run(default_tag: 'test', expect_emits: 1, timeout: 10, start: false, shutdown: false){ d.feed(time, {"k1" => 3}) }
503
+ d.run(default_tag: 'test', expect_emits: 4) do
504
+ d.feed(time, {"k1" => 0})
505
+ d.flush
506
+ sleep 0.5
507
+ d.feed(time, {"k1" => 1})
508
+ d.flush
509
+ sleep 0.5
510
+ d.feed(time, {"k1" => 2})
511
+ d.flush
512
+ sleep 0.5
513
+ d.feed(time, {"k1" => 3})
514
+ end
507
515
 
508
516
  assert_equal "2011-01-02 13:14:15\ttest\t0\n", d.formatted[0]
509
517
  assert_equal "2011-01-02 13:14:15\ttest\t1\n", d.formatted[1]
@@ -524,9 +532,6 @@ class ExecFilterOutputTest < Test::Unit::TestCase
524
532
  assert_equal pid_list[1], events[1][2]['child_pid']
525
533
  assert_equal pid_list[0], events[2][2]['child_pid']
526
534
  assert_equal pid_list[1], events[3][2]['child_pid']
527
-
528
- ensure
529
- d.run(start: false, shutdown: true)
530
535
  end
531
536
 
532
537
  # child process exits per 3 lines
@@ -130,7 +130,7 @@ class FileOutputTest < Test::Unit::TestCase
130
130
  'path' => "#{TMP_DIR}/${tag}/${type}/conf_test.%Y%m%d.%H%M.log",
131
131
  'add_path_suffix' => 'false',
132
132
  'append' => "true",
133
- 'symlink_path' => "#{TMP_DIR}/conf_test.current.log",
133
+ 'symlink_path' => "#{TMP_DIR}/${tag}/conf_test.current.log",
134
134
  'compress' => 'gzip',
135
135
  'recompress' => 'true',
136
136
  }, [
@@ -183,6 +183,26 @@ class FileOutputTest < Test::Unit::TestCase
183
183
  Fluent::Test::Driver::Output.new(Fluent::Plugin::NullOutput).configure(conf)
184
184
  end
185
185
  end
186
+
187
+ test 'warning for symlink_path not including correct placeholders corresponding to chunk keys' do
188
+ omit "Windows doesn't support symlink" if Fluent.windows?
189
+ conf = config_element('match', '**', {
190
+ 'path' => "#{TMP_DIR}/${tag}/${key1}/${key2}/conf_test.%Y%m%d.%H%M.log",
191
+ 'symlink_path' => "#{TMP_DIR}/conf_test.current.log",
192
+ }, [
193
+ config_element('buffer', 'time,tag,key1,key2', {
194
+ '@type' => 'file',
195
+ 'timekey' => '1d',
196
+ 'path' => "#{TMP_DIR}/buf_conf_test",
197
+ }),
198
+ ])
199
+ assert_nothing_raised do
200
+ d = create_driver(conf)
201
+ assert do
202
+ d.logs.count { |log| log.include?("multiple chunks are competing for a single symlink_path") } == 2
203
+ end
204
+ end
205
+ end
186
206
  end
187
207
 
188
208
  sub_test_case 'fully configured output' do
@@ -314,7 +334,7 @@ class FileOutputTest < Test::Unit::TestCase
314
334
  assert_equal r5, d.formatted[4]
315
335
 
316
336
  read_gunzip = ->(path){
317
- File.open(path){ |fio|
337
+ File.open(path, 'rb'){ |fio|
318
338
  Zlib::GzipReader.new(StringIO.new(fio.read)).read
319
339
  }
320
340
  }
@@ -12,7 +12,8 @@ class ForwardOutputTest < Test::Unit::TestCase
12
12
  FileUtils.rm_rf(TMP_DIR)
13
13
  FileUtils.mkdir_p(TMP_DIR)
14
14
  @d = nil
15
- @target_port = unused_port
15
+ # forward plugin uses TCP and UDP sockets on the same port number
16
+ @target_port = unused_port(protocol: :all)
16
17
  end
17
18
 
18
19
  def teardown
@@ -610,7 +611,6 @@ EOL
610
611
 
611
612
  @d = d = create_driver(config + %[
612
613
  require_ack_response true
613
- ack_response_timeout 1s
614
614
  <buffer tag>
615
615
  flush_mode immediate
616
616
  retry_type periodic
@@ -658,7 +658,6 @@ EOL
658
658
 
659
659
  @d = d = create_driver(config + %[
660
660
  require_ack_response true
661
- ack_response_timeout 10s
662
661
  <buffer tag>
663
662
  flush_mode immediate
664
663
  retry_type periodic
@@ -54,7 +54,7 @@ class TcpOutputTest < Test::Unit::TestCase
54
54
 
55
55
  def setup
56
56
  super
57
- @port = unused_port
57
+ @port = unused_port(protocol: :tcp)
58
58
  end
59
59
 
60
60
  def teardown
@@ -8,6 +8,37 @@ class JsonParserTest < ::Test::Unit::TestCase
8
8
  @parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::JSONParser)
9
9
  end
10
10
 
11
+ sub_test_case "configure_json_parser" do
12
+ data("oj", [:oj, [Oj.method(:load), Oj::ParseError]])
13
+ data("json", [:json, [JSON.method(:load), JSON::ParserError]])
14
+ data("yajl", [:yajl, [Yajl.method(:load), Yajl::ParseError]])
15
+ def test_return_each_loader((input, expected_return))
16
+ result = @parser.instance.configure_json_parser(input)
17
+ assert_equal expected_return, result
18
+ end
19
+
20
+ def test_raise_exception_for_unknown_input
21
+ assert_raise RuntimeError do
22
+ @parser.instance.configure_json_parser(:unknown)
23
+ end
24
+ end
25
+
26
+ def test_fall_back_oj_to_yajl_if_oj_not_available
27
+ stub(Fluent::OjOptions).available? { false }
28
+
29
+ result = @parser.instance.configure_json_parser(:oj)
30
+
31
+ assert_equal [Yajl.method(:load), Yajl::ParseError], result
32
+ logs = @parser.logs.collect do |log|
33
+ log.gsub(/\A\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4} /, "")
34
+ end
35
+ assert_equal(
36
+ ["[info]: Oj is not installed, and failing back to Yajl for json parser\n"],
37
+ logs
38
+ )
39
+ end
40
+ end
41
+
11
42
  data('oj' => 'oj', 'yajl' => 'yajl')
12
43
  def test_parse(data)
13
44
  @parser.configure('json_parser' => data)
@@ -14,7 +14,7 @@ class HttpHelperTest < Test::Unit::TestCase
14
14
  CERT_CA_DIR = File.expand_path(File.dirname(__FILE__) + '/data/cert/with_ca')
15
15
 
16
16
  def setup
17
- @port = unused_port
17
+ @port = unused_port(protocol: :tcp)
18
18
  end
19
19
 
20
20
  def teardown