fluentd 0.14.3 → 0.14.4
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.
Potentially problematic release.
This version of fluentd might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ChangeLog +59 -1131
- data/Rakefile +15 -0
- data/appveyor.yml +2 -2
- data/example/multi_filters.conf +61 -0
- data/fluentd.gemspec +19 -16
- data/lib/fluent/agent.rb +3 -0
- data/lib/fluent/command/debug.rb +4 -4
- data/lib/fluent/compat/handle_tag_and_time_mixin.rb +2 -0
- data/lib/fluent/compat/output.rb +5 -2
- data/lib/fluent/config/configure_proxy.rb +26 -5
- data/lib/fluent/config/error.rb +3 -0
- data/lib/fluent/config/section.rb +15 -0
- data/lib/fluent/event_router.rb +77 -4
- data/lib/fluent/plugin/base.rb +12 -3
- data/lib/fluent/plugin/filter.rb +48 -6
- data/lib/fluent/plugin/filter_record_transformer.rb +3 -1
- data/lib/fluent/plugin/filter_stdout.rb +0 -4
- data/lib/fluent/plugin/in_debug_agent.rb +5 -5
- data/lib/fluent/plugin/in_dummy.rb +9 -1
- data/lib/fluent/plugin/in_forward.rb +32 -14
- data/lib/fluent/plugin/in_monitor_agent.rb +31 -77
- data/lib/fluent/plugin/in_tail.rb +37 -9
- data/lib/fluent/plugin/out_forward.rb +2 -13
- data/lib/fluent/plugin/output.rb +16 -1
- data/lib/fluent/plugin/storage_local.rb +16 -0
- data/lib/fluent/plugin_helper/timer.rb +6 -1
- data/lib/fluent/root_agent.rb +3 -0
- data/lib/fluent/supervisor.rb +62 -9
- data/lib/fluent/test/base.rb +3 -0
- data/lib/fluent/test/driver/base.rb +5 -0
- data/lib/fluent/test/formatter_test.rb +2 -0
- data/lib/fluent/test/parser_test.rb +2 -0
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +1 -2
- data/test/compat/test_calls_super.rb +2 -0
- data/test/config/test_configurable.rb +88 -0
- data/test/config/test_types.rb +7 -3
- data/test/plugin/test_filter.rb +121 -23
- data/test/plugin/test_filter_record_transformer.rb +22 -6
- data/test/plugin/test_in_debug_agent.rb +2 -2
- data/test/plugin/test_in_forward.rb +54 -6
- data/test/plugin/test_in_monitor_agent.rb +329 -0
- data/test/plugin/test_in_tail.rb +73 -0
- data/test/plugin/test_out_forward.rb +1 -0
- data/test/plugin/test_output.rb +53 -0
- data/test/plugin/test_output_as_buffered.rb +13 -0
- data/test/plugin/test_output_as_buffered_overflow.rb +3 -0
- data/test/plugin/test_output_as_buffered_retries.rb +11 -0
- data/test/plugin/test_output_as_buffered_secondary.rb +12 -0
- data/test/plugin/test_output_as_standard.rb +12 -0
- data/test/plugin_helper/test_compat_parameters.rb +2 -0
- data/test/plugin_helper/test_timer.rb +31 -0
- data/test/test_event_router.rb +87 -0
- data/test/test_filter.rb +48 -6
- data/test/test_log.rb +5 -2
- data/test/test_output.rb +41 -1
- data/test/test_plugin_classes.rb +17 -9
- data/test/test_root_agent.rb +146 -0
- metadata +51 -67
@@ -67,14 +67,10 @@ module Fluent
|
|
67
67
|
config_param :multiline_flush_interval, :time, default: nil
|
68
68
|
desc 'Enable the additional watch timer.'
|
69
69
|
config_param :enable_watch_timer, :bool, default: true
|
70
|
+
desc 'The encoding after conversion of the input.'
|
71
|
+
config_param :encoding, :string, default: nil
|
70
72
|
desc 'The encoding of the input.'
|
71
|
-
config_param :
|
72
|
-
begin
|
73
|
-
Encoding.find(encoding_name)
|
74
|
-
rescue ArgumentError => e
|
75
|
-
raise ConfigError, e.message
|
76
|
-
end
|
77
|
-
end
|
73
|
+
config_param :from_encoding, :string, default: nil
|
78
74
|
desc 'Add the log path being tailed to records. Specify the field name to be used.'
|
79
75
|
config_param :path_key, :string, default: nil
|
80
76
|
|
@@ -95,6 +91,7 @@ module Fluent
|
|
95
91
|
|
96
92
|
configure_parser(conf)
|
97
93
|
configure_tag
|
94
|
+
configure_encoding
|
98
95
|
|
99
96
|
@multiline_mode = conf['format'] =~ /multiline/
|
100
97
|
@receive_handler = if @multiline_mode
|
@@ -120,6 +117,25 @@ module Fluent
|
|
120
117
|
end
|
121
118
|
end
|
122
119
|
|
120
|
+
def configure_encoding
|
121
|
+
unless @encoding
|
122
|
+
if @from_encoding
|
123
|
+
raise ConfigError, "tail: 'from_encoding' parameter must be specified with 'encoding' parameter."
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
@encoding = parse_encoding_param(@encoding) if @encoding
|
128
|
+
@from_encoding = parse_encoding_param(@from_encoding) if @from_encoding
|
129
|
+
end
|
130
|
+
|
131
|
+
def parse_encoding_param(encoding_name)
|
132
|
+
begin
|
133
|
+
Encoding.find(encoding_name) if encoding_name
|
134
|
+
rescue ArgumentError => e
|
135
|
+
raise ConfigError, e.message
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
123
139
|
def start
|
124
140
|
super
|
125
141
|
|
@@ -254,7 +270,13 @@ module Fluent
|
|
254
270
|
def flush_buffer(tw)
|
255
271
|
if lb = tw.line_buffer
|
256
272
|
lb.chomp!
|
257
|
-
|
273
|
+
if @encoding
|
274
|
+
if @from_encoding
|
275
|
+
lb.encode!(@encoding, @from_encoding)
|
276
|
+
else
|
277
|
+
lb.force_encoding(@encoding)
|
278
|
+
end
|
279
|
+
end
|
258
280
|
@parser.parse(lb) { |time, record|
|
259
281
|
if time && record
|
260
282
|
tag = if @tag_prefix || @tag_suffix
|
@@ -303,7 +325,13 @@ module Fluent
|
|
303
325
|
def convert_line_to_event(line, es, tail_watcher)
|
304
326
|
begin
|
305
327
|
line.chomp! # remove \n
|
306
|
-
|
328
|
+
if @encoding
|
329
|
+
if @from_encoding
|
330
|
+
line.encode!(@encoding, @from_encoding)
|
331
|
+
else
|
332
|
+
line.force_encoding(@encoding)
|
333
|
+
end
|
334
|
+
end
|
307
335
|
@parser.parse(line) { |time, record|
|
308
336
|
if time && record
|
309
337
|
record[@path_key] ||= tail_watcher.path unless @path_key.nil?
|
@@ -89,23 +89,12 @@ module Fluent
|
|
89
89
|
|
90
90
|
attr_reader :nodes
|
91
91
|
|
92
|
-
|
93
|
-
config_param :
|
94
|
-
config_param :host, :string, default: nil
|
92
|
+
config_param :port, :integer, default: LISTEN_PORT, obsoleted: "User <server> section instead."
|
93
|
+
config_param :host, :string, default: nil, obsoleted: "Use <server> section instead."
|
95
94
|
|
96
95
|
def configure(conf)
|
97
96
|
super
|
98
97
|
|
99
|
-
# backward compatibility
|
100
|
-
if host = conf['host']
|
101
|
-
log.warn "'host' option in forward output is obsoleted. Use '<server> host xxx </server>' instead."
|
102
|
-
port = conf['port']
|
103
|
-
port = port ? port.to_i : LISTEN_PORT
|
104
|
-
element = conf.add_element('server')
|
105
|
-
element['host'] = host
|
106
|
-
element['port'] = port.to_s
|
107
|
-
end
|
108
|
-
|
109
98
|
recover_sample_size = @recover_wait / @heartbeat_interval
|
110
99
|
|
111
100
|
if @dns_round_robin
|
data/lib/fluent/plugin/output.rb
CHANGED
@@ -301,7 +301,7 @@ module Fluent
|
|
301
301
|
@secondary.acts_as_secondary(self)
|
302
302
|
@secondary.configure(secondary_conf)
|
303
303
|
@secondary.router = router if @secondary.has_router?
|
304
|
-
if self.class != @secondary.class
|
304
|
+
if (self.class != @secondary.class) && (@custom_format || @secondary.implement?(:custom_format))
|
305
305
|
log.warn "secondary type should be same with primary one", primary: self.class.to_s, secondary: @secondary.class.to_s
|
306
306
|
end
|
307
307
|
else
|
@@ -384,6 +384,11 @@ module Fluent
|
|
384
384
|
@secondary.start if @secondary
|
385
385
|
end
|
386
386
|
|
387
|
+
def after_start
|
388
|
+
super
|
389
|
+
@secondary.after_start if @secondary
|
390
|
+
end
|
391
|
+
|
387
392
|
def stop
|
388
393
|
@secondary.stop if @secondary
|
389
394
|
@buffer.stop if @buffering && @buffer
|
@@ -922,6 +927,11 @@ module Fluent
|
|
922
927
|
interval = @buffer_config.flush_thread_interval
|
923
928
|
end
|
924
929
|
|
930
|
+
while !self.after_started? && !self.stopped?
|
931
|
+
sleep 0.5
|
932
|
+
end
|
933
|
+
log.debug "enqueue_thread actually running"
|
934
|
+
|
925
935
|
begin
|
926
936
|
while @output_flush_threads_running
|
927
937
|
now_int = Time.now.to_i
|
@@ -969,6 +979,11 @@ module Fluent
|
|
969
979
|
clock_id = Process::CLOCK_MONOTONIC rescue Process::CLOCK_MONOTONIC_RAW
|
970
980
|
state.next_time = Process.clock_gettime(clock_id) + flush_thread_interval
|
971
981
|
|
982
|
+
while !self.after_started? && !self.stopped?
|
983
|
+
sleep 0.5
|
984
|
+
end
|
985
|
+
log.debug "flush_thread actually running"
|
986
|
+
|
972
987
|
begin
|
973
988
|
# This thread don't use `thread_current_running?` because this thread should run in `before_shutdown` phase
|
974
989
|
while @output_flush_threads_running
|
@@ -1,3 +1,19 @@
|
|
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
|
+
|
1
17
|
require 'fluent/plugin'
|
2
18
|
require 'fluent/plugin/storage'
|
3
19
|
|
@@ -66,6 +66,7 @@ module Fluent
|
|
66
66
|
def initialize(title, interval, repeat, log, checker, &callback)
|
67
67
|
@title = title
|
68
68
|
@callback = callback
|
69
|
+
@repeat = repeat
|
69
70
|
@log = log
|
70
71
|
@checker = checker
|
71
72
|
super(interval, repeat)
|
@@ -76,8 +77,12 @@ module Fluent
|
|
76
77
|
rescue => e
|
77
78
|
@log.error "Unexpected error raised. Stopping the timer.", title: @title, error: e
|
78
79
|
@log.error_backtrace
|
79
|
-
|
80
|
+
detach
|
80
81
|
@log.error "Timer detached.", title: @title
|
82
|
+
ensure
|
83
|
+
if attached?
|
84
|
+
detach unless @repeat
|
85
|
+
end
|
81
86
|
end
|
82
87
|
end
|
83
88
|
end
|
data/lib/fluent/root_agent.rb
CHANGED
data/lib/fluent/supervisor.rb
CHANGED
@@ -29,8 +29,10 @@ require 'shellwords'
|
|
29
29
|
|
30
30
|
if Fluent.windows?
|
31
31
|
require 'windows/library'
|
32
|
+
require 'windows/synchronize'
|
32
33
|
require 'windows/system_info'
|
33
34
|
include Windows::Library
|
35
|
+
include Windows::Synchronize
|
34
36
|
include Windows::SystemInfo
|
35
37
|
require 'win32/ipc'
|
36
38
|
require 'win32/event'
|
@@ -48,16 +50,17 @@ module Fluent
|
|
48
50
|
end
|
49
51
|
install_supervisor_signal_handlers
|
50
52
|
|
53
|
+
if config[:signame]
|
54
|
+
@signame = config[:signame]
|
55
|
+
install_windows_event_handler
|
56
|
+
end
|
57
|
+
|
51
58
|
socket_manager_path = ServerEngine::SocketManager::Server.generate_path
|
52
59
|
ServerEngine::SocketManager::Server.open(socket_manager_path)
|
53
60
|
ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = socket_manager_path.to_s
|
54
61
|
end
|
55
62
|
|
56
63
|
def after_run
|
57
|
-
if Time.now - @start_time < 1
|
58
|
-
$log.warn "process died within 1 second. exit."
|
59
|
-
end
|
60
|
-
|
61
64
|
stop_rpc_server if @rpc_endpoint
|
62
65
|
end
|
63
66
|
|
@@ -135,6 +138,22 @@ module Fluent
|
|
135
138
|
end unless Fluent.windows?
|
136
139
|
end
|
137
140
|
|
141
|
+
def install_windows_event_handler
|
142
|
+
Thread.new do
|
143
|
+
ev = Win32::Event.new(@signame)
|
144
|
+
begin
|
145
|
+
ev.reset
|
146
|
+
until WaitForSingleObject(ev.handle, 0) == WAIT_OBJECT_0
|
147
|
+
sleep 1
|
148
|
+
end
|
149
|
+
kill_worker
|
150
|
+
stop(true)
|
151
|
+
ensure
|
152
|
+
ev.close
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
138
157
|
def supervisor_sighup_handler
|
139
158
|
kill_worker
|
140
159
|
end
|
@@ -220,10 +239,13 @@ module Fluent
|
|
220
239
|
logger_initializer.init
|
221
240
|
logger = $log
|
222
241
|
|
242
|
+
command_sender = Fluent.windows? ? "pipe" : "signal"
|
243
|
+
|
223
244
|
# ServerEngine's "daemonize" option is boolean, and path of pid file is brought by "pid_path"
|
224
245
|
pid_path = params['daemonize']
|
225
246
|
daemonize = !!params['daemonize']
|
226
247
|
main_cmd = params['main_cmd']
|
248
|
+
signame = params['signame']
|
227
249
|
|
228
250
|
se_config = {
|
229
251
|
worker_type: 'spawn',
|
@@ -233,6 +255,8 @@ module Fluent
|
|
233
255
|
log_stderr: false,
|
234
256
|
enable_heartbeat: true,
|
235
257
|
auto_heartbeat: false,
|
258
|
+
unrecoverable_exit_codes: [2],
|
259
|
+
stop_immediately_at_unrecoverable_exit: true,
|
236
260
|
logger: logger,
|
237
261
|
log: logger.out,
|
238
262
|
log_path: log_path,
|
@@ -240,6 +264,7 @@ module Fluent
|
|
240
264
|
logger_initializer: logger_initializer,
|
241
265
|
chuser: chuser,
|
242
266
|
chgroup: chgroup,
|
267
|
+
chumask: 0,
|
243
268
|
suppress_repeated_stacktrace: suppress_repeated_stacktrace,
|
244
269
|
daemonize: daemonize,
|
245
270
|
rpc_endpoint: rpc_endpoint,
|
@@ -250,8 +275,10 @@ module Fluent
|
|
250
275
|
WorkerModule.name,
|
251
276
|
path,
|
252
277
|
JSON.dump(params)],
|
278
|
+
command_sender: command_sender,
|
253
279
|
fluentd_conf: fluentd_conf,
|
254
280
|
main_cmd: main_cmd,
|
281
|
+
signame: signame,
|
255
282
|
}
|
256
283
|
if daemonize
|
257
284
|
se_config[:pid_path] = pid_path
|
@@ -280,8 +307,8 @@ module Fluent
|
|
280
307
|
if @path && @path != "-"
|
281
308
|
@io = File.open(@path, "a")
|
282
309
|
if @chuser || @chgroup
|
283
|
-
chuid = @chuser ? ServerEngine::
|
284
|
-
chgid = @chgroup ? ServerEngine::
|
310
|
+
chuid = @chuser ? ServerEngine::Privilege.get_etc_passwd(@chuser).uid : nil
|
311
|
+
chgid = @chgroup ? ServerEngine::Privilege.get_etc_group(@chgroup).gid : nil
|
285
312
|
File.chown(chuid, chgid, @path)
|
286
313
|
end
|
287
314
|
else
|
@@ -489,6 +516,7 @@ module Fluent
|
|
489
516
|
params['chgroup'] = @chgroup
|
490
517
|
params['use_v1_config'] = @use_v1_config
|
491
518
|
params['suppress_repeated_stacktrace'] = @suppress_repeated_stacktrace
|
519
|
+
params['signame'] = @signame
|
492
520
|
|
493
521
|
se = ServerEngine.create(ServerModule, WorkerModule){
|
494
522
|
Fluent::Supervisor.load_config(@config_path, params)
|
@@ -527,6 +555,29 @@ module Fluent
|
|
527
555
|
trap :USR1 do
|
528
556
|
flush_buffer
|
529
557
|
end unless Fluent.windows?
|
558
|
+
|
559
|
+
if Fluent.windows?
|
560
|
+
command_pipe = STDIN.dup
|
561
|
+
STDIN.reopen(File::NULL, "rb")
|
562
|
+
command_pipe.binmode
|
563
|
+
command_pipe.sync = true
|
564
|
+
|
565
|
+
Thread.new do
|
566
|
+
loop do
|
567
|
+
cmd = command_pipe.gets.chomp
|
568
|
+
case cmd
|
569
|
+
when "GRACEFUL_STOP", "IMMEDIATE_STOP"
|
570
|
+
$log.debug "fluentd main process get #{cmd} command"
|
571
|
+
@finished = true
|
572
|
+
$log.debug "getting start to shutdown main process"
|
573
|
+
Fluent::Engine.stop
|
574
|
+
break
|
575
|
+
else
|
576
|
+
$log.warn "fluentd main process get unknown command [#{cmd}]"
|
577
|
+
end
|
578
|
+
end
|
579
|
+
end
|
580
|
+
end
|
530
581
|
end
|
531
582
|
|
532
583
|
def flush_buffer
|
@@ -549,6 +600,8 @@ module Fluent
|
|
549
600
|
def main_process(&block)
|
550
601
|
Process.setproctitle("worker:#{@process_name}") if @process_name
|
551
602
|
|
603
|
+
configuration_error = false
|
604
|
+
|
552
605
|
begin
|
553
606
|
block.call
|
554
607
|
rescue Fluent::ConfigError
|
@@ -562,7 +615,7 @@ module Fluent
|
|
562
615
|
console.error "config error", file: @config_path, error: $!.to_s
|
563
616
|
console.debug_backtrace
|
564
617
|
end
|
565
|
-
|
618
|
+
configuration_error = true
|
566
619
|
rescue
|
567
620
|
$log.error "unexpected error", error: $!.to_s
|
568
621
|
$log.error_backtrace
|
@@ -576,7 +629,7 @@ module Fluent
|
|
576
629
|
end
|
577
630
|
end
|
578
631
|
|
579
|
-
exit! 1
|
632
|
+
exit!(configuration_error ? 2 : 1)
|
580
633
|
end
|
581
634
|
|
582
635
|
def read_config
|
@@ -598,7 +651,7 @@ module Fluent
|
|
598
651
|
end
|
599
652
|
|
600
653
|
def change_privilege
|
601
|
-
ServerEngine::
|
654
|
+
ServerEngine::Privilege.change(@chuser, @chgroup)
|
602
655
|
end
|
603
656
|
|
604
657
|
def init_engine
|
data/lib/fluent/test/base.rb
CHANGED
@@ -30,7 +30,9 @@ module Fluent
|
|
30
30
|
if block
|
31
31
|
# Create new class for test w/ overwritten methods
|
32
32
|
# klass.dup is worse because its ancestors does NOT include original class name
|
33
|
+
klass_name = klass.name
|
33
34
|
klass = Class.new(klass)
|
35
|
+
klass.define_singleton_method("name") { klass_name }
|
34
36
|
klass.module_eval(&block)
|
35
37
|
end
|
36
38
|
@instance = klass.new
|
@@ -62,6 +64,7 @@ module Fluent
|
|
62
64
|
# num_waits is for checking thread status. This will be removed after improved plugin API
|
63
65
|
def run(num_waits = 10, &block)
|
64
66
|
@instance.start
|
67
|
+
@instance.after_start
|
65
68
|
begin
|
66
69
|
# wait until thread starts
|
67
70
|
num_waits.times { sleep 0.05 }
|
@@ -31,7 +31,9 @@ module Fluent
|
|
31
31
|
if block
|
32
32
|
# Create new class for test w/ overwritten methods
|
33
33
|
# klass.dup is worse because its ancestors does NOT include original class name
|
34
|
+
klass_name = klass.name
|
34
35
|
klass = Class.new(klass)
|
36
|
+
klass.define_singleton_method("name") { klass_name }
|
35
37
|
klass.module_eval(&block)
|
36
38
|
end
|
37
39
|
@instance = klass.new
|
@@ -86,6 +88,9 @@ module Fluent
|
|
86
88
|
@instance.start
|
87
89
|
instance_hook_after_started
|
88
90
|
end
|
91
|
+
unless @instance.after_started?
|
92
|
+
@instance.after_start
|
93
|
+
end
|
89
94
|
end
|
90
95
|
|
91
96
|
def instance_hook_after_started
|
@@ -26,7 +26,9 @@ module Fluent
|
|
26
26
|
if block
|
27
27
|
# Create new class for test w/ overwritten methods
|
28
28
|
# klass.dup is worse because its ancestors does NOT include original class name
|
29
|
+
klass_name = klass_or_str.name
|
29
30
|
klass_or_str = Class.new(klass_or_str)
|
31
|
+
klass_or_str.define_singleton_method("name") { klass_name }
|
30
32
|
klass_or_str.module_eval(&block)
|
31
33
|
end
|
32
34
|
@instance = klass_or_str.new
|
@@ -25,7 +25,9 @@ module Fluent
|
|
25
25
|
if block
|
26
26
|
# Create new class for test w/ overwritten methods
|
27
27
|
# klass.dup is worse because its ancestors does NOT include original class name
|
28
|
+
klass_name = klass_or_str.name
|
28
29
|
klass_or_str = Class.new(klass_or_str)
|
30
|
+
klass_or_str.define_singleton_method("name") { klass_name }
|
29
31
|
klass_or_str.module_eval(&block)
|
30
32
|
end
|
31
33
|
case klass_or_str.instance_method(:initialize).arity
|