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.
- checksums.yaml +4 -4
- data/.deepsource.toml +13 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- data/.github/ISSUE_TEMPLATE/config.yml +5 -0
- data/.github/workflows/linux-test.yaml +36 -0
- data/.github/workflows/macos-test.yaml +30 -0
- data/.github/workflows/stale-actions.yml +22 -0
- data/.github/workflows/windows-test.yaml +35 -0
- data/.gitlab-ci.yml +41 -19
- data/CHANGELOG.md +166 -0
- data/MAINTAINERS.md +5 -2
- data/README.md +7 -4
- data/bin/fluent-cap-ctl +7 -0
- data/bin/fluent-ctl +7 -0
- data/fluentd.gemspec +7 -5
- data/lib/fluent/capability.rb +87 -0
- data/lib/fluent/command/bundler_injection.rb +1 -1
- data/lib/fluent/command/ca_generate.rb +6 -3
- data/lib/fluent/command/cap_ctl.rb +174 -0
- data/lib/fluent/command/cat.rb +0 -1
- data/lib/fluent/command/ctl.rb +177 -0
- data/lib/fluent/command/fluentd.rb +4 -0
- data/lib/fluent/command/plugin_config_formatter.rb +18 -2
- data/lib/fluent/command/plugin_generator.rb +31 -1
- data/lib/fluent/compat/parser.rb +2 -2
- data/lib/fluent/config/section.rb +2 -2
- data/lib/fluent/config/types.rb +2 -2
- data/lib/fluent/env.rb +4 -0
- data/lib/fluent/event.rb +3 -13
- data/lib/fluent/load.rb +0 -1
- data/lib/fluent/plugin.rb +5 -0
- data/lib/fluent/plugin/buffer.rb +2 -21
- data/lib/fluent/plugin/file_wrapper.rb +39 -3
- data/lib/fluent/plugin/formatter.rb +24 -0
- data/lib/fluent/plugin/formatter_csv.rb +1 -1
- data/lib/fluent/plugin/formatter_hash.rb +3 -1
- data/lib/fluent/plugin/formatter_json.rb +3 -1
- data/lib/fluent/plugin/formatter_ltsv.rb +7 -5
- data/lib/fluent/plugin/formatter_out_file.rb +6 -4
- data/lib/fluent/plugin/formatter_single_value.rb +4 -2
- data/lib/fluent/plugin/formatter_tsv.rb +4 -2
- data/lib/fluent/plugin/in_http.rb +24 -3
- data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
- data/lib/fluent/plugin/in_tail.rb +129 -41
- data/lib/fluent/plugin/in_tail/position_file.rb +39 -14
- data/lib/fluent/plugin/in_tcp.rb +1 -0
- data/lib/fluent/plugin/out_copy.rb +18 -5
- data/lib/fluent/plugin/out_exec_filter.rb +3 -3
- data/lib/fluent/plugin/out_forward.rb +61 -28
- data/lib/fluent/plugin/out_http.rb +28 -3
- data/lib/fluent/plugin/output.rb +18 -10
- data/lib/fluent/plugin/parser_csv.rb +2 -2
- data/lib/fluent/plugin/parser_syslog.rb +2 -2
- data/lib/fluent/plugin/storage_local.rb +4 -4
- data/lib/fluent/plugin_helper/http_server/compat/server.rb +1 -1
- data/lib/fluent/plugin_helper/inject.rb +4 -2
- data/lib/fluent/plugin_helper/retry_state.rb +4 -0
- data/lib/fluent/plugin_helper/server.rb +4 -2
- data/lib/fluent/plugin_helper/socket_option.rb +2 -2
- data/lib/fluent/supervisor.rb +153 -48
- data/lib/fluent/system_config.rb +2 -1
- data/lib/fluent/time.rb +58 -1
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +22 -4
- data/templates/new_gem/fluent-plugin.gemspec.erb +3 -3
- data/templates/plugin_config_formatter/param.md-table.erb +10 -0
- data/test/command/test_binlog_reader.rb +22 -6
- data/test/command/test_cap_ctl.rb +100 -0
- data/test/command/test_ctl.rb +57 -0
- data/test/command/test_fluentd.rb +38 -0
- data/test/command/test_plugin_config_formatter.rb +124 -2
- data/test/config/test_configurable.rb +1 -1
- data/test/plugin/in_tail/test_position_file.rb +46 -26
- data/test/plugin/test_file_wrapper.rb +105 -0
- data/test/plugin/test_filter_stdout.rb +6 -1
- data/test/plugin/test_formatter_hash.rb +6 -3
- data/test/plugin/test_formatter_json.rb +14 -4
- data/test/plugin/test_formatter_ltsv.rb +13 -5
- data/test/plugin/test_formatter_out_file.rb +35 -14
- data/test/plugin/test_formatter_single_value.rb +12 -6
- data/test/plugin/test_formatter_tsv.rb +12 -4
- data/test/plugin/test_in_exec.rb +1 -1
- data/test/plugin/test_in_http.rb +25 -0
- data/test/plugin/test_in_tail.rb +503 -42
- data/test/plugin/test_out_copy.rb +87 -0
- data/test/plugin/test_out_file.rb +23 -18
- data/test/plugin/test_out_forward.rb +94 -6
- data/test/plugin/test_out_http.rb +20 -1
- data/test/plugin/test_output.rb +15 -3
- data/test/plugin/test_output_as_buffered_backup.rb +2 -0
- data/test/plugin/test_parser_csv.rb +14 -0
- data/test/plugin/test_parser_syslog.rb +16 -2
- data/test/plugin/test_sd_file.rb +1 -1
- data/test/plugin_helper/service_discovery/test_manager.rb +1 -1
- data/test/plugin_helper/test_child_process.rb +5 -2
- data/test/plugin_helper/test_compat_parameters.rb +7 -2
- data/test/plugin_helper/test_http_server_helper.rb +4 -2
- data/test/plugin_helper/test_inject.rb +29 -0
- data/test/plugin_helper/test_server.rb +26 -7
- data/test/test_capability.rb +74 -0
- data/test/test_event.rb +16 -0
- data/test/test_formatter.rb +64 -10
- data/test/test_output.rb +8 -3
- data/test/test_supervisor.rb +150 -1
- data/test/test_time_parser.rb +109 -0
- metadata +87 -33
- data/.travis.yml +0 -57
- 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 [](
|
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
|
-
|
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(
|
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
|
-
|
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
|
-
|
98
|
-
|
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
|
-
|
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
|
data/lib/fluent/plugin/in_tcp.rb
CHANGED
@@ -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.
|
42
|
-
|
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
|
-
|
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?
|
162
|
+
@respawns = if @child_respawn.nil? || (@child_respawn == 'none') || (@child_respawn == '0')
|
163
163
|
0
|
164
|
-
elsif @child_respawn == 'inf'
|
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
|
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
|
-
|
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 =
|
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
|
-
|
493
|
-
|
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
|
-
|
507
|
-
|
508
|
-
|
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
|
-
|
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
|
data/lib/fluent/plugin/output.rb
CHANGED
@@ -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
|
-
|
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.
|
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 :
|
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 @
|
37
|
+
if @parser_engine == :fast
|
38
38
|
@quote_char = '"'
|
39
39
|
@escape_pattern = Regexp.compile(@quote_char * 2)
|
40
40
|
|