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
#
@@ -54,17 +55,22 @@ def initialize(log:, system_config: SystemConfig.new)
54
55
@inputs = [ ]
55
56
@suppress_emit_error_log_interval = 0
56
57
@next_emit_error_log_time = nil
57
- @without_source = false
58
- @enable_input_metrics = false
58
+ @without_source = system_config . without_source || false
59
+ @with_source_only = system_config . with_source_only || false
60
+ @source_only_buffer_agent = nil
61
+ @enable_input_metrics = system_config . enable_input_metrics || false
59
62
60
63
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
64
end
64
65
65
66
attr_reader :inputs
66
67
attr_reader :labels
67
68
69
+ def source_only_router
70
+ raise "[BUG] 'RootAgent#source_only_router' should not be called when 'with_source_only' is false" unless @with_source_only
71
+ @source_only_buffer_agent . event_router
72
+ end
73
+
68
74
def configure ( conf )
69
75
used_worker_ids = [ ]
70
76
available_worker_ids = ( 0 ..Fluent ::Engine . system_config . workers - 1 ) . to_a
@@ -148,6 +154,8 @@ def configure(conf)
148
154
149
155
super
150
156
157
+ setup_source_only_buffer_agent if @with_source_only
158
+
151
159
# initialize <source> elements
152
160
if @without_source
153
161
log . info :worker0 , "'--without-source' is applied. Ignore <source> sections"
@@ -169,16 +177,29 @@ def setup_error_label(e)
169
177
@error_collector = error_label . event_router
170
178
end
171
179
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 |
180
+ def setup_source_only_buffer_agent ( flush : false )
181
+ @source_only_buffer_agent = SourceOnlyBufferAgent . new ( log : log , system_config : Fluent ::Engine . system_config )
182
+ @source_only_buffer_agent . configure ( flush : flush )
183
+ end
184
+
185
+ def lifecycle ( desc : false , kind_callback : nil , kind_or_agent_list : nil )
186
+ unless kind_or_agent_list
187
+ if @with_source_only
188
+ kind_or_agent_list = [ :input , @source_only_buffer_agent ]
189
+ elsif @source_only_buffer_agent
190
+ # source_only_buffer_agent can re-reroute events, so the priority is equal to output_with_router.
191
+ kind_or_agent_list = [ :input , :output_with_router , @source_only_buffer_agent , @labels . values , :filter , :output ] . flatten
192
+ else
193
+ kind_or_agent_list = [ :input , :output_with_router , @labels . values , :filter , :output ] . flatten
194
+ end
195
+
196
+ kind_or_agent_list . reverse! if desc
197
+ end
198
+
199
+ kind_or_agent_list . each do |kind |
179
200
if kind . respond_to? ( :lifecycle )
180
- label = kind
181
- label . lifecycle ( desc : desc ) do |plugin , display_kind |
201
+ agent = kind
202
+ agent . lifecycle ( desc : desc ) do |plugin , display_kind |
182
203
yield plugin , display_kind
183
204
end
184
205
else
@@ -198,8 +219,8 @@ def lifecycle(desc: false, kind_callback: nil)
198
219
end
199
220
end
200
221
201
- def start
202
- lifecycle ( desc : true ) do |i | # instance
222
+ def start ( kind_or_agent_list : nil )
223
+ lifecycle ( desc : true , kind_or_agent_list : kind_or_agent_list ) do |i | # instance
203
224
i . start unless i . started?
204
225
# Input#start sometimes emits lots of events with in_tail/`read_from_head true` case
205
226
# and it causes deadlock for small buffer/queue output. To avoid such problem,
@@ -231,13 +252,45 @@ def flush!
231
252
flushing_threads . each { |t | t . join }
232
253
end
233
254
234
- def shutdown # Fluentd's shutdown sequence is stop, before_shutdown, shutdown, after_shutdown, close, terminate for plugins
255
+ def cancel_source_only!
256
+ # TODO exclusive lock
257
+ if @with_source_only
258
+ log . info "cancel --with-source-only mode and start the other plugins"
259
+ @with_source_only = false
260
+ start
261
+
262
+ lifecycle_control_list [ :input ] . each ( &:event_emitter_cancel_source_only )
263
+
264
+ # Want to make sure that the source_only_router finishes all process.
265
+ # Strictly speaking, we must make a forwarding feature for the source_only_router
266
+ # to make sure it.
267
+ # However, it would need exclusive lock for EventRouter and worsen its performance.
268
+ # So, just sleep a few seconds here.
269
+ sleep 5
270
+
271
+ shutdown ( kind_or_agent_list : [ @source_only_buffer_agent ] )
272
+ @source_only_buffer_agent = nil
273
+ end
274
+
275
+ if @source_only_buffer_agent
276
+ log . info "do nothing for canceling --with-source-only because it is already canceled, and the loading agent already exists"
277
+ return
278
+ end
279
+
280
+ # TODO This agent should stop after flushing its all buffer.
281
+ log . info "starts the loading agent for --with-source-only"
282
+ setup_source_only_buffer_agent ( flush : true )
283
+ start ( kind_or_agent_list : [ @source_only_buffer_agent ] )
284
+ end
285
+
286
+ def shutdown ( kind_or_agent_list : nil )
287
+ # Fluentd's shutdown sequence is stop, before_shutdown, shutdown, after_shutdown, close, terminate for plugins
235
288
# These method callers does `rescue Exception` to call methods of shutdown sequence as far as possible
236
289
# if plugin methods does something like infinite recursive call, `exit`, unregistering signal handlers or others.
237
290
# Plugins should be separated and be in sandbox to protect data in each plugins/buffers.
238
291
239
292
lifecycle_safe_sequence = -> ( method , checker ) {
240
- lifecycle do |instance , kind |
293
+ lifecycle ( kind_or_agent_list : kind_or_agent_list ) do |instance , kind |
241
294
begin
242
295
log . debug "calling #{ method } on #{ kind } plugin" , type : Plugin . lookup_type_from_class ( instance . class ) , plugin_id : instance . plugin_id
243
296
instance . __send__ ( method ) unless instance . __send__ ( checker )
@@ -260,7 +313,7 @@ def shutdown # Fluentd's shutdown sequence is stop, before_shutdown, shutdown, a
260
313
operation_threads . each { |t | t . join }
261
314
operation_threads . clear
262
315
}
263
- lifecycle ( kind_callback : callback ) do |instance , kind |
316
+ lifecycle ( kind_callback : callback , kind_or_agent_list : kind_or_agent_list ) do |instance , kind |
264
317
t = Thread . new do
265
318
Thread . current . abort_on_exception = true
266
319
begin
@@ -318,6 +371,7 @@ def add_source(type, conf)
318
371
# See also 'fluentd/plugin/input.rb'
319
372
input . context_router = @event_router
320
373
input . configure ( conf )
374
+ input . event_emitter_set_source_only if @with_source_only
321
375
if @enable_input_metrics
322
376
@event_router . add_metric_callbacks ( input . plugin_id , Proc . new { |es | input . metric_callback ( es ) } )
323
377
end
0 commit comments