fluentd 1.11.4-x64-mingw32 → 1.12.3-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 (108) hide show
  1. checksums.yaml +4 -4
  2. data/.deepsource.toml +13 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  4. data/.github/ISSUE_TEMPLATE/config.yml +5 -0
  5. data/.github/workflows/linux-test.yaml +36 -0
  6. data/.github/workflows/macos-test.yaml +30 -0
  7. data/.github/workflows/stale-actions.yml +22 -0
  8. data/.github/workflows/windows-test.yaml +35 -0
  9. data/.gitlab-ci.yml +41 -19
  10. data/CHANGELOG.md +166 -0
  11. data/MAINTAINERS.md +5 -2
  12. data/README.md +7 -4
  13. data/bin/fluent-cap-ctl +7 -0
  14. data/bin/fluent-ctl +7 -0
  15. data/fluentd.gemspec +7 -5
  16. data/lib/fluent/capability.rb +87 -0
  17. data/lib/fluent/command/bundler_injection.rb +1 -1
  18. data/lib/fluent/command/ca_generate.rb +6 -3
  19. data/lib/fluent/command/cap_ctl.rb +174 -0
  20. data/lib/fluent/command/cat.rb +0 -1
  21. data/lib/fluent/command/ctl.rb +177 -0
  22. data/lib/fluent/command/fluentd.rb +4 -0
  23. data/lib/fluent/command/plugin_config_formatter.rb +18 -2
  24. data/lib/fluent/command/plugin_generator.rb +31 -1
  25. data/lib/fluent/compat/parser.rb +2 -2
  26. data/lib/fluent/config/section.rb +2 -2
  27. data/lib/fluent/config/types.rb +2 -2
  28. data/lib/fluent/env.rb +4 -0
  29. data/lib/fluent/event.rb +3 -13
  30. data/lib/fluent/load.rb +0 -1
  31. data/lib/fluent/plugin.rb +5 -0
  32. data/lib/fluent/plugin/buffer.rb +2 -21
  33. data/lib/fluent/plugin/file_wrapper.rb +39 -3
  34. data/lib/fluent/plugin/formatter.rb +24 -0
  35. data/lib/fluent/plugin/formatter_csv.rb +1 -1
  36. data/lib/fluent/plugin/formatter_hash.rb +3 -1
  37. data/lib/fluent/plugin/formatter_json.rb +3 -1
  38. data/lib/fluent/plugin/formatter_ltsv.rb +7 -5
  39. data/lib/fluent/plugin/formatter_out_file.rb +6 -4
  40. data/lib/fluent/plugin/formatter_single_value.rb +4 -2
  41. data/lib/fluent/plugin/formatter_tsv.rb +4 -2
  42. data/lib/fluent/plugin/in_http.rb +24 -3
  43. data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
  44. data/lib/fluent/plugin/in_tail.rb +129 -41
  45. data/lib/fluent/plugin/in_tail/position_file.rb +39 -14
  46. data/lib/fluent/plugin/in_tcp.rb +1 -0
  47. data/lib/fluent/plugin/out_copy.rb +18 -5
  48. data/lib/fluent/plugin/out_exec_filter.rb +3 -3
  49. data/lib/fluent/plugin/out_forward.rb +61 -28
  50. data/lib/fluent/plugin/out_http.rb +28 -3
  51. data/lib/fluent/plugin/output.rb +18 -10
  52. data/lib/fluent/plugin/parser_csv.rb +2 -2
  53. data/lib/fluent/plugin/parser_syslog.rb +2 -2
  54. data/lib/fluent/plugin/storage_local.rb +4 -4
  55. data/lib/fluent/plugin_helper/http_server/compat/server.rb +1 -1
  56. data/lib/fluent/plugin_helper/inject.rb +4 -2
  57. data/lib/fluent/plugin_helper/retry_state.rb +4 -0
  58. data/lib/fluent/plugin_helper/server.rb +4 -2
  59. data/lib/fluent/plugin_helper/socket_option.rb +2 -2
  60. data/lib/fluent/supervisor.rb +153 -48
  61. data/lib/fluent/system_config.rb +2 -1
  62. data/lib/fluent/time.rb +58 -1
  63. data/lib/fluent/version.rb +1 -1
  64. data/lib/fluent/winsvc.rb +22 -4
  65. data/templates/new_gem/fluent-plugin.gemspec.erb +3 -3
  66. data/templates/plugin_config_formatter/param.md-table.erb +10 -0
  67. data/test/command/test_binlog_reader.rb +22 -6
  68. data/test/command/test_cap_ctl.rb +100 -0
  69. data/test/command/test_ctl.rb +57 -0
  70. data/test/command/test_fluentd.rb +38 -0
  71. data/test/command/test_plugin_config_formatter.rb +124 -2
  72. data/test/config/test_configurable.rb +1 -1
  73. data/test/plugin/in_tail/test_position_file.rb +46 -26
  74. data/test/plugin/test_file_wrapper.rb +105 -0
  75. data/test/plugin/test_filter_stdout.rb +6 -1
  76. data/test/plugin/test_formatter_hash.rb +6 -3
  77. data/test/plugin/test_formatter_json.rb +14 -4
  78. data/test/plugin/test_formatter_ltsv.rb +13 -5
  79. data/test/plugin/test_formatter_out_file.rb +35 -14
  80. data/test/plugin/test_formatter_single_value.rb +12 -6
  81. data/test/plugin/test_formatter_tsv.rb +12 -4
  82. data/test/plugin/test_in_exec.rb +1 -1
  83. data/test/plugin/test_in_http.rb +25 -0
  84. data/test/plugin/test_in_tail.rb +503 -42
  85. data/test/plugin/test_out_copy.rb +87 -0
  86. data/test/plugin/test_out_file.rb +23 -18
  87. data/test/plugin/test_out_forward.rb +94 -6
  88. data/test/plugin/test_out_http.rb +20 -1
  89. data/test/plugin/test_output.rb +15 -3
  90. data/test/plugin/test_output_as_buffered_backup.rb +2 -0
  91. data/test/plugin/test_parser_csv.rb +14 -0
  92. data/test/plugin/test_parser_syslog.rb +16 -2
  93. data/test/plugin/test_sd_file.rb +1 -1
  94. data/test/plugin_helper/service_discovery/test_manager.rb +1 -1
  95. data/test/plugin_helper/test_child_process.rb +5 -2
  96. data/test/plugin_helper/test_compat_parameters.rb +7 -2
  97. data/test/plugin_helper/test_http_server_helper.rb +4 -2
  98. data/test/plugin_helper/test_inject.rb +29 -0
  99. data/test/plugin_helper/test_server.rb +26 -7
  100. data/test/test_capability.rb +74 -0
  101. data/test/test_event.rb +16 -0
  102. data/test/test_formatter.rb +64 -10
  103. data/test/test_output.rb +8 -3
  104. data/test/test_supervisor.rb +150 -1
  105. data/test/test_time_parser.rb +109 -0
  106. metadata +87 -33
  107. data/.travis.yml +0 -57
  108. data/appveyor.yml +0 -28
@@ -22,34 +22,40 @@ module Fluent::Plugin
22
22
  UNWATCHED_POSITION = 0xffffffffffffffff
23
23
  POSITION_FILE_ENTRY_REGEX = /^([^\t]+)\t([0-9a-fA-F]+)\t([0-9a-fA-F]+)/.freeze
24
24
 
25
- def self.load(file, logger:)
26
- pf = new(file, logger: logger)
25
+ def self.load(file, follow_inodes, existing_paths, logger:)
26
+ pf = new(file, follow_inodes, existing_paths, logger: logger)
27
27
  pf.load
28
28
  pf
29
29
  end
30
30
 
31
- def initialize(file, logger: nil)
31
+ def initialize(file, follow_inodes, existing_paths, logger: nil)
32
32
  @file = file
33
33
  @logger = logger
34
34
  @file_mutex = Mutex.new
35
35
  @map = {}
36
+ @follow_inodes = follow_inodes
37
+ @existing_paths = existing_paths
36
38
  end
37
39
 
38
- def [](path)
39
- if m = @map[path]
40
+ def [](target_info)
41
+ if m = @map[@follow_inodes ? target_info.ino : target_info.path]
40
42
  return m
41
43
  end
42
44
 
43
45
  @file_mutex.synchronize {
44
46
  @file.seek(0, IO::SEEK_END)
45
- seek = @file.pos + path.bytesize + 1
46
- @file.write "#{path}\t0000000000000000\t0000000000000000\n"
47
- @map[path] = FilePositionEntry.new(@file, @file_mutex, seek, 0, 0)
47
+ seek = @file.pos + target_info.path.bytesize + 1
48
+ @file.write "#{target_info.path}\t0000000000000000\t0000000000000000\n"
49
+ if @follow_inodes
50
+ @map[target_info.ino] = FilePositionEntry.new(@file, @file_mutex, seek, 0, 0)
51
+ else
52
+ @map[target_info.path] = FilePositionEntry.new(@file, @file_mutex, seek, 0, 0)
53
+ end
48
54
  }
49
55
  end
50
56
 
51
- def unwatch(path)
52
- if (entry = @map.delete(path))
57
+ def unwatch(target_info)
58
+ if (entry = @map.delete(@follow_inodes ? target_info.ino : target_info.path))
53
59
  entry.update_pos(UNWATCHED_POSITION)
54
60
  end
55
61
  end
@@ -69,7 +75,11 @@ module Fluent::Plugin
69
75
  pos = m[2].to_i(16)
70
76
  ino = m[3].to_i(16)
71
77
  seek = @file.pos - line.bytesize + path.bytesize + 1
72
- map[path] = FilePositionEntry.new(@file, @file_mutex, seek, pos, ino)
78
+ if @follow_inodes
79
+ map[ino] = FilePositionEntry.new(@file, @file_mutex, seek, pos, ino)
80
+ else
81
+ map[path] = FilePositionEntry.new(@file, @file_mutex, seek, pos, ino)
82
+ end
73
83
  end
74
84
  end
75
85
 
@@ -94,8 +104,9 @@ module Fluent::Plugin
94
104
  @file.truncate(0)
95
105
  @file.write(entries.values.map(&:to_entry_fmt).join)
96
106
 
97
- entries.each do |path, val|
98
- if (m = @map[path])
107
+ # entry contains path/ino key and value.
108
+ entries.each do |key, val|
109
+ if (m = @map[key])
99
110
  m.seek = val.seek
100
111
  end
101
112
  end
@@ -139,13 +150,25 @@ module Fluent::Plugin
139
150
  @logger.warn("#{path} already exists. use latest one: deleted #{entries[path]}") if @logger
140
151
  end
141
152
 
142
- entries[path] = Entry.new(path, pos, ino, file_pos + path.size + 1)
153
+ if @follow_inodes
154
+ entries[ino] = Entry.new(path, pos, ino, file_pos + path.size + 1)
155
+ else
156
+ entries[path] = Entry.new(path, pos, ino, file_pos + path.size + 1)
157
+ end
143
158
  file_pos += line.size
144
159
  end
145
160
  end
146
161
 
162
+ entries = remove_deleted_files_entries(entries, @existing_paths) if @follow_inodes
147
163
  entries
148
164
  end
165
+
166
+ def remove_deleted_files_entries(existent_entries, existing_paths)
167
+ filtered_entries = existent_entries.select {|file_entry|
168
+ existing_paths.key?(file_entry)
169
+ }
170
+ filtered_entries
171
+ end
149
172
  end
150
173
 
151
174
  Entry = Struct.new(:path, :pos, :ino, :seek) do
@@ -224,5 +247,7 @@ module Fluent::Plugin
224
247
  @inode
225
248
  end
226
249
  end
250
+
251
+ TargetInfo = Struct.new(:path, :ino)
227
252
  end
228
253
  end
@@ -98,6 +98,7 @@ module Fluent::Plugin
98
98
  def start
99
99
  super
100
100
 
101
+ log.info "listening tcp socket", bind: @bind, port: @port
101
102
  del_size = @delimiter.length
102
103
  if @_extract_enabled && @_extract_tag_key
103
104
  server_create(:in_tcp_server_single_emit, @port, bind: @bind, resolve_name: !!@source_hostname_key) do |data, conn|
@@ -27,20 +27,28 @@ module Fluent::Plugin
27
27
  desc 'Pass different record to each `store` plugin by specified method'
28
28
  config_param :copy_mode, :enum, list: [:no_copy, :shallow, :deep, :marshal], default: :no_copy
29
29
 
30
- attr_reader :ignore_errors
30
+ attr_reader :ignore_errors, :ignore_if_prev_successes
31
31
 
32
32
  def initialize
33
33
  super
34
34
  @ignore_errors = []
35
+ @ignore_if_prev_successes = []
35
36
  end
36
37
 
37
38
  def configure(conf)
38
39
  super
39
40
 
40
41
  @copy_proc = gen_copy_proc
41
- @stores.each { |store|
42
- @ignore_errors << (store.arg == 'ignore_error')
42
+ @stores.each_with_index { |store, i|
43
+ if i == 0 && store.arg.include?('ignore_if_prev_success')
44
+ raise Fluent::ConfigError, "ignore_if_prev_success must specify 2nd or later <store> directives"
45
+ end
46
+ @ignore_errors << (store.arg.include?('ignore_error'))
47
+ @ignore_if_prev_successes << (store.arg.include?('ignore_if_prev_success'))
43
48
  }
49
+ if @ignore_errors.uniq.size == 1 && @ignore_errors.include?(true) && @ignore_if_prev_successes.include?(false)
50
+ log.warn "ignore_errors are specified in all <store>, but ignore_if_prev_success is not specified. Is this intended?"
51
+ end
44
52
  end
45
53
 
46
54
  def multi_workers_ready?
@@ -55,10 +63,15 @@ module Fluent::Plugin
55
63
  }
56
64
  es = m
57
65
  end
58
-
66
+ success = Array.new(outputs.size)
59
67
  outputs.each_with_index do |output, i|
60
68
  begin
61
- output.emit_events(tag, @copy_proc ? @copy_proc.call(es) : es)
69
+ if i > 0 && success[i - 1] && @ignore_if_prev_successes[i]
70
+ log.debug "ignore copy because prev_success in #{output.plugin_id}", index: i
71
+ else
72
+ output.emit_events(tag, @copy_proc ? @copy_proc.call(es) : es)
73
+ success[i] = true
74
+ end
62
75
  rescue => e
63
76
  if @ignore_errors[i]
64
77
  log.error "ignore emit error in #{output.plugin_id}", error: e
@@ -159,9 +159,9 @@ module Fluent::Plugin
159
159
  @added_prefix_string = @add_prefix + '.'
160
160
  end
161
161
 
162
- @respawns = if @child_respawn.nil? or @child_respawn == 'none' or @child_respawn == '0'
162
+ @respawns = if @child_respawn.nil? || (@child_respawn == 'none') || (@child_respawn == '0')
163
163
  0
164
- elsif @child_respawn == 'inf' or @child_respawn == '-1'
164
+ elsif (@child_respawn == 'inf') || (@child_respawn == '-1')
165
165
  -1
166
166
  elsif @child_respawn =~ /^\d+$/
167
167
  @child_respawn.to_i
@@ -251,7 +251,7 @@ module Fluent::Plugin
251
251
 
252
252
  def tag_remove_prefix(tag)
253
253
  if @remove_prefix
254
- if (tag[0, @removed_length] == @removed_prefix_string and tag.length > @removed_length) or tag == @removed_prefix_string
254
+ if ((tag[0, @removed_length] == @removed_prefix_string) && (tag.length > @removed_length)) || (tag == @removed_prefix_string)
255
255
  tag = tag[@removed_length..-1] || ''
256
256
  end
257
257
  end
@@ -166,6 +166,7 @@ module Fluent::Plugin
166
166
 
167
167
  @usock = nil
168
168
  @keep_alive_watcher_interval = 5 # TODO
169
+ @suspend_flush = false
169
170
  end
170
171
 
171
172
  def configure(conf)
@@ -291,6 +292,15 @@ module Fluent::Plugin
291
292
  @require_ack_response
292
293
  end
293
294
 
295
+ def overwrite_delayed_commit_timeout
296
+ # Output#start sets @delayed_commit_timeout by @buffer_config.delayed_commit_timeout
297
+ # But it should be overwritten by ack_response_timeout to rollback chunks after timeout
298
+ if @delayed_commit_timeout != @ack_response_timeout
299
+ log.info "delayed_commit_timeout is overwritten by ack_response_timeout"
300
+ @delayed_commit_timeout = @ack_response_timeout + 2 # minimum ack_reader IO.select interval is 1s
301
+ end
302
+ end
303
+
294
304
  def start
295
305
  super
296
306
 
@@ -303,13 +313,7 @@ module Fluent::Plugin
303
313
  end
304
314
 
305
315
  if @require_ack_response
306
- # Output#start sets @delayed_commit_timeout by @buffer_config.delayed_commit_timeout
307
- # But it should be overwritten by ack_response_timeout to rollback chunks after timeout
308
- if @delayed_commit_timeout != @ack_response_timeout
309
- log.info "delayed_commit_timeout is overwritten by ack_response_timeout"
310
- @delayed_commit_timeout = @ack_response_timeout + 2 # minimum ack_reader IO.select interval is 1s
311
- end
312
-
316
+ overwrite_delayed_commit_timeout
313
317
  thread_create(:out_forward_receiving_ack, &method(:ack_reader))
314
318
  end
315
319
 
@@ -346,6 +350,26 @@ module Fluent::Plugin
346
350
  end
347
351
  end
348
352
 
353
+ def before_shutdown
354
+ super
355
+ @suspend_flush = true
356
+ end
357
+
358
+ def after_shutdown
359
+ last_ack if @require_ack_response
360
+ super
361
+ end
362
+
363
+ def try_flush
364
+ return if @require_ack_response && @suspend_flush
365
+ super
366
+ end
367
+
368
+ def last_ack
369
+ overwrite_delayed_commit_timeout
370
+ ack_check(ack_select_interval)
371
+ end
372
+
349
373
  def write(chunk)
350
374
  return if chunk.empty?
351
375
  tag = chunk.metadata.tag
@@ -361,6 +385,7 @@ module Fluent::Plugin
361
385
  end
362
386
  tag = chunk.metadata.tag
363
387
  discovery_manager.select_service { |node| node.send_data(tag, chunk) }
388
+ last_ack if @require_ack_response && @suspend_flush
364
389
  end
365
390
 
366
391
  def create_transfer_socket(host, port, hostname, &block)
@@ -481,31 +506,39 @@ module Fluent::Plugin
481
506
  @connection_manager.purge_obsolete_socks
482
507
  end
483
508
 
509
+ def ack_select_interval
510
+ if @delayed_commit_timeout > 3
511
+ 1
512
+ else
513
+ @delayed_commit_timeout / 3.0
514
+ end
515
+ end
516
+
484
517
  def ack_reader
485
- select_interval = if @delayed_commit_timeout > 3
486
- 1
487
- else
488
- @delayed_commit_timeout / 3.0
489
- end
518
+ select_interval = ack_select_interval
490
519
 
491
520
  while thread_current_running?
492
- @ack_handler.collect_response(select_interval) do |chunk_id, node, sock, result|
493
- @connection_manager.close(sock)
494
-
495
- case result
496
- when AckHandler::Result::SUCCESS
497
- commit_write(chunk_id)
498
- when AckHandler::Result::FAILED
499
- node.disable!
500
- rollback_write(chunk_id, update_retry: false)
501
- when AckHandler::Result::CHUNKID_UNMATCHED
502
- rollback_write(chunk_id, update_retry: false)
503
- else
504
- log.warn("BUG: invalid status #{result} #{chunk_id}")
521
+ ack_check(select_interval)
522
+ end
523
+ end
505
524
 
506
- if chunk_id
507
- rollback_write(chunk_id, update_retry: false)
508
- end
525
+ def ack_check(select_interval)
526
+ @ack_handler.collect_response(select_interval) do |chunk_id, node, sock, result|
527
+ @connection_manager.close(sock)
528
+
529
+ case result
530
+ when AckHandler::Result::SUCCESS
531
+ commit_write(chunk_id)
532
+ when AckHandler::Result::FAILED
533
+ node.disable!
534
+ rollback_write(chunk_id, update_retry: false)
535
+ when AckHandler::Result::CHUNKID_UNMATCHED
536
+ rollback_write(chunk_id, update_retry: false)
537
+ else
538
+ log.warn("BUG: invalid status #{result} #{chunk_id}")
539
+
540
+ if chunk_id
541
+ rollback_write(chunk_id, update_retry: false)
509
542
  end
510
543
  end
511
544
  end
@@ -21,6 +21,16 @@ require 'fluent/tls'
21
21
  require 'fluent/plugin/output'
22
22
  require 'fluent/plugin_helper/socket'
23
23
 
24
+ # patch Net::HTTP to support extra_chain_cert which was added in Ruby feature #9758.
25
+ # see: https://github.com/ruby/ruby/commit/31af0dafba6d3769d2a39617c0dddedb97883712
26
+ unless Net::HTTP::SSL_IVNAMES.include?(:@extra_chain_cert)
27
+ class Net::HTTP
28
+ SSL_IVNAMES << :@extra_chain_cert
29
+ SSL_ATTRIBUTES << :extra_chain_cert
30
+ attr_accessor :extra_chain_cert
31
+ end
32
+ end
33
+
24
34
  module Fluent::Plugin
25
35
  class HTTPOutput < Output
26
36
  Fluent::Plugin.register_output('http', self)
@@ -41,6 +51,8 @@ module Fluent::Plugin
41
51
  config_param :json_array, :bool, default: false
42
52
  desc 'Additional headers for HTTP request'
43
53
  config_param :headers, :hash, default: nil
54
+ desc 'Additional placeholder based headers for HTTP request'
55
+ config_param :headers_from_placeholders, :hash, default: nil
44
56
 
45
57
  desc 'The connection open timeout in seconds'
46
58
  config_param :open_timeout, :integer, default: nil
@@ -171,7 +183,15 @@ module Fluent::Plugin
171
183
  end
172
184
  if @tls_client_cert_path
173
185
  raise Fluent::ConfigError, "tls_client_cert_path is wrong: #{@tls_client_cert_path}" unless File.file?(@tls_client_cert_path)
174
- opt[:cert] = OpenSSL::X509::Certificate.new(File.read(@tls_client_cert_path))
186
+
187
+ bundle = File.read(@tls_client_cert_path)
188
+ bundle_certs = bundle.scan(/-----BEGIN CERTIFICATE-----(?:.|\n)+?-----END CERTIFICATE-----/)
189
+ opt[:cert] = OpenSSL::X509::Certificate.new(bundle_certs[0])
190
+
191
+ intermediate_certs = bundle_certs[1..-1]
192
+ if intermediate_certs
193
+ opt[:extra_chain_cert] = intermediate_certs.map { |cert| OpenSSL::X509::Certificate.new(cert) }
194
+ end
175
195
  end
176
196
  if @tls_private_key_path
177
197
  raise Fluent::ConfigError, "tls_private_key_path is wrong: #{@tls_private_key_path}" unless File.file?(@tls_private_key_path)
@@ -195,12 +215,17 @@ module Fluent::Plugin
195
215
  URI.parse(endpoint)
196
216
  end
197
217
 
198
- def set_headers(req)
218
+ def set_headers(req, chunk)
199
219
  if @headers
200
220
  @headers.each do |k, v|
201
221
  req[k] = v
202
222
  end
203
223
  end
224
+ if @headers_from_placeholders
225
+ @headers_from_placeholders.each do |k, v|
226
+ req[k] = extract_placeholders(v, chunk)
227
+ end
228
+ end
204
229
  req['Content-Type'] = @content_type
205
230
  end
206
231
 
@@ -214,7 +239,7 @@ module Fluent::Plugin
214
239
  if @auth
215
240
  req.basic_auth(@auth.username, @auth.password)
216
241
  end
217
- set_headers(req)
242
+ set_headers(req, chunk)
218
243
  req.body = @json_array ? "[#{chunk.read.chop}]" : chunk.read
219
244
  req
220
245
  end
@@ -754,7 +754,17 @@ module Fluent
754
754
  log.warn "tag placeholder '#{$1}' not replaced. tag:#{metadata.tag}, template:#{str}"
755
755
  end
756
756
  end
757
- # ${a_chunk_key}, ...
757
+
758
+ # First we replace ${chunk_id} with chunk.unique_id (hexlified).
759
+ rvalue = rvalue.sub(CHUNK_ID_PLACEHOLDER_PATTERN) {
760
+ if chunk_passed
761
+ dump_unique_id_hex(chunk.unique_id)
762
+ else
763
+ log.warn "${chunk_id} is not allowed in this plugin. Pass Chunk instead of metadata in extract_placeholders's 2nd argument"
764
+ end
765
+ }
766
+
767
+ # Then, replace other ${chunk_key}s.
758
768
  if !@chunk_keys.empty? && metadata.variables
759
769
  hash = {'${tag}' => '${tag}'} # not to erase this wrongly
760
770
  @chunk_keys.each do |key|
@@ -769,14 +779,6 @@ module Fluent
769
779
  end
770
780
  end
771
781
 
772
- rvalue = rvalue.sub(CHUNK_ID_PLACEHOLDER_PATTERN) {
773
- if chunk_passed
774
- dump_unique_id_hex(chunk.unique_id)
775
- else
776
- log.warn "${chunk_id} is not allowed in this plugin. Pass Chunk instead of metadata in extract_placeholders's 2nd argument"
777
- end
778
- }
779
-
780
782
  if rvalue =~ CHUNK_KEY_PLACEHOLDER_PATTERN
781
783
  log.warn "chunk key placeholder '#{$1}' not replaced. template:#{str}"
782
784
  end
@@ -1252,7 +1254,13 @@ module Fluent
1252
1254
  log.debug "buffer queue cleared"
1253
1255
  @retry = nil
1254
1256
  else
1255
- @retry.step
1257
+ # Ensure that the current time is greater than or equal to @retry.next_time to avoid the situation when
1258
+ # @retry.step is called almost as many times as the number of flush threads in a short time.
1259
+ if Time.now >= @retry.next_time
1260
+ @retry.step
1261
+ else
1262
+ @retry.recalc_next_time # to prevent all flush threads from retrying at the same time
1263
+ end
1256
1264
  if error
1257
1265
  if using_secondary
1258
1266
  msg = "failed to flush the buffer with secondary output."
@@ -28,13 +28,13 @@ module Fluent
28
28
  desc 'The delimiter character (or string) of CSV values'
29
29
  config_param :delimiter, :string, default: ','
30
30
  desc 'The parser type used to parse CSV line'
31
- config_param :parser_type, :enum, list: [:normal, :fast], default: :normal
31
+ config_param :parser_engine, :enum, list: [:normal, :fast], default: :normal, alias: :parser_type
32
32
 
33
33
  def configure(conf)
34
34
  super
35
35
 
36
36
 
37
- if @parser_type == :fast
37
+ if @parser_engine == :fast
38
38
  @quote_char = '"'
39
39
  @escape_pattern = Regexp.compile(@quote_char * 2)
40
40