fluentd 1.17.1-x64-mingw-ucrt → 1.18.0-x64-mingw-ucrt

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.
@@ -39,7 +39,8 @@ module Fluent
39
39
  scheme = tls_context ? 'https' : 'http'
40
40
  @uri = URI("#{scheme}://#{@addr}:#{@port}").to_s
41
41
  @router = Router.new(default_app)
42
- @reactor = Async::Reactor.new(nil, logger: Fluent::Log::ConsoleAdapter.wrap(@logger))
42
+ @server_task = nil
43
+ Console.logger = Fluent::Log::ConsoleAdapter.wrap(@logger)
43
44
 
44
45
  opts = if tls_context
45
46
  { ssl_context: tls_context }
@@ -54,24 +55,35 @@ module Fluent
54
55
  end
55
56
 
56
57
  def start(notify = nil)
58
+ Console.logger = Fluent::Log::ConsoleAdapter.wrap(@logger)
57
59
  @logger.debug("Start async HTTP server listening #{@uri}")
58
- task = @reactor.run do
59
- @server.run
60
60
 
61
+ Async do |task|
62
+ Console.logger = Fluent::Log::ConsoleAdapter.wrap(@logger)
63
+ @server_task = task.async do
64
+ Console.logger = Fluent::Log::ConsoleAdapter.wrap(@logger)
65
+ @server.run
66
+ end
61
67
  if notify
62
68
  notify.push(:ready)
63
69
  end
70
+
71
+ if async_v2?
72
+ @server_task_queue = ::Thread::Queue.new
73
+ @server_task_queue.pop
74
+ @server_task&.stop
75
+ end
64
76
  end
65
77
 
66
- task.stop
67
78
  @logger.debug('Finished HTTP server')
68
79
  end
69
80
 
70
81
  def stop
71
82
  @logger.debug('closing HTTP server')
72
-
73
- if @reactor
74
- @reactor.stop
83
+ if async_v2?
84
+ @server_task_queue&.push(:stop)
85
+ else
86
+ @server_task&.stop
75
87
  end
76
88
  end
77
89
 
@@ -88,6 +100,10 @@ module Fluent
88
100
  @router.mount(name, path, app || block)
89
101
  end
90
102
  end
103
+
104
+ private def async_v2?
105
+ Gem::Version.new(Async::VERSION) >= Gem::Version.new('2.0')
106
+ end
91
107
  end
92
108
  end
93
109
  end
@@ -84,6 +84,8 @@ module Fluent
84
84
  socket_options[:linger_timeout] ||= @transport_config&.linger_timeout || 0
85
85
  end
86
86
 
87
+ socket_options[:receive_buffer_size] ||= @transport_config&.receive_buffer_size
88
+
87
89
  socket_option_validate!(proto, **socket_options)
88
90
  socket_option_setter = ->(sock){ socket_option_set(sock, **socket_options) }
89
91
 
@@ -136,6 +138,8 @@ module Fluent
136
138
  socket_options[:linger_timeout] ||= @transport_config&.linger_timeout || 0
137
139
  end
138
140
 
141
+ socket_options[:receive_buffer_size] ||= @transport_config&.receive_buffer_size
142
+
139
143
  unless socket
140
144
  socket_option_validate!(proto, **socket_options)
141
145
  socket_option_setter = ->(sock){ socket_option_set(sock, **socket_options) }
@@ -247,6 +251,7 @@ module Fluent
247
251
  :generate_cert_country, :generate_cert_state, :generate_cert_state,
248
252
  :generate_cert_locality, :generate_cert_common_name,
249
253
  :generate_cert_expiration, :generate_cert_digest,
254
+ :ensure_fips,
250
255
  ]
251
256
 
252
257
  def server_create_transport_section_object(opts)
@@ -266,6 +271,9 @@ module Fluent
266
271
 
267
272
  ### Socket Params ###
268
273
 
274
+ desc "The max size of socket receive buffer. SO_RCVBUF"
275
+ config_param :receive_buffer_size, :size, default: nil
276
+
269
277
  # SO_LINGER 0 to send RST rather than FIN to avoid lots of connections sitting in TIME_WAIT at src.
270
278
  # Set positive value if needing to send FIN on closing on non-Windows.
271
279
  # (On Windows, Fluentd can send FIN with zero `linger_timeout` since Fluentd doesn't set 0 to SO_LINGER on Windows.
@@ -287,6 +295,7 @@ module Fluent
287
295
  config_param :max_version, :enum, list: Fluent::TLS::SUPPORTED_VERSIONS, default: nil
288
296
  config_param :ciphers, :string, default: Fluent::TLS::CIPHERS_DEFAULT
289
297
  config_param :insecure, :bool, default: false
298
+ config_param :ensure_fips, :bool, default: false
290
299
 
291
300
  # Cert signed by public CA
292
301
  config_param :ca_path, :string, default: nil
@@ -22,6 +22,7 @@ require 'fluent/label'
22
22
  require 'fluent/plugin'
23
23
  require 'fluent/system_config'
24
24
  require 'fluent/time'
25
+ require 'fluent/source_only_buffer_agent'
25
26
 
26
27
  module Fluent
27
28
  #
@@ -47,24 +48,57 @@ module Fluent
47
48
  class RootAgent < Agent
48
49
  ERROR_LABEL = "@ERROR".freeze # @ERROR is built-in error label
49
50
 
50
- def initialize(log:, system_config: SystemConfig.new)
51
+ class SourceOnlyMode
52
+ DISABLED = 0
53
+ NORMAL = 1
54
+ ONLY_ZERO_DOWNTIME_RESTART_READY = 2
55
+
56
+ def initialize(with_source_only, start_in_parallel)
57
+ if start_in_parallel
58
+ @mode = ONLY_ZERO_DOWNTIME_RESTART_READY
59
+ elsif with_source_only
60
+ @mode = NORMAL
61
+ else
62
+ @mode = DISABLED
63
+ end
64
+ end
65
+
66
+ def enabled?
67
+ @mode != DISABLED
68
+ end
69
+
70
+ def only_zero_downtime_restart_ready?
71
+ @mode == ONLY_ZERO_DOWNTIME_RESTART_READY
72
+ end
73
+
74
+ def disable!
75
+ @mode = DISABLED
76
+ end
77
+ end
78
+
79
+ def initialize(log:, system_config: SystemConfig.new, start_in_parallel: false)
51
80
  super(log: log)
52
81
 
53
82
  @labels = {}
54
83
  @inputs = []
55
84
  @suppress_emit_error_log_interval = 0
56
85
  @next_emit_error_log_time = nil
57
- @without_source = false
58
- @enable_input_metrics = false
86
+ @without_source = system_config.without_source || false
87
+ @source_only_mode = SourceOnlyMode.new(system_config.with_source_only, start_in_parallel)
88
+ @source_only_buffer_agent = nil
89
+ @enable_input_metrics = system_config.enable_input_metrics || false
59
90
 
60
91
  suppress_interval(system_config.emit_error_log_interval) unless system_config.emit_error_log_interval.nil?
61
- @without_source = system_config.without_source unless system_config.without_source.nil?
62
- @enable_input_metrics = !!system_config.enable_input_metrics
63
92
  end
64
93
 
65
94
  attr_reader :inputs
66
95
  attr_reader :labels
67
96
 
97
+ def source_only_router
98
+ raise "[BUG] 'RootAgent#source_only_router' should not be called when 'with_source_only' is false" unless @source_only_mode.enabled?
99
+ @source_only_buffer_agent.event_router
100
+ end
101
+
68
102
  def configure(conf)
69
103
  used_worker_ids = []
70
104
  available_worker_ids = (0..Fluent::Engine.system_config.workers - 1).to_a
@@ -148,6 +182,8 @@ module Fluent
148
182
 
149
183
  super
150
184
 
185
+ setup_source_only_buffer_agent if @source_only_mode.enabled?
186
+
151
187
  # initialize <source> elements
152
188
  if @without_source
153
189
  log.info :worker0, "'--without-source' is applied. Ignore <source> sections"
@@ -169,16 +205,36 @@ module Fluent
169
205
  @error_collector = error_label.event_router
170
206
  end
171
207
 
172
- def lifecycle(desc: false, kind_callback: nil)
173
- kind_or_label_list = if desc
174
- [:output, :filter, @labels.values.reverse, :output_with_router, :input].flatten
175
- else
176
- [:input, :output_with_router, @labels.values, :filter, :output].flatten
177
- end
178
- kind_or_label_list.each do |kind|
208
+ def setup_source_only_buffer_agent(flush: false)
209
+ @source_only_buffer_agent = SourceOnlyBufferAgent.new(log: log, system_config: Fluent::Engine.system_config)
210
+ @source_only_buffer_agent.configure(flush: flush)
211
+ end
212
+
213
+ def cleanup_source_only_buffer_agent
214
+ @source_only_buffer_agent&.cleanup
215
+ end
216
+
217
+ def lifecycle(desc: false, kind_callback: nil, kind_or_agent_list: nil)
218
+ only_zero_downtime_restart_ready = false
219
+
220
+ unless kind_or_agent_list
221
+ if @source_only_mode.enabled?
222
+ kind_or_agent_list = [:input, @source_only_buffer_agent]
223
+ only_zero_downtime_restart_ready = @source_only_mode.only_zero_downtime_restart_ready?
224
+ elsif @source_only_buffer_agent
225
+ # source_only_buffer_agent can re-reroute events, so the priority is equal to output_with_router.
226
+ kind_or_agent_list = [:input, :output_with_router, @source_only_buffer_agent, @labels.values, :filter, :output].flatten
227
+ else
228
+ kind_or_agent_list = [:input, :output_with_router, @labels.values, :filter, :output].flatten
229
+ end
230
+
231
+ kind_or_agent_list.reverse! if desc
232
+ end
233
+
234
+ kind_or_agent_list.each do |kind|
179
235
  if kind.respond_to?(:lifecycle)
180
- label = kind
181
- label.lifecycle(desc: desc) do |plugin, display_kind|
236
+ agent = kind
237
+ agent.lifecycle(desc: desc) do |plugin, display_kind|
182
238
  yield plugin, display_kind
183
239
  end
184
240
  else
@@ -189,6 +245,9 @@ module Fluent
189
245
  end
190
246
  display_kind = (kind == :output_with_router ? :output : kind)
191
247
  list.each do |instance|
248
+ if only_zero_downtime_restart_ready
249
+ next unless instance.respond_to?(:zero_downtime_restart_ready?) and instance.zero_downtime_restart_ready?
250
+ end
192
251
  yield instance, display_kind
193
252
  end
194
253
  end
@@ -198,8 +257,8 @@ module Fluent
198
257
  end
199
258
  end
200
259
 
201
- def start
202
- lifecycle(desc: true) do |i| # instance
260
+ def start(kind_or_agent_list: nil)
261
+ lifecycle(desc: true, kind_or_agent_list: kind_or_agent_list) do |i| # instance
203
262
  i.start unless i.started?
204
263
  # Input#start sometimes emits lots of events with in_tail/`read_from_head true` case
205
264
  # and it causes deadlock for small buffer/queue output. To avoid such problem,
@@ -231,13 +290,46 @@ module Fluent
231
290
  flushing_threads.each{|t| t.join }
232
291
  end
233
292
 
234
- def shutdown # Fluentd's shutdown sequence is stop, before_shutdown, shutdown, after_shutdown, close, terminate for plugins
293
+ def cancel_source_only!
294
+ unless @source_only_mode.enabled?
295
+ log.info "do nothing for canceling with-source-only because the current mode is not with-source-only."
296
+ return
297
+ end
298
+
299
+ log.info "cancel with-source-only mode and start the other plugins"
300
+ all_plugins = [:input, :output_with_router, @labels.values, :filter, :output].flatten.reverse
301
+ start(kind_or_agent_list: all_plugins)
302
+
303
+ lifecycle_control_list[:input].each(&:event_emitter_cancel_source_only)
304
+
305
+ # Want to make sure that the source_only_router finishes all process before
306
+ # shutting down the agent.
307
+ # Strictly speaking, it would be necessary to have exclusive lock between
308
+ # EventRouter and the shutting down process of this agent.
309
+ # However, adding lock to EventRouter would worsen its performance, and
310
+ # the entire shutting down process does not care about it either.
311
+ # So, sleep here just in case.
312
+ sleep 1
313
+
314
+ shutdown(kind_or_agent_list: [@source_only_buffer_agent])
315
+ @source_only_buffer_agent = nil
316
+
317
+ # This agent can stop after flushing its all buffer, but it is not implemented for now.
318
+ log.info "starts the loading agent for with-source-only"
319
+ setup_source_only_buffer_agent(flush: true)
320
+ start(kind_or_agent_list: [@source_only_buffer_agent])
321
+
322
+ @source_only_mode.disable!
323
+ end
324
+
325
+ def shutdown(kind_or_agent_list: nil)
326
+ # Fluentd's shutdown sequence is stop, before_shutdown, shutdown, after_shutdown, close, terminate for plugins
235
327
  # These method callers does `rescue Exception` to call methods of shutdown sequence as far as possible
236
328
  # if plugin methods does something like infinite recursive call, `exit`, unregistering signal handlers or others.
237
329
  # Plugins should be separated and be in sandbox to protect data in each plugins/buffers.
238
330
 
239
331
  lifecycle_safe_sequence = ->(method, checker) {
240
- lifecycle do |instance, kind|
332
+ lifecycle(kind_or_agent_list: kind_or_agent_list) do |instance, kind|
241
333
  begin
242
334
  log.debug "calling #{method} on #{kind} plugin", type: Plugin.lookup_type_from_class(instance.class), plugin_id: instance.plugin_id
243
335
  instance.__send__(method) unless instance.__send__(checker)
@@ -260,7 +352,7 @@ module Fluent
260
352
  operation_threads.each{|t| t.join }
261
353
  operation_threads.clear
262
354
  }
263
- lifecycle(kind_callback: callback) do |instance, kind|
355
+ lifecycle(kind_callback: callback, kind_or_agent_list: kind_or_agent_list) do |instance, kind|
264
356
  t = Thread.new do
265
357
  Thread.current.abort_on_exception = true
266
358
  begin
@@ -301,6 +393,8 @@ module Fluent
301
393
  lifecycle_unsafe_sequence.call(:close, :closed?)
302
394
 
303
395
  lifecycle_safe_sequence.call(:terminate, :terminated?)
396
+
397
+ cleanup_source_only_buffer_agent unless kind_or_agent_list
304
398
  end
305
399
 
306
400
  def suppress_interval(interval_time)
@@ -318,6 +412,7 @@ module Fluent
318
412
  # See also 'fluentd/plugin/input.rb'
319
413
  input.context_router = @event_router
320
414
  input.configure(conf)
415
+ input.event_emitter_apply_source_only if @source_only_mode.enabled?
321
416
  if @enable_input_metrics
322
417
  @event_router.add_metric_callbacks(input.plugin_id, Proc.new {|es| input.metric_callback(es) })
323
418
  end
@@ -0,0 +1,102 @@
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 'fluent/agent'
18
+ require 'fluent/system_config'
19
+
20
+ module Fluent
21
+ class SourceOnlyBufferAgent < Agent
22
+ # Use INSTANCE_ID to use the same base dir as the other workers.
23
+ # This will make recovery easier.
24
+ BUFFER_DIR_NAME = Fluent::INSTANCE_ID
25
+
26
+ def initialize(log:, system_config:)
27
+ super(log: log)
28
+
29
+ @default_buffer_path = File.join(system_config.root_dir || DEFAULT_BACKUP_DIR, 'source-only-buffer', BUFFER_DIR_NAME)
30
+ @optional_buffer_config = system_config.source_only_buffer.to_h.transform_keys(&:to_s)
31
+ @base_buffer_dir = nil
32
+ @actual_buffer_dir = nil
33
+ end
34
+
35
+ def configure(flush: false)
36
+ buffer_config = @optional_buffer_config.compact
37
+ buffer_config['flush_at_shutdown'] = flush ? 'true' : 'false'
38
+ buffer_config['flush_thread_count'] = 0 unless flush
39
+ buffer_config['path'] ||= @default_buffer_path
40
+
41
+ super(
42
+ Config::Element.new('SOURCE_ONLY_BUFFER', '', {}, [
43
+ Config::Element.new('match', '**', {'@type' => 'buffer', '@label' => '@ROOT'}, [
44
+ Config::Element.new('buffer', '', buffer_config, [])
45
+ ])
46
+ ])
47
+ )
48
+
49
+ @base_buffer_dir = buffer_config['path']
50
+ # It can be "#{@base_buffer_dir}/worker#{fluentd_worker_id}/" when using multiple workers
51
+ @actual_buffer_dir = File.dirname(outputs[0].buffer.path)
52
+
53
+ unless flush
54
+ log.info "with-source-only: the emitted data will be stored in the buffer files under" +
55
+ " #{@base_buffer_dir}. You can send SIGWINCH to the supervisor process to cancel" +
56
+ " with-source-only mode and process data."
57
+ end
58
+ end
59
+
60
+ def cleanup
61
+ unless (Dir.empty?(@actual_buffer_dir) rescue true)
62
+ log.warn "some buffer files remain in #{@base_buffer_dir}." +
63
+ " Please consider recovering or saving the buffer files in the directory." +
64
+ " To recover them, you can set the buffer path manually to system config and" +
65
+ " retry, i.e., restart Fluentd with with-source-only mode and send SIGWINCH again." +
66
+ " Config Example:\n#{config_example_to_recover(@base_buffer_dir)}"
67
+ return
68
+ end
69
+
70
+ begin
71
+ FileUtils.remove_dir(@base_buffer_dir)
72
+ rescue Errno::ENOENT
73
+ # This worker doesn't need to do anything. Another worker may remove the dir first.
74
+ rescue => e
75
+ log.warn "failed to remove the buffer directory: #{@base_buffer_dir}", error: e
76
+ end
77
+ end
78
+
79
+ def emit_error_event(tag, time, record, error)
80
+ error_info = {error: error, location: (error.backtrace ? error.backtrace.first : nil), tag: tag, time: time, record: record}
81
+ log.warn "SourceOnlyBufferAgent: dump an error event:", error_info
82
+ end
83
+
84
+ def handle_emits_error(tag, es, error)
85
+ error_info = {error: error, location: (error.backtrace ? error.backtrace.first : nil), tag: tag}
86
+ log.warn "SourceOnlyBufferAgent: emit transaction failed:", error_info
87
+ log.warn_backtrace
88
+ end
89
+
90
+ private
91
+
92
+ def config_example_to_recover(path)
93
+ <<~EOC
94
+ <system>
95
+ <source_only_buffer>
96
+ path #{path}
97
+ </source_only_buffer>
98
+ </system>
99
+ EOC
100
+ end
101
+ end
102
+ end