fluentd 0.14.11-x64-mingw32 → 0.14.12-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/.travis.yml +1 -5
- data/ChangeLog +54 -2
- data/example/in_dummy_blocks.conf +17 -0
- data/example/in_forward_tls.conf +14 -0
- data/example/in_forward_workers.conf +21 -0
- data/example/logevents.conf +25 -0
- data/example/out_forward_heartbeat_none.conf +16 -0
- data/example/out_forward_tls.conf +18 -0
- data/example/suppress_config_dump.conf +7 -0
- data/lib/fluent/agent.rb +3 -32
- data/lib/fluent/clock.rb +62 -0
- data/lib/fluent/command/fluentd.rb +12 -0
- data/lib/fluent/compat/input.rb +10 -1
- data/lib/fluent/compat/output.rb +40 -1
- data/lib/fluent/config/configure_proxy.rb +30 -7
- data/lib/fluent/config/section.rb +4 -0
- data/lib/fluent/config/types.rb +2 -2
- data/lib/fluent/configurable.rb +31 -5
- data/lib/fluent/engine.rb +61 -12
- data/lib/fluent/event_router.rb +6 -0
- data/lib/fluent/load.rb +0 -1
- data/lib/fluent/log.rb +118 -42
- data/lib/fluent/match.rb +37 -0
- data/lib/fluent/plugin.rb +25 -3
- data/lib/fluent/plugin/base.rb +4 -0
- data/lib/fluent/plugin/buf_file.rb +38 -14
- data/lib/fluent/plugin/buffer.rb +20 -20
- data/lib/fluent/plugin/buffer/file_chunk.rb +2 -2
- data/lib/fluent/plugin/compressable.rb +1 -0
- data/lib/fluent/plugin/filter_record_transformer.rb +3 -6
- data/lib/fluent/plugin/formatter_csv.rb +4 -1
- data/lib/fluent/plugin/formatter_hash.rb +5 -1
- data/lib/fluent/plugin/formatter_json.rb +10 -0
- data/lib/fluent/plugin/formatter_ltsv.rb +2 -1
- data/lib/fluent/plugin/in_dummy.rb +4 -0
- data/lib/fluent/plugin/in_exec.rb +4 -0
- data/lib/fluent/plugin/in_forward.rb +11 -3
- data/lib/fluent/plugin/in_gc_stat.rb +4 -0
- data/lib/fluent/plugin/in_http.rb +4 -0
- data/lib/fluent/plugin/in_monitor_agent.rb +29 -2
- data/lib/fluent/plugin/in_object_space.rb +4 -1
- data/lib/fluent/plugin/in_syslog.rb +4 -0
- data/lib/fluent/plugin/in_tail.rb +193 -116
- data/lib/fluent/plugin/in_tcp.rb +5 -1
- data/lib/fluent/plugin/in_udp.rb +4 -0
- data/lib/fluent/plugin/input.rb +4 -0
- data/lib/fluent/plugin/out_copy.rb +4 -0
- data/lib/fluent/plugin/out_exec.rb +4 -0
- data/lib/fluent/plugin/out_exec_filter.rb +4 -0
- data/lib/fluent/plugin/out_file.rb +70 -30
- data/lib/fluent/plugin/out_forward.rb +132 -28
- data/lib/fluent/plugin/out_null.rb +10 -0
- data/lib/fluent/plugin/out_relabel.rb +4 -0
- data/lib/fluent/plugin/out_roundrobin.rb +4 -0
- data/lib/fluent/plugin/out_secondary_file.rb +5 -0
- data/lib/fluent/plugin/out_stdout.rb +5 -0
- data/lib/fluent/plugin/output.rb +18 -9
- data/lib/fluent/plugin/storage_local.rb +25 -2
- data/lib/fluent/plugin_helper/cert_option.rb +159 -0
- data/lib/fluent/plugin_helper/child_process.rb +6 -6
- data/lib/fluent/plugin_helper/compat_parameters.rb +1 -1
- data/lib/fluent/plugin_helper/event_loop.rb +29 -4
- data/lib/fluent/plugin_helper/inject.rb +14 -1
- data/lib/fluent/plugin_helper/server.rb +275 -31
- data/lib/fluent/plugin_helper/socket.rb +144 -4
- data/lib/fluent/plugin_helper/socket_option.rb +2 -17
- data/lib/fluent/plugin_helper/storage.rb +7 -1
- data/lib/fluent/plugin_helper/thread.rb +16 -4
- data/lib/fluent/registry.rb +26 -9
- data/lib/fluent/root_agent.rb +7 -3
- data/lib/fluent/supervisor.rb +37 -15
- data/lib/fluent/system_config.rb +37 -10
- data/lib/fluent/test.rb +2 -0
- data/lib/fluent/test/driver/base.rb +24 -26
- data/lib/fluent/test/helpers.rb +21 -0
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_fluentd.rb +274 -4
- data/test/config/test_configurable.rb +154 -0
- data/test/config/test_configure_proxy.rb +180 -1
- data/test/config/test_system_config.rb +10 -0
- data/test/config/test_types.rb +1 -0
- data/test/plugin/test_base.rb +4 -0
- data/test/plugin/test_buf_file.rb +241 -9
- data/test/plugin/test_buffer.rb +11 -11
- data/test/plugin/test_buffer_file_chunk.rb +6 -6
- data/test/plugin/test_compressable.rb +3 -0
- data/test/plugin/test_filter.rb +4 -0
- data/test/plugin/test_filter_record_transformer.rb +20 -0
- data/test/plugin/test_formatter_csv.rb +9 -0
- data/test/plugin/test_formatter_hash.rb +35 -0
- data/test/plugin/test_formatter_json.rb +8 -0
- data/test/plugin/test_formatter_ltsv.rb +7 -0
- data/test/plugin/test_in_dummy.rb +7 -3
- data/test/plugin/test_in_monitor_agent.rb +43 -5
- data/test/plugin/test_in_tail.rb +97 -4
- data/test/plugin/test_input.rb +4 -0
- data/test/plugin/test_out_file.rb +46 -7
- data/test/plugin/test_out_forward.rb +59 -7
- data/test/plugin/test_output.rb +10 -4
- data/test/plugin/test_output_as_buffered.rb +37 -25
- data/test/plugin/test_output_as_buffered_compress.rb +1 -1
- data/test/plugin/test_output_as_buffered_retries.rb +6 -6
- data/test/plugin/test_output_as_buffered_secondary.rb +91 -31
- data/test/plugin/test_storage_local.rb +40 -1
- data/test/plugin_helper/test_child_process.rb +29 -28
- data/test/plugin_helper/test_compat_parameters.rb +1 -1
- data/test/plugin_helper/test_inject.rb +27 -9
- data/test/plugin_helper/test_server.rb +822 -50
- data/test/plugin_helper/test_storage.rb +11 -0
- data/test/plugin_helper/test_timer.rb +1 -0
- data/test/test_clock.rb +164 -0
- data/test/test_log.rb +146 -15
- data/test/test_plugin.rb +251 -0
- data/test/test_supervisor.rb +65 -57
- data/test/test_test_drivers.rb +2 -2
- metadata +18 -7
- data/lib/fluent/process.rb +0 -504
- data/test/test_process.rb +0 -48
data/lib/fluent/plugin/in_tcp.rb
CHANGED
@@ -48,11 +48,15 @@ module Fluent::Plugin
|
|
48
48
|
@parser = parser_create
|
49
49
|
end
|
50
50
|
|
51
|
+
def multi_workers_ready?
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
51
55
|
def start
|
52
56
|
super
|
53
57
|
|
54
58
|
@buffer = ''
|
55
|
-
server_create(:in_tcp_server, @port,
|
59
|
+
server_create(:in_tcp_server, @port, bind: @bind) do |data, conn|
|
56
60
|
@buffer << data
|
57
61
|
begin
|
58
62
|
pos = 0
|
data/lib/fluent/plugin/in_udp.rb
CHANGED
data/lib/fluent/plugin/input.rb
CHANGED
@@ -25,6 +25,10 @@ module Fluent::Plugin
|
|
25
25
|
desc 'If true, pass different record to each `store` plugin.'
|
26
26
|
config_param :deep_copy, :bool, default: false
|
27
27
|
|
28
|
+
def multi_workers_ready?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
28
32
|
def process(tag, es)
|
29
33
|
unless es.repeatable?
|
30
34
|
m = Fluent::MultiEventStream.new
|
@@ -93,14 +93,15 @@ module Fluent::Plugin
|
|
93
93
|
|
94
94
|
configured_time_slice_format = conf['time_slice_format']
|
95
95
|
|
96
|
-
# v0.14 file buffer handles path as directory if '*' is missing
|
97
|
-
# 'dummy_path' is not to raise configuration error for 'path' in file buffer plugin,
|
98
|
-
# but raise it in this plugin.
|
99
96
|
if conf.elements(name: 'buffer').empty?
|
100
97
|
conf.add_element('buffer', 'time')
|
101
98
|
end
|
102
99
|
buffer_conf = conf.elements(name: 'buffer').first
|
103
|
-
|
100
|
+
# Fluent::PluginId#configure is not called yet, so we can't use #plugin_root_dir here.
|
101
|
+
if !buffer_conf.has_key?('path') && !(conf['@id'] && system_config.root_dir)
|
102
|
+
# v0.14 file buffer handles path as directory if '*' is missing
|
103
|
+
# 'dummy_path' is not to raise configuration error for 'path' in file buffer plugin,
|
104
|
+
# but raise it in this plugin.
|
104
105
|
buffer_conf['path'] = conf['path'] || '/tmp/dummy_path'
|
105
106
|
end
|
106
107
|
|
@@ -159,6 +160,11 @@ module Fluent::Plugin
|
|
159
160
|
|
160
161
|
@dir_perm = system_config.dir_permission || DIR_PERMISSION
|
161
162
|
@file_perm = system_config.file_permission || FILE_PERMISSION
|
163
|
+
@need_lock = system_config.workers > 1
|
164
|
+
end
|
165
|
+
|
166
|
+
def multi_workers_ready?
|
167
|
+
true
|
162
168
|
end
|
163
169
|
|
164
170
|
def format(tag, time, record)
|
@@ -170,34 +176,51 @@ module Fluent::Plugin
|
|
170
176
|
path = extract_placeholders(@path_template, chunk.metadata)
|
171
177
|
FileUtils.mkdir_p File.dirname(path), mode: @dir_perm
|
172
178
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
end
|
189
|
-
else
|
190
|
-
File.open(path, "ab", @file_perm) do |f|
|
191
|
-
chunk.write_to(f, compressed: :gzip)
|
192
|
-
end
|
193
|
-
end
|
179
|
+
writer = case
|
180
|
+
when @compress_method.nil?
|
181
|
+
method(:write_without_compression)
|
182
|
+
when @compress_method == :gzip
|
183
|
+
if @buffer.compress != :gzip || @recompress
|
184
|
+
method(:write_gzip_with_compression)
|
185
|
+
else
|
186
|
+
method(:write_gzip_from_gzipped_chunk)
|
187
|
+
end
|
188
|
+
else
|
189
|
+
raise "BUG: unknown compression method #{@compress_method}"
|
190
|
+
end
|
191
|
+
|
192
|
+
if @append
|
193
|
+
writer.call(path, chunk)
|
194
194
|
else
|
195
|
-
|
195
|
+
find_filepath_available(path, with_lock: @need_lock) do |actual_path|
|
196
|
+
writer.call(actual_path, chunk)
|
197
|
+
path = actual_path
|
198
|
+
end
|
196
199
|
end
|
197
200
|
|
198
201
|
@last_written_path = path
|
199
202
|
end
|
200
203
|
|
204
|
+
def write_without_compression(path, chunk)
|
205
|
+
File.open(path, "ab", @file_perm) do |f|
|
206
|
+
chunk.write_to(f)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def write_gzip_with_compression(path, chunk)
|
211
|
+
File.open(path, "ab", @file_perm) do |f|
|
212
|
+
gz = Zlib::GzipWriter.new(f)
|
213
|
+
chunk.write_to(gz, compressed: :text)
|
214
|
+
gz.close
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def write_gzip_from_gzipped_chunk(path, chunk)
|
219
|
+
File.open(path, "ab", @file_perm) do |f|
|
220
|
+
chunk.write_to(f, compressed: :gzip)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
201
224
|
def timekey_to_timeformat(timekey)
|
202
225
|
case timekey
|
203
226
|
when nil then ''
|
@@ -249,14 +272,31 @@ module Fluent::Plugin
|
|
249
272
|
end
|
250
273
|
end
|
251
274
|
|
252
|
-
def find_filepath_available(path_with_placeholder) # for non-append
|
275
|
+
def find_filepath_available(path_with_placeholder, with_lock: false) # for non-append
|
253
276
|
raise "BUG: index placeholder not found in path: #{path_with_placeholder}" unless path_with_placeholder.index('_**')
|
254
277
|
i = 0
|
255
|
-
|
256
|
-
|
278
|
+
dir_path = locked = nil
|
279
|
+
while true
|
280
|
+
path = path_with_placeholder.sub('_**', "_#{i}")
|
257
281
|
i += 1
|
282
|
+
next if File.exist?(path)
|
283
|
+
|
284
|
+
if with_lock
|
285
|
+
dir_path = path + '.lock'
|
286
|
+
locked = Dir.mkdir(dir_path) rescue false
|
287
|
+
next unless locked
|
288
|
+
# ensure that other worker doesn't create a file (and release lock)
|
289
|
+
# between previous File.exist? and Dir.mkdir
|
290
|
+
next if File.exist?(path)
|
291
|
+
end
|
292
|
+
|
293
|
+
break
|
294
|
+
end
|
295
|
+
yield path
|
296
|
+
ensure
|
297
|
+
if dir_path && locked && Dir.exist?(dir_path)
|
298
|
+
Dir.rmdir(dir_path) rescue nil
|
258
299
|
end
|
259
|
-
path
|
260
300
|
end
|
261
301
|
end
|
262
302
|
end
|
@@ -16,6 +16,7 @@
|
|
16
16
|
|
17
17
|
require 'fluent/output'
|
18
18
|
require 'fluent/config/error'
|
19
|
+
require 'fluent/clock'
|
19
20
|
require 'base64'
|
20
21
|
|
21
22
|
require 'fluent/compat/socket_util'
|
@@ -32,14 +33,17 @@ module Fluent::Plugin
|
|
32
33
|
|
33
34
|
LISTEN_PORT = 24224
|
34
35
|
|
35
|
-
|
36
|
+
desc 'The transport protocol.'
|
37
|
+
config_param :transport, :enum, list: [:tcp, :tls], default: :tcp
|
38
|
+
# TODO: TLS session cache/tickets
|
39
|
+
# TODO: Connection keepalive
|
36
40
|
|
37
41
|
desc 'The timeout time when sending event logs.'
|
38
42
|
config_param :send_timeout, :time, default: 60
|
39
43
|
# TODO: add linger_timeout, recv_timeout
|
40
44
|
|
41
|
-
desc 'The
|
42
|
-
config_param :heartbeat_type, :enum, list: [:tcp, :udp, :none], default: :
|
45
|
+
desc 'The protocol to use for heartbeats (default is the same with "transport").'
|
46
|
+
config_param :heartbeat_type, :enum, list: [:transport, :tcp, :udp, :none], default: :transport
|
43
47
|
desc 'The interval of the heartbeat packer.'
|
44
48
|
config_param :heartbeat_interval, :time, default: 1
|
45
49
|
desc 'The wait time before accepting a server fault recovery.'
|
@@ -70,9 +74,25 @@ module Fluent::Plugin
|
|
70
74
|
desc 'Enable client-side DNS round robin.'
|
71
75
|
config_param :dns_round_robin, :bool, default: false # heartbeat_type 'udp' is not available for this
|
72
76
|
|
77
|
+
desc 'Ignore DNS resolution and errors at startup time.'
|
78
|
+
config_param :ignore_network_errors_at_startup, :bool, default: false
|
79
|
+
|
73
80
|
desc 'Compress buffered data.'
|
74
81
|
config_param :compress, :enum, list: [:text, :gzip], default: :text
|
75
82
|
|
83
|
+
desc 'The default version of TLS transport.'
|
84
|
+
config_param :tls_version, :enum, list: Fluent::PluginHelper::Socket::TLS_SUPPORTED_VERSIONS, default: Fluent::PluginHelper::Socket::TLS_DEFAULT_VERSION
|
85
|
+
desc 'The cipher configuration of TLS transport.'
|
86
|
+
config_param :tls_ciphers, :string, default: Fluent::PluginHelper::Socket::CIPHERS_DEFAULT
|
87
|
+
desc 'Skip all verification of certificates or not.'
|
88
|
+
config_param :tls_insecure_mode, :bool, default: false
|
89
|
+
desc 'Allow self signed certificates or not.'
|
90
|
+
config_param :tls_allow_self_signed_cert, :bool, default: false
|
91
|
+
desc 'Verify hostname of servers and certificates or not in TLS transport.'
|
92
|
+
config_param :tls_verify_hostname, :bool, default: true
|
93
|
+
desc 'The additional CA certificate path for TLS.'
|
94
|
+
config_param :tls_cert_path, :array, value_type: :string, default: nil
|
95
|
+
|
76
96
|
config_section :security, required: false, multi: false do
|
77
97
|
desc 'The hostname'
|
78
98
|
config_param :self_hostname, :string
|
@@ -83,7 +103,7 @@ module Fluent::Plugin
|
|
83
103
|
config_section :server, param_name: :servers do
|
84
104
|
desc "The IP address or host name of the server."
|
85
105
|
config_param :host, :string
|
86
|
-
desc "The name of the server. Used in
|
106
|
+
desc "The name of the server. Used for logging and certificate verification in TLS transport (when host is address)."
|
87
107
|
config_param :name, :string, default: nil
|
88
108
|
desc "The port number of the host."
|
89
109
|
config_param :port, :integer, default: LISTEN_PORT
|
@@ -134,9 +154,29 @@ module Fluent::Plugin
|
|
134
154
|
@read_interval = @read_interval_msec / 1000.0
|
135
155
|
@recover_sample_size = @recover_wait / @heartbeat_interval
|
136
156
|
|
157
|
+
if @heartbeat_type == :tcp
|
158
|
+
log.warn "'heartbeat_type tcp' is deprecated. use 'transport' instead."
|
159
|
+
@heartbeat_type = :transport
|
160
|
+
end
|
161
|
+
|
137
162
|
if @dns_round_robin
|
138
163
|
if @heartbeat_type == :udp
|
139
|
-
raise Fluent::ConfigError, "forward output heartbeat type must be '
|
164
|
+
raise Fluent::ConfigError, "forward output heartbeat type must be 'transport' or 'none' to use dns_round_robin option"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
if @transport == :tls
|
169
|
+
if @tls_cert_path && !@tls_cert_path.empty?
|
170
|
+
@tls_cert_path.each do |path|
|
171
|
+
raise Fluent::ConfigError, "specified cert path does not exist:#{path}" unless File.exist?(path)
|
172
|
+
raise Fluent::ConfigError, "specified cert path is not readable:#{path}" unless File.readable?(path)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
if @tls_insecure_mode
|
177
|
+
log.warn "TLS transport is configured in insecure way"
|
178
|
+
@tls_verify_hostname = false
|
179
|
+
@tls_allow_self_signed_cert = true
|
140
180
|
end
|
141
181
|
end
|
142
182
|
|
@@ -148,7 +188,15 @@ module Fluent::Plugin
|
|
148
188
|
if @heartbeat_type == :none
|
149
189
|
@nodes << NoneHeartbeatNode.new(self, server, failure: failure)
|
150
190
|
else
|
151
|
-
|
191
|
+
node = Node.new(self, server, failure: failure)
|
192
|
+
begin
|
193
|
+
node.validate_host_resolution!
|
194
|
+
rescue => e
|
195
|
+
raise unless @ignore_network_errors_at_startup
|
196
|
+
log.warn "failed to resolve node name when configured", server: (server.name || server.host), error: e
|
197
|
+
node.disable!
|
198
|
+
end
|
199
|
+
@nodes << node
|
152
200
|
end
|
153
201
|
end
|
154
202
|
|
@@ -167,6 +215,10 @@ module Fluent::Plugin
|
|
167
215
|
raise Fluent::ConfigError, "ack_response_timeout must be a positive integer" if @ack_response_timeout < 1
|
168
216
|
end
|
169
217
|
|
218
|
+
def multi_workers_ready?
|
219
|
+
true
|
220
|
+
end
|
221
|
+
|
170
222
|
def prefer_delayed_commit
|
171
223
|
@require_ack_response
|
172
224
|
end
|
@@ -204,7 +256,10 @@ module Fluent::Plugin
|
|
204
256
|
end
|
205
257
|
|
206
258
|
def close
|
207
|
-
|
259
|
+
if @usock
|
260
|
+
# close socket and ignore errors: this socket will not be used anyway.
|
261
|
+
@usock.close rescue nil
|
262
|
+
end
|
208
263
|
super
|
209
264
|
end
|
210
265
|
|
@@ -229,7 +284,7 @@ module Fluent::Plugin
|
|
229
284
|
tag = chunk.metadata.tag
|
230
285
|
sock, node = select_a_healthy_node{|n| n.send_data(tag, chunk) }
|
231
286
|
chunk_id_base64 = Base64.encode64(chunk.unique_id)
|
232
|
-
current_time =
|
287
|
+
current_time = Fluent::Clock.now
|
233
288
|
info = ACKWaitingSockInfo.new(sock, chunk.unique_id, chunk_id_base64, node, current_time, @ack_response_timeout)
|
234
289
|
@sock_ack_waiting_mutex.synchronize do
|
235
290
|
@sock_ack_waiting << info
|
@@ -258,14 +313,34 @@ module Fluent::Plugin
|
|
258
313
|
raise NoNodesAvailable, "no nodes are available"
|
259
314
|
end
|
260
315
|
|
261
|
-
def create_transfer_socket(host, port, &block)
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
316
|
+
def create_transfer_socket(host, port, hostname, &block)
|
317
|
+
case @transport
|
318
|
+
when :tls
|
319
|
+
socket_create_tls(
|
320
|
+
host, port,
|
321
|
+
version: @tls_version,
|
322
|
+
ciphers: @tls_ciphers,
|
323
|
+
insecure: @tls_insecure_mode,
|
324
|
+
verify_fqdn: @tls_verify_hostname,
|
325
|
+
fqdn: hostname,
|
326
|
+
allow_self_signed_cert: @tls_allow_self_signed_cert,
|
327
|
+
cert_paths: @tls_cert_path,
|
328
|
+
linger_timeout: @send_timeout,
|
329
|
+
send_timeout: @send_timeout,
|
330
|
+
recv_timeout: @ack_response_timeout,
|
331
|
+
&block
|
332
|
+
)
|
333
|
+
when :tcp
|
334
|
+
socket_create_tcp(
|
335
|
+
host, port,
|
336
|
+
linger_timeout: @send_timeout,
|
337
|
+
send_timeout: @send_timeout,
|
338
|
+
recv_timeout: @ack_response_timeout,
|
339
|
+
&block
|
340
|
+
)
|
341
|
+
else
|
342
|
+
raise "BUG: unknown transport protocol #{@transport}"
|
343
|
+
end
|
269
344
|
end
|
270
345
|
|
271
346
|
# MessagePack FixArray length is 3
|
@@ -390,7 +465,7 @@ module Fluent::Plugin
|
|
390
465
|
unpacker = Fluent::Engine.msgpack_unpacker
|
391
466
|
|
392
467
|
while thread_current_running?
|
393
|
-
now =
|
468
|
+
now = Fluent::Clock.now
|
394
469
|
sockets = []
|
395
470
|
begin
|
396
471
|
@sock_ack_waiting_mutex.synchronize do
|
@@ -441,6 +516,14 @@ module Fluent::Plugin
|
|
441
516
|
@available = true
|
442
517
|
@state = nil
|
443
518
|
|
519
|
+
# @hostname is used for certificate verification & TLS SNI
|
520
|
+
host_is_hostname = !(IPAddr.new(@host) rescue false)
|
521
|
+
@hostname = case
|
522
|
+
when host_is_hostname then @host
|
523
|
+
when @name then @name
|
524
|
+
else nil
|
525
|
+
end
|
526
|
+
|
444
527
|
@usock = nil
|
445
528
|
|
446
529
|
@username = server.username
|
@@ -453,7 +536,7 @@ module Fluent::Plugin
|
|
453
536
|
|
454
537
|
@resolved_host = nil
|
455
538
|
@resolved_time = 0
|
456
|
-
|
539
|
+
@resolved_once = false
|
457
540
|
end
|
458
541
|
|
459
542
|
attr_accessor :usock
|
@@ -462,6 +545,10 @@ module Fluent::Plugin
|
|
462
545
|
attr_reader :sockaddr # used by on_heartbeat
|
463
546
|
attr_reader :failure, :available # for test
|
464
547
|
|
548
|
+
def validate_host_resolution!
|
549
|
+
resolved_host
|
550
|
+
end
|
551
|
+
|
465
552
|
def available?
|
466
553
|
@available
|
467
554
|
end
|
@@ -517,20 +604,26 @@ module Fluent::Plugin
|
|
517
604
|
option = { 'size' => chunk.size, 'compressed' => @compress }
|
518
605
|
option['chunk'] = Base64.encode64(chunk.unique_id) if @sender.require_ack_response
|
519
606
|
|
520
|
-
#
|
521
|
-
#
|
607
|
+
# https://github.com/fluent/fluentd/wiki/Forward-Protocol-Specification-v1#packedforward-mode
|
608
|
+
# out_forward always uses str32 type for entries.
|
609
|
+
# str16 can store only 64kbytes, and it should be much smaller than buffer chunk size.
|
610
|
+
|
611
|
+
tag = tag.dup.force_encoding(Encoding::UTF_8)
|
522
612
|
|
523
|
-
sock.write @sender.forward_header
|
524
|
-
sock.write tag.to_msgpack
|
613
|
+
sock.write @sender.forward_header # array, size=3
|
614
|
+
sock.write tag.to_msgpack # 1. tag: String (str)
|
525
615
|
chunk.open(compressed: @compress) do |chunk_io|
|
526
|
-
|
527
|
-
|
616
|
+
entries = [0xdb, chunk_io.size].pack('CN')
|
617
|
+
sock.write entries.force_encoding(Encoding::UTF_8) # 2. entries: String (str32)
|
618
|
+
IO.copy_stream(chunk_io, sock) # writeRawBody(packed_es)
|
528
619
|
end
|
529
|
-
sock.write option.to_msgpack
|
620
|
+
sock.write option.to_msgpack # 3. option: Hash(map)
|
621
|
+
|
622
|
+
# TODO: use bin32 for non-utf8 content(entries) when old msgpack-ruby (0.5.x or earlier) not supported
|
530
623
|
end
|
531
624
|
|
532
625
|
def send_data(tag, chunk)
|
533
|
-
sock = @sender.create_transfer_socket(resolved_host, port)
|
626
|
+
sock = @sender.create_transfer_socket(resolved_host, port, @hostname)
|
534
627
|
begin
|
535
628
|
send_data_actual(sock, tag, chunk)
|
536
629
|
rescue
|
@@ -550,9 +643,20 @@ module Fluent::Plugin
|
|
550
643
|
|
551
644
|
# FORWARD_TCP_HEARTBEAT_DATA = FORWARD_HEADER + ''.to_msgpack + [].to_msgpack
|
552
645
|
def send_heartbeat
|
646
|
+
begin
|
647
|
+
dest_addr = resolved_host
|
648
|
+
@resolved_once = true
|
649
|
+
rescue ::SocketError => e
|
650
|
+
if !@resolved_once && @sender.ignore_network_errors_at_startup
|
651
|
+
@log.warn "failed to resolve node name in heartbeating", server: @name || @host, error: e
|
652
|
+
return
|
653
|
+
end
|
654
|
+
raise
|
655
|
+
end
|
656
|
+
|
553
657
|
case @sender.heartbeat_type
|
554
|
-
when :
|
555
|
-
@sender.create_transfer_socket(
|
658
|
+
when :transport
|
659
|
+
@sender.create_transfer_socket(dest_addr, port, @hostname) do |sock|
|
556
660
|
## don't send any data to not cause a compatibility problem
|
557
661
|
# sock.write FORWARD_TCP_HEARTBEAT_DATA
|
558
662
|
|