fluentd 1.9.3 → 1.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/issue-auto-closer.yml +12 -0
- data/CHANGELOG.md +182 -0
- data/CONTRIBUTING.md +1 -1
- data/README.md +4 -0
- data/docs/SECURITY_AUDIT.pdf +0 -0
- data/lib/fluent/command/debug.rb +1 -0
- data/lib/fluent/command/fluentd.rb +25 -1
- data/lib/fluent/config.rb +1 -0
- data/lib/fluent/daemonizer.rb +88 -0
- data/lib/fluent/log.rb +45 -6
- data/lib/fluent/match.rb +1 -1
- data/lib/fluent/msgpack_factory.rb +13 -6
- data/lib/fluent/plugin/buffer.rb +2 -2
- data/lib/fluent/plugin/in_dummy.rb +3 -3
- data/lib/fluent/plugin/in_forward.rb +2 -2
- data/lib/fluent/plugin/in_gc_stat.rb +16 -0
- data/lib/fluent/plugin/in_http.rb +146 -75
- data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
- data/lib/fluent/plugin/in_syslog.rb +4 -4
- data/lib/fluent/plugin/in_tail.rb +40 -31
- data/lib/fluent/plugin/in_tail/position_file.rb +23 -6
- data/lib/fluent/plugin/in_unix.rb +77 -77
- data/lib/fluent/plugin/out_copy.rb +1 -1
- data/lib/fluent/plugin/out_file.rb +1 -1
- data/lib/fluent/plugin/out_forward.rb +25 -22
- data/lib/fluent/plugin/out_forward/handshake_protocol.rb +4 -0
- data/lib/fluent/plugin/out_forward/load_balancer.rb +1 -1
- data/lib/fluent/plugin/out_http.rb +15 -2
- data/lib/fluent/plugin/parser_multiline.rb +1 -1
- data/lib/fluent/plugin/parser_syslog.rb +303 -62
- data/lib/fluent/plugin/sd_file.rb +1 -0
- data/lib/fluent/plugin/sd_srv.rb +135 -0
- data/lib/fluent/plugin_helper/cert_option.rb +15 -2
- data/lib/fluent/plugin_helper/child_process.rb +3 -2
- data/lib/fluent/plugin_helper/record_accessor.rb +14 -0
- data/lib/fluent/plugin_helper/server.rb +3 -1
- data/lib/fluent/plugin_helper/service_discovery.rb +7 -0
- data/lib/fluent/plugin_helper/service_discovery/manager.rb +8 -0
- data/lib/fluent/plugin_helper/socket.rb +20 -2
- data/lib/fluent/plugin_helper/socket_option.rb +21 -3
- data/lib/fluent/supervisor.rb +21 -9
- data/lib/fluent/system_config.rb +2 -1
- data/lib/fluent/test/filter_test.rb +2 -2
- data/lib/fluent/test/output_test.rb +3 -3
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_fluentd.rb +71 -12
- data/test/config/test_system_config.rb +2 -0
- data/test/helper.rb +2 -2
- data/test/plugin/in_tail/test_fifo.rb +121 -0
- data/test/plugin/in_tail/test_io_handler.rb +132 -0
- data/test/plugin/in_tail/test_position_file.rb +25 -1
- data/test/plugin/out_forward/test_handshake_protocol.rb +10 -1
- data/test/plugin/out_forward/test_load_balancer.rb +46 -0
- data/test/plugin/test_buf_file.rb +3 -1
- data/test/plugin/test_buffer.rb +20 -0
- data/test/plugin/test_compressable.rb +7 -4
- data/test/plugin/test_in_dummy.rb +12 -14
- data/test/plugin/test_in_forward.rb +2 -2
- data/test/plugin/test_in_gc_stat.rb +24 -1
- data/test/plugin/test_in_http.rb +57 -0
- data/test/plugin/test_in_syslog.rb +16 -1
- data/test/plugin/test_in_tail.rb +43 -20
- data/test/plugin/test_in_unix.rb +128 -73
- data/test/plugin/test_out_forward.rb +39 -3
- data/test/plugin/test_out_http.rb +38 -0
- data/test/plugin/test_out_null.rb +1 -1
- data/test/plugin/test_output_as_buffered_retries.rb +12 -4
- data/test/plugin/test_output_as_buffered_secondary.rb +9 -1
- data/test/plugin/test_parser_syslog.rb +106 -46
- data/test/plugin/test_sd_file.rb +17 -0
- data/test/plugin/test_sd_srv.rb +230 -0
- data/test/plugin_helper/data/cert/cert-with-CRLF.pem +19 -0
- data/test/plugin_helper/data/cert/cert_chains/ca-cert-key.pem +27 -0
- data/test/plugin_helper/data/cert/cert_chains/ca-cert.pem +20 -0
- data/test/plugin_helper/data/cert/cert_chains/cert-key.pem +27 -0
- data/test/plugin_helper/data/cert/cert_chains/cert.pem +40 -0
- data/test/plugin_helper/data/cert/generate_cert.rb +38 -0
- data/test/plugin_helper/http_server/test_app.rb +1 -1
- data/test/plugin_helper/http_server/test_route.rb +1 -1
- data/test/plugin_helper/test_cert_option.rb +2 -0
- data/test/plugin_helper/test_child_process.rb +20 -3
- data/test/plugin_helper/test_http_server_helper.rb +2 -2
- data/test/plugin_helper/test_record_accessor.rb +41 -0
- data/test/plugin_helper/test_server.rb +1 -1
- data/test/plugin_helper/test_service_discovery.rb +37 -4
- data/test/plugin_helper/test_socket.rb +131 -0
- data/test/test_daemonizer.rb +91 -0
- data/test/test_log.rb +44 -0
- data/test/test_msgpack_factory.rb +18 -0
- metadata +28 -2
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Fluentd
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#
|
|
16
|
+
|
|
17
|
+
require 'resolv'
|
|
18
|
+
|
|
19
|
+
require 'fluent/plugin_helper'
|
|
20
|
+
require 'fluent/plugin/service_discovery'
|
|
21
|
+
|
|
22
|
+
module Fluent
|
|
23
|
+
module Plugin
|
|
24
|
+
class SrvServiceDiscovery < ServiceDiscovery
|
|
25
|
+
include PluginHelper::Mixin
|
|
26
|
+
|
|
27
|
+
Plugin.register_sd('srv', self)
|
|
28
|
+
|
|
29
|
+
helpers :timer
|
|
30
|
+
|
|
31
|
+
desc 'Service without underscore in RFC2782'
|
|
32
|
+
config_param :service, :string
|
|
33
|
+
desc 'Proto without underscore in RFC2782'
|
|
34
|
+
config_param :proto, :string, default: 'tcp'
|
|
35
|
+
desc 'Name in RFC2782'
|
|
36
|
+
config_param :hostname, :string
|
|
37
|
+
desc 'hostname of DNS server to request the SRV record'
|
|
38
|
+
config_param :dns_server_host, :string, default: nil
|
|
39
|
+
desc 'interval of requesting to DNS server'
|
|
40
|
+
config_param :interval, :integer, default: 60
|
|
41
|
+
desc "resolve hostname to IP addr of SRV's Target"
|
|
42
|
+
config_param :dns_lookup, :bool, default: true
|
|
43
|
+
desc 'The shared key per server'
|
|
44
|
+
config_param :shared_key, :string, default: nil, secret: true
|
|
45
|
+
desc 'The username for authentication'
|
|
46
|
+
config_param :username, :string, default: ''
|
|
47
|
+
desc 'The password for authentication'
|
|
48
|
+
config_param :password, :string, default: '', secret: true
|
|
49
|
+
|
|
50
|
+
def initialize
|
|
51
|
+
super
|
|
52
|
+
@target = nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def configure(conf)
|
|
56
|
+
super
|
|
57
|
+
|
|
58
|
+
@target = "_#{@service}._#{@proto}.#{@hostname}"
|
|
59
|
+
@dns_resolve =
|
|
60
|
+
if @dns_server_host.nil?
|
|
61
|
+
Resolv::DNS.new
|
|
62
|
+
elsif @dns_server_host.include?(':') # e.g. 127.0.0.1:8600
|
|
63
|
+
host, port = @dns_server_host.split(':', 2)
|
|
64
|
+
Resolv::DNS.new(nameserver_port: [[host, port.to_i]])
|
|
65
|
+
else
|
|
66
|
+
Resolv::DNS.new(nameserver: @dns_server_host)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
@services = fetch_srv_record
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def start(queue)
|
|
73
|
+
timer_execute(:"sd_srv_record_#{@target}", @interval) do
|
|
74
|
+
refresh_srv_records(queue)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
super()
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def refresh_srv_records(queue)
|
|
83
|
+
s = begin
|
|
84
|
+
fetch_srv_record
|
|
85
|
+
rescue => e
|
|
86
|
+
@log.error("sd_srv: #{e}")
|
|
87
|
+
return
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
if s.nil? || s.empty?
|
|
91
|
+
return
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
diff = []
|
|
95
|
+
join = s - @services
|
|
96
|
+
# Need service_in first to guarantee that server exist at least one all time.
|
|
97
|
+
join.each do |j|
|
|
98
|
+
diff << ServiceDiscovery.service_in_msg(j)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
drain = @services - s
|
|
102
|
+
drain.each do |d|
|
|
103
|
+
diff << ServiceDiscovery.service_out_msg(d)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
@services = s
|
|
107
|
+
|
|
108
|
+
diff.each do |a|
|
|
109
|
+
queue.push(a)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def fetch_srv_record
|
|
114
|
+
adders = @dns_resolve.getresources(@target, Resolv::DNS::Resource::IN::SRV)
|
|
115
|
+
|
|
116
|
+
services = []
|
|
117
|
+
|
|
118
|
+
adders.each do |addr|
|
|
119
|
+
host = @dns_lookup ? dns_lookup!(addr.target) : addr.target
|
|
120
|
+
services << [
|
|
121
|
+
addr.priority,
|
|
122
|
+
Service.new(:srv, host.to_s, addr.port.to_i, addr.target.to_s, addr.weight, false, @username, @password, @shared_key)
|
|
123
|
+
]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
services.sort_by(&:first).flat_map { |s| s[1] }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def dns_lookup!(host)
|
|
130
|
+
# may need to cache the result
|
|
131
|
+
@dns_resolve.getaddress(host) # get first result for now
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
@@ -36,7 +36,7 @@ module Fluent
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
if conf.client_cert_auth
|
|
39
|
-
|
|
39
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
ctx.ca_file = conf.ca_path
|
|
@@ -45,6 +45,16 @@ module Fluent
|
|
|
45
45
|
if extra && !extra.empty?
|
|
46
46
|
ctx.extra_chain_cert = extra
|
|
47
47
|
end
|
|
48
|
+
if conf.cert_verifier
|
|
49
|
+
sandbox = Class.new
|
|
50
|
+
ctx.verify_callback = if File.exist?(conf.cert_verifier)
|
|
51
|
+
verifier = File.read(conf.cert_verifier)
|
|
52
|
+
sandbox.instance_eval(verifier, File.basename(conf.cert_verifier))
|
|
53
|
+
else
|
|
54
|
+
sandbox.instance_eval(conf.cert_verifier)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
48
58
|
Fluent::TLS.set_version_to_context(ctx, version, conf.min_version, conf.max_version)
|
|
49
59
|
|
|
50
60
|
ctx
|
|
@@ -171,9 +181,12 @@ module Fluent
|
|
|
171
181
|
|
|
172
182
|
def cert_option_certificates_from_file(path)
|
|
173
183
|
data = File.read(path)
|
|
174
|
-
pattern = Regexp.compile('-+BEGIN CERTIFICATE-+\n(?:[^-]*\n)+-+END CERTIFICATE-+\n?', Regexp::MULTILINE)
|
|
184
|
+
pattern = Regexp.compile('-+BEGIN CERTIFICATE-+\r?\n(?:[^-]*\r?\n)+-+END CERTIFICATE-+\r?\n?', Regexp::MULTILINE)
|
|
175
185
|
list = []
|
|
176
186
|
data.scan(pattern){|match| list << OpenSSL::X509::Certificate.new(match) }
|
|
187
|
+
if list.length == 0
|
|
188
|
+
log.warn "cert_path does not contain a valid certificate"
|
|
189
|
+
end
|
|
177
190
|
list
|
|
178
191
|
end
|
|
179
192
|
end
|
|
@@ -259,6 +259,9 @@ module Fluent
|
|
|
259
259
|
|
|
260
260
|
if !mode.include?(:stderr) && !mode.include?(:read_with_stderr)
|
|
261
261
|
spawn_opts[:err] = IO::NULL if stderr == :discard
|
|
262
|
+
if !mode.include?(:read) && !mode.include?(:read_with_stderr)
|
|
263
|
+
spawn_opts[:out] = IO::NULL
|
|
264
|
+
end
|
|
262
265
|
writeio, readio, wait_thread = *Open3.popen2(*spawn_args, spawn_opts)
|
|
263
266
|
elsif mode.include?(:read_with_stderr)
|
|
264
267
|
writeio, readio, wait_thread = *Open3.popen2e(*spawn_args, spawn_opts)
|
|
@@ -275,8 +278,6 @@ module Fluent
|
|
|
275
278
|
if mode.include?(:read) || mode.include?(:read_with_stderr)
|
|
276
279
|
readio.set_encoding(external_encoding, internal_encoding, **encoding_options)
|
|
277
280
|
readio_in_use = true
|
|
278
|
-
else
|
|
279
|
-
readio.reopen(IO::NULL) if readio
|
|
280
281
|
end
|
|
281
282
|
if mode.include?(:stderr)
|
|
282
283
|
stderrio.set_encoding(external_encoding, internal_encoding, **encoding_options)
|
|
@@ -41,9 +41,11 @@ module Fluent
|
|
|
41
41
|
else
|
|
42
42
|
mcall = method(:call_dig)
|
|
43
43
|
mdelete = method(:delete_nest)
|
|
44
|
+
mset = method(:set_nest)
|
|
44
45
|
singleton_class.module_eval do
|
|
45
46
|
define_method(:call, mcall)
|
|
46
47
|
define_method(:delete, mdelete)
|
|
48
|
+
define_method(:set, mset)
|
|
47
49
|
end
|
|
48
50
|
end
|
|
49
51
|
end
|
|
@@ -75,6 +77,18 @@ module Fluent
|
|
|
75
77
|
nil
|
|
76
78
|
end
|
|
77
79
|
|
|
80
|
+
def set(r, v)
|
|
81
|
+
r[@keys] = v
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# set_nest doesn't create intermediate object. If key doesn't exist, no effect.
|
|
85
|
+
# See also: https://bugs.ruby-lang.org/issues/11747
|
|
86
|
+
def set_nest(r, v)
|
|
87
|
+
r.dig(*@dig_keys)&.[]=(@last_key, v)
|
|
88
|
+
rescue
|
|
89
|
+
nil
|
|
90
|
+
end
|
|
91
|
+
|
|
78
92
|
def self.parse_parameter(param)
|
|
79
93
|
if param.start_with?('$.')
|
|
80
94
|
parse_dot_notation(param)
|
|
@@ -243,7 +243,7 @@ module Fluent
|
|
|
243
243
|
:protocol, :version, :min_version, :max_version, :ciphers, :insecure,
|
|
244
244
|
:ca_path, :cert_path, :private_key_path, :private_key_passphrase, :client_cert_auth,
|
|
245
245
|
:ca_cert_path, :ca_private_key_path, :ca_private_key_passphrase,
|
|
246
|
-
:generate_private_key_length,
|
|
246
|
+
:cert_verifier, :generate_private_key_length,
|
|
247
247
|
:generate_cert_country, :generate_cert_state, :generate_cert_state,
|
|
248
248
|
:generate_cert_locality, :generate_cert_common_name,
|
|
249
249
|
:generate_cert_expiration, :generate_cert_digest,
|
|
@@ -281,6 +281,8 @@ module Fluent
|
|
|
281
281
|
config_param :ca_private_key_path, :string, default: nil
|
|
282
282
|
config_param :ca_private_key_passphrase, :string, default: nil, secret: true
|
|
283
283
|
|
|
284
|
+
config_param :cert_verifier, :string, default: nil
|
|
285
|
+
|
|
284
286
|
# Options for generating certs by private CA certs or self-signed
|
|
285
287
|
config_param :generate_private_key_length, :integer, default: 2048
|
|
286
288
|
config_param :generate_cert_country, :string, default: 'US'
|
|
@@ -43,6 +43,13 @@ module Fluent
|
|
|
43
43
|
super
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
%i[after_start stop before_shutdown shutdown after_shutdown close terminate].each do |mth|
|
|
47
|
+
define_method(mth) do
|
|
48
|
+
@discovery_manager&.__send__(mth)
|
|
49
|
+
super()
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
46
53
|
private
|
|
47
54
|
|
|
48
55
|
# @param title [Symbol] the thread name. this value should be unique.
|
|
@@ -60,6 +60,14 @@ module Fluent
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
+
%i[after_start stop before_shutdown shutdown after_shutdown close terminate].each do |mth|
|
|
64
|
+
define_method(mth) do
|
|
65
|
+
@discoveries.each do |d|
|
|
66
|
+
d.__send__(mth)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
63
71
|
def run_once
|
|
64
72
|
# Don't care race in this loop intentionally
|
|
65
73
|
s = @queue.size
|
|
@@ -145,9 +145,16 @@ module Fluent
|
|
|
145
145
|
context.ciphers = ciphers
|
|
146
146
|
context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
147
147
|
context.cert_store = cert_store
|
|
148
|
-
context.verify_hostname =
|
|
149
|
-
context.cert = OpenSSL::X509::Certificate.new(File.read(cert_path)) if cert_path
|
|
148
|
+
context.verify_hostname = verify_fqdn && fqdn
|
|
150
149
|
context.key = OpenSSL::PKey::read(File.read(private_key_path), private_key_passphrase) if private_key_path
|
|
150
|
+
|
|
151
|
+
if cert_path
|
|
152
|
+
certs = socket_certificates_from_file(cert_path)
|
|
153
|
+
context.cert = certs.shift
|
|
154
|
+
unless certs.empty?
|
|
155
|
+
context.extra_chain_cert = certs
|
|
156
|
+
end
|
|
157
|
+
end
|
|
151
158
|
end
|
|
152
159
|
Fluent::TLS.set_version_to_context(context, version, min_version, max_version)
|
|
153
160
|
|
|
@@ -186,6 +193,17 @@ module Fluent
|
|
|
186
193
|
end
|
|
187
194
|
end
|
|
188
195
|
|
|
196
|
+
def socket_certificates_from_file(path)
|
|
197
|
+
data = File.read(path)
|
|
198
|
+
pattern = Regexp.compile('-+BEGIN CERTIFICATE-+\r?\n(?:[^-]*\r?\n)+-+END CERTIFICATE-+\r?\n?', Regexp::MULTILINE)
|
|
199
|
+
list = []
|
|
200
|
+
data.scan(pattern) { |match| list << OpenSSL::X509::Certificate.new(match) }
|
|
201
|
+
if list.length == 0
|
|
202
|
+
log.warn "cert_path does not contain a valid certificate"
|
|
203
|
+
end
|
|
204
|
+
list
|
|
205
|
+
end
|
|
206
|
+
|
|
189
207
|
def self.tls_verify_result_name(code)
|
|
190
208
|
case code
|
|
191
209
|
when OpenSSL::X509::V_OK then 'V_OK'
|
|
@@ -21,6 +21,8 @@ require 'fcntl'
|
|
|
21
21
|
module Fluent
|
|
22
22
|
module PluginHelper
|
|
23
23
|
module SocketOption
|
|
24
|
+
# ref: https://docs.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-linger
|
|
25
|
+
FORMAT_STRUCT_LINGER_WINDOWS = 'S!S!' # { u_short l_onoff; u_short l_linger; }
|
|
24
26
|
FORMAT_STRUCT_LINGER = 'I!I!' # { int l_onoff; int l_linger; }
|
|
25
27
|
FORMAT_STRUCT_TIMEVAL = 'L!L!' # { time_t tv_sec; suseconds_t tv_usec; }
|
|
26
28
|
|
|
@@ -49,9 +51,25 @@ module Fluent
|
|
|
49
51
|
if nonblock
|
|
50
52
|
sock.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
|
|
51
53
|
end
|
|
52
|
-
if
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
if Fluent.windows?
|
|
55
|
+
# To prevent closing socket forcibly on Windows,
|
|
56
|
+
# this options shouldn't be set up when linger_timeout equals to 0 (including nil).
|
|
57
|
+
# This unintended behavior always ocurrs on Windows when linger_timeout.to_i == 0.
|
|
58
|
+
# This unintented behavior causes "Errno::ECONNRESET: An existing connection was forcibly
|
|
59
|
+
# closed by the remote host." on Windows.
|
|
60
|
+
if linger_timeout.to_i > 0
|
|
61
|
+
if linger_timeout >= 2**16
|
|
62
|
+
log.warn "maximum linger_timeout is 65535(2^16 - 1). Set to 65535 forcibly."
|
|
63
|
+
linger_timeout = 2**16 - 1
|
|
64
|
+
end
|
|
65
|
+
optval = [1, linger_timeout.to_i].pack(FORMAT_STRUCT_LINGER_WINDOWS)
|
|
66
|
+
socket_option_set_one(sock, :SO_LINGER, optval)
|
|
67
|
+
end
|
|
68
|
+
else
|
|
69
|
+
if linger_timeout
|
|
70
|
+
optval = [1, linger_timeout.to_i].pack(FORMAT_STRUCT_LINGER)
|
|
71
|
+
socket_option_set_one(sock, :SO_LINGER, optval)
|
|
72
|
+
end
|
|
55
73
|
end
|
|
56
74
|
if recv_timeout
|
|
57
75
|
optval = [recv_timeout.to_i, 0].pack(FORMAT_STRUCT_TIMEVAL)
|
data/lib/fluent/supervisor.rb
CHANGED
|
@@ -301,6 +301,7 @@ module Fluent
|
|
|
301
301
|
|
|
302
302
|
log_level = params['log_level']
|
|
303
303
|
suppress_repeated_stacktrace = params['suppress_repeated_stacktrace']
|
|
304
|
+
ignore_repeated_log_interval = params['ignore_repeated_log_interval']
|
|
304
305
|
|
|
305
306
|
log_path = params['log_path']
|
|
306
307
|
chuser = params['chuser']
|
|
@@ -308,7 +309,7 @@ module Fluent
|
|
|
308
309
|
log_rotate_age = params['log_rotate_age']
|
|
309
310
|
log_rotate_size = params['log_rotate_size']
|
|
310
311
|
|
|
311
|
-
log_opts = {suppress_repeated_stacktrace: suppress_repeated_stacktrace}
|
|
312
|
+
log_opts = {suppress_repeated_stacktrace: suppress_repeated_stacktrace, ignore_repeated_log_interval: ignore_repeated_log_interval}
|
|
312
313
|
logger_initializer = Supervisor::LoggerInitializer.new(
|
|
313
314
|
log_path, log_level, chuser, chgroup, log_opts,
|
|
314
315
|
log_rotate_age: log_rotate_age,
|
|
@@ -345,6 +346,7 @@ module Fluent
|
|
|
345
346
|
chgroup: chgroup,
|
|
346
347
|
chumask: 0,
|
|
347
348
|
suppress_repeated_stacktrace: suppress_repeated_stacktrace,
|
|
349
|
+
ignore_repeated_log_interval: ignore_repeated_log_interval,
|
|
348
350
|
daemonize: daemonize,
|
|
349
351
|
rpc_endpoint: params['rpc_endpoint'],
|
|
350
352
|
counter_server: params['counter_server'],
|
|
@@ -439,9 +441,10 @@ module Fluent
|
|
|
439
441
|
self
|
|
440
442
|
end
|
|
441
443
|
|
|
442
|
-
def apply_options(format: nil, time_format: nil, log_dir_perm: nil)
|
|
444
|
+
def apply_options(format: nil, time_format: nil, log_dir_perm: nil, ignore_repeated_log_interval: nil)
|
|
443
445
|
$log.format = format if format
|
|
444
446
|
$log.time_format = time_format if time_format
|
|
447
|
+
$log.ignore_repeated_log_interval = ignore_repeated_log_interval if ignore_repeated_log_interval
|
|
445
448
|
|
|
446
449
|
if @path && log_dir_perm
|
|
447
450
|
File.chmod(log_dir_perm || 0755, File.dirname(@path))
|
|
@@ -468,6 +471,7 @@ module Fluent
|
|
|
468
471
|
root_dir: nil,
|
|
469
472
|
suppress_interval: 0,
|
|
470
473
|
suppress_repeated_stacktrace: true,
|
|
474
|
+
ignore_repeated_log_interval: nil,
|
|
471
475
|
without_source: nil,
|
|
472
476
|
use_v1_config: true,
|
|
473
477
|
strict_config_value: nil,
|
|
@@ -507,7 +511,7 @@ module Fluent
|
|
|
507
511
|
@cl_opt = opt
|
|
508
512
|
@conf = nil
|
|
509
513
|
|
|
510
|
-
log_opts = {
|
|
514
|
+
log_opts = {suppress_repeated_stacktrace: opt[:suppress_repeated_stacktrace], ignore_repeated_log_interval: opt[:ignore_repeated_log_interval]}
|
|
511
515
|
@log = LoggerInitializer.new(
|
|
512
516
|
@log_path, opt[:log_level], @chuser, @chgroup, log_opts,
|
|
513
517
|
log_rotate_age: @log_rotate_age,
|
|
@@ -552,7 +556,7 @@ module Fluent
|
|
|
552
556
|
end
|
|
553
557
|
|
|
554
558
|
if dry_run
|
|
555
|
-
$log.info '
|
|
559
|
+
$log.info 'finished dry run mode'
|
|
556
560
|
exit 0
|
|
557
561
|
else
|
|
558
562
|
supervise
|
|
@@ -589,7 +593,10 @@ module Fluent
|
|
|
589
593
|
|
|
590
594
|
main_process do
|
|
591
595
|
create_socket_manager if @standalone_worker
|
|
592
|
-
|
|
596
|
+
if @standalone_worker
|
|
597
|
+
ServerEngine::Privilege.change(@chuser, @chgroup)
|
|
598
|
+
File.umask(0)
|
|
599
|
+
end
|
|
593
600
|
MessagePackFactory.init(enable_time_support: @system_config.enable_msgpack_time_support)
|
|
594
601
|
Fluent::Engine.init(@system_config)
|
|
595
602
|
Fluent::Engine.run_configure(@conf)
|
|
@@ -628,6 +635,7 @@ module Fluent
|
|
|
628
635
|
format: @system_config.log.format,
|
|
629
636
|
time_format: @system_config.log.time_format,
|
|
630
637
|
log_dir_perm: @system_config.dir_permission,
|
|
638
|
+
ignore_repeated_log_interval: @system_config.ignore_repeated_log_interval
|
|
631
639
|
)
|
|
632
640
|
|
|
633
641
|
$log.info :supervisor, 'parsing config file is succeeded', path: @config_path
|
|
@@ -690,6 +698,7 @@ module Fluent
|
|
|
690
698
|
'root_dir' => @system_config.root_dir,
|
|
691
699
|
'log_level' => @system_config.log_level,
|
|
692
700
|
'suppress_repeated_stacktrace' => @system_config.suppress_repeated_stacktrace,
|
|
701
|
+
'ignore_repeated_log_interval' => @system_config.ignore_repeated_log_interval,
|
|
693
702
|
'rpc_endpoint' => @system_config.rpc_endpoint,
|
|
694
703
|
'enable_get_dump' => @system_config.enable_get_dump,
|
|
695
704
|
'counter_server' => @system_config.counter_server,
|
|
@@ -882,7 +891,11 @@ module Fluent
|
|
|
882
891
|
RUBY_ENCODING_OPTIONS_REGEX = %r{\A(-E|--encoding=|--internal-encoding=|--external-encoding=)}.freeze
|
|
883
892
|
|
|
884
893
|
def build_spawn_command
|
|
885
|
-
|
|
894
|
+
if ENV['TEST_RUBY_PATH']
|
|
895
|
+
fluentd_spawn_cmd = [ENV['TEST_RUBY_PATH']]
|
|
896
|
+
else
|
|
897
|
+
fluentd_spawn_cmd = [ServerEngine.ruby_bin_path]
|
|
898
|
+
end
|
|
886
899
|
|
|
887
900
|
rubyopt = ENV['RUBYOPT']
|
|
888
901
|
if rubyopt
|
|
@@ -897,10 +910,9 @@ module Fluent
|
|
|
897
910
|
|
|
898
911
|
# Adding `-h` so that it can avoid ruby's command blocking
|
|
899
912
|
# e.g. `ruby -Eascii-8bit:ascii-8bit` will block. but `ruby -Eascii-8bit:ascii-8bit -h` won't.
|
|
900
|
-
|
|
901
|
-
_, e, s = Open3.capture3("#{cmd} -h")
|
|
913
|
+
_, e, s = Open3.capture3(*fluentd_spawn_cmd, "-h")
|
|
902
914
|
if s.exitstatus != 0
|
|
903
|
-
$log.error('Invalid option is passed to RUBYOPT', command:
|
|
915
|
+
$log.error('Invalid option is passed to RUBYOPT', command: fluentd_spawn_cmd, error: e)
|
|
904
916
|
exit s.exitstatus
|
|
905
917
|
end
|
|
906
918
|
|