fluentd 0.14.8 → 0.14.9
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/.gitignore +2 -0
- data/CONTRIBUTING.md +6 -1
- data/ChangeLog +38 -0
- data/Rakefile +21 -0
- data/example/out_exec_filter.conf +42 -0
- data/lib/fluent/agent.rb +2 -2
- data/lib/fluent/command/binlog_reader.rb +1 -1
- data/lib/fluent/command/cat.rb +5 -2
- data/lib/fluent/compat/output.rb +7 -8
- data/lib/fluent/compat/parser.rb +139 -11
- data/lib/fluent/config/configure_proxy.rb +2 -11
- data/lib/fluent/config/section.rb +7 -0
- data/lib/fluent/configurable.rb +1 -3
- data/lib/fluent/log.rb +1 -1
- data/lib/fluent/plugin/base.rb +17 -0
- data/lib/fluent/plugin/filter_parser.rb +108 -0
- data/lib/fluent/plugin/filter_record_transformer.rb +4 -7
- data/lib/fluent/plugin/filter_stdout.rb +1 -1
- data/lib/fluent/plugin/formatter.rb +5 -0
- data/lib/fluent/plugin/formatter_msgpack.rb +4 -0
- data/lib/fluent/plugin/formatter_stdout.rb +3 -2
- data/lib/fluent/plugin/formatter_tsv.rb +34 -0
- data/lib/fluent/plugin/in_exec.rb +48 -93
- data/lib/fluent/plugin/in_forward.rb +25 -105
- data/lib/fluent/plugin/in_http.rb +68 -65
- data/lib/fluent/plugin/in_syslog.rb +29 -51
- data/lib/fluent/plugin/multi_output.rb +1 -3
- data/lib/fluent/plugin/out_exec.rb +58 -71
- data/lib/fluent/plugin/out_exec_filter.rb +199 -279
- data/lib/fluent/plugin/out_file.rb +155 -80
- data/lib/fluent/plugin/out_forward.rb +44 -47
- data/lib/fluent/plugin/out_stdout.rb +6 -21
- data/lib/fluent/plugin/output.rb +23 -17
- data/lib/fluent/plugin/parser.rb +121 -61
- data/lib/fluent/plugin/parser_csv.rb +9 -3
- data/lib/fluent/plugin/parser_json.rb +37 -35
- data/lib/fluent/plugin/parser_ltsv.rb +11 -19
- data/lib/fluent/plugin/parser_msgpack.rb +50 -0
- data/lib/fluent/plugin/parser_regexp.rb +15 -42
- data/lib/fluent/plugin/parser_tsv.rb +8 -3
- data/lib/fluent/plugin_helper.rb +8 -1
- data/lib/fluent/plugin_helper/child_process.rb +139 -73
- data/lib/fluent/plugin_helper/compat_parameters.rb +93 -4
- data/lib/fluent/plugin_helper/event_emitter.rb +14 -1
- data/lib/fluent/plugin_helper/extract.rb +16 -4
- data/lib/fluent/plugin_helper/formatter.rb +9 -11
- data/lib/fluent/plugin_helper/inject.rb +4 -0
- data/lib/fluent/plugin_helper/parser.rb +3 -3
- data/lib/fluent/root_agent.rb +1 -1
- data/lib/fluent/test/driver/base.rb +51 -37
- data/lib/fluent/test/driver/base_owner.rb +18 -8
- data/lib/fluent/test/driver/multi_output.rb +2 -1
- data/lib/fluent/test/driver/output.rb +29 -6
- data/lib/fluent/test/helpers.rb +3 -1
- data/lib/fluent/test/log.rb +4 -0
- data/lib/fluent/test/startup_shutdown.rb +13 -0
- data/lib/fluent/time.rb +14 -8
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_binlog_reader.rb +5 -1
- data/test/config/test_configurable.rb +173 -0
- data/test/config/test_configure_proxy.rb +0 -43
- data/test/plugin/test_base.rb +16 -0
- data/test/plugin/test_filter_parser.rb +665 -0
- data/test/plugin/test_filter_record_transformer.rb +11 -3
- data/test/plugin/test_filter_stdout.rb +18 -27
- data/test/plugin/test_in_dummy.rb +1 -1
- data/test/plugin/test_in_exec.rb +206 -94
- data/test/plugin/test_in_forward.rb +310 -327
- data/test/plugin/test_in_http.rb +310 -186
- data/test/plugin/test_out_exec.rb +223 -68
- data/test/plugin/test_out_exec_filter.rb +520 -169
- data/test/plugin/test_out_file.rb +620 -177
- data/test/plugin/test_out_forward.rb +110 -132
- data/test/plugin/test_out_null.rb +1 -1
- data/test/plugin/test_out_secondary_file.rb +4 -2
- data/test/plugin/test_out_stdout.rb +14 -35
- data/test/plugin/test_parser.rb +359 -0
- data/test/plugin/test_parser_csv.rb +1 -2
- data/test/plugin/test_parser_json.rb +3 -4
- data/test/plugin/test_parser_labeled_tsv.rb +1 -2
- data/test/plugin/test_parser_none.rb +1 -2
- data/test/plugin/test_parser_regexp.rb +8 -4
- data/test/plugin/test_parser_tsv.rb +4 -3
- data/test/plugin_helper/test_child_process.rb +184 -0
- data/test/plugin_helper/test_compat_parameters.rb +88 -1
- data/test/plugin_helper/test_extract.rb +0 -1
- data/test/plugin_helper/test_formatter.rb +5 -2
- data/test/plugin_helper/test_parser.rb +6 -5
- data/test/test_output.rb +24 -2
- data/test/test_plugin_classes.rb +20 -0
- data/test/test_root_agent.rb +139 -0
- data/test/test_test_drivers.rb +132 -0
- metadata +12 -4
- data/test/plugin/test_parser_base.rb +0 -32
|
@@ -48,10 +48,19 @@ module Fluent
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
PARSER_PARAMS = {
|
|
51
|
-
"format" =>
|
|
51
|
+
"format" => nil,
|
|
52
|
+
"types" => nil,
|
|
53
|
+
"types_delimiter" => nil,
|
|
54
|
+
"types_label_delimiter" => nil,
|
|
55
|
+
"keys" => "keys", # CSVParser, TSVParser (old ValuesParser)
|
|
52
56
|
"time_key" => "time_key",
|
|
53
57
|
"time_format" => "time_format",
|
|
58
|
+
"localtim" => nil,
|
|
59
|
+
"utc" => nil,
|
|
54
60
|
"delimiter" => "delimiter",
|
|
61
|
+
"keep_time_key" => "keep_time_key",
|
|
62
|
+
"null_empty_string" => "null_empty_string",
|
|
63
|
+
"null_value_pattern" => "null_value_pattern",
|
|
55
64
|
"json_parser" => "json_parser", # JSONParser
|
|
56
65
|
"label_delimiter" => "label_delimiter", # LabeledTSVParser
|
|
57
66
|
"format_firstline" => "format_firstline", # MultilineParser
|
|
@@ -62,19 +71,29 @@ module Fluent
|
|
|
62
71
|
|
|
63
72
|
INJECT_PARAMS = {
|
|
64
73
|
"include_time_key" => nil,
|
|
65
|
-
"time_key"
|
|
66
|
-
"time_format"
|
|
67
|
-
"timezone"
|
|
74
|
+
"time_key" => "time_key",
|
|
75
|
+
"time_format" => "time_format",
|
|
76
|
+
"timezone" => "timezone",
|
|
68
77
|
"include_tag_key" => nil,
|
|
69
78
|
"tag_key" => "tag_key",
|
|
70
79
|
"localtime" => nil,
|
|
71
80
|
"utc" => nil,
|
|
72
81
|
}
|
|
73
82
|
|
|
83
|
+
EXTRACT_PARAMS = {
|
|
84
|
+
"time_key" => "time_key",
|
|
85
|
+
"time_format" => "time_format",
|
|
86
|
+
"timezone" => "timezone",
|
|
87
|
+
"tag_key" => "tag_key",
|
|
88
|
+
"localtime" => nil,
|
|
89
|
+
"utc" => nil,
|
|
90
|
+
}
|
|
91
|
+
|
|
74
92
|
FORMATTER_PARAMS = {
|
|
75
93
|
"format" => "@type",
|
|
76
94
|
"delimiter" => "delimiter",
|
|
77
95
|
"force_quotes" => "force_quotes", # CsvFormatter
|
|
96
|
+
"keys" => "keys", # TSVFormatter
|
|
78
97
|
"fields" => "fields", # CsvFormatter
|
|
79
98
|
"json_parser" => "json_parser", # JSONFormatter
|
|
80
99
|
"label_delimiter" => "label_delimiter", # LabeledTSVFormatter
|
|
@@ -95,6 +114,8 @@ module Fluent
|
|
|
95
114
|
compat_parameters_buffer(conf, **kwargs)
|
|
96
115
|
when :inject
|
|
97
116
|
compat_parameters_inject(conf)
|
|
117
|
+
when :extract
|
|
118
|
+
compat_parameters_extract(conf)
|
|
98
119
|
when :parser
|
|
99
120
|
compat_parameters_parser(conf)
|
|
100
121
|
when :formatter
|
|
@@ -167,6 +188,7 @@ module Fluent
|
|
|
167
188
|
hash['time_type'] ||= 'string'
|
|
168
189
|
end
|
|
169
190
|
if conf.has_key?('time_as_epoch') && Fluent::Config.bool_value(conf['time_as_epoch'])
|
|
191
|
+
hash['time_key'] ||= 'time'
|
|
170
192
|
hash['time_type'] = 'unixtime'
|
|
171
193
|
end
|
|
172
194
|
if conf.has_key?('localtime') || conf.has_key?('utc')
|
|
@@ -193,6 +215,40 @@ module Fluent
|
|
|
193
215
|
conf
|
|
194
216
|
end
|
|
195
217
|
|
|
218
|
+
def compat_parameters_extract(conf)
|
|
219
|
+
return unless conf.elements('extract').empty?
|
|
220
|
+
return if EXTRACT_PARAMS.keys.all?{|k| !conf.has_key?(k) } && !conf.has_key?('format')
|
|
221
|
+
|
|
222
|
+
# TODO: warn obsolete parameters if these are deprecated
|
|
223
|
+
hash = compat_parameters_copy_to_subsection_attributes(conf, EXTRACT_PARAMS)
|
|
224
|
+
|
|
225
|
+
if conf.has_key?('time_as_epoch') && Fluent::Config.bool_value(conf['time_as_epoch'])
|
|
226
|
+
hash['time_key'] ||= 'time'
|
|
227
|
+
hash['time_type'] = 'unixtime'
|
|
228
|
+
elsif conf.has_key?('format') && conf["format"].start_with?("/") && conf["format"].end_with?("/") # old-style regexp parser
|
|
229
|
+
hash['time_key'] ||= 'time'
|
|
230
|
+
hash['time_type'] ||= 'string'
|
|
231
|
+
end
|
|
232
|
+
if conf.has_key?('localtime') || conf.has_key?('utc')
|
|
233
|
+
if conf.has_key?('localtime') && conf.has_key?('utc')
|
|
234
|
+
raise Fluent::ConfigError, "both of utc and localtime are specified, use only one of them"
|
|
235
|
+
elsif conf.has_key?('localtime')
|
|
236
|
+
hash['localtime'] = Fluent::Config.bool_value(conf['localtime'])
|
|
237
|
+
elsif conf.has_key?('utc')
|
|
238
|
+
hash['localtime'] = !(Fluent::Config.bool_value(conf['utc']))
|
|
239
|
+
# Specifying "localtime false" means using UTC in TimeFormatter
|
|
240
|
+
# And specifying "utc" is different from specifying "timezone +0000"(it's not always UTC).
|
|
241
|
+
# There are difference between "Z" and "+0000" in timezone formatting.
|
|
242
|
+
# TODO: add kwargs to TimeFormatter to specify "using localtime", "using UTC" or "using specified timezone" in more explicit way
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
e = Fluent::Config::Element.new('extract', '', hash, [])
|
|
247
|
+
conf.elements << e
|
|
248
|
+
|
|
249
|
+
conf
|
|
250
|
+
end
|
|
251
|
+
|
|
196
252
|
def compat_parameters_parser(conf)
|
|
197
253
|
return unless conf.elements('parse').empty?
|
|
198
254
|
return if PARSER_PARAMS.keys.all?{|k| !conf.has_key?(k) }
|
|
@@ -200,6 +256,39 @@ module Fluent
|
|
|
200
256
|
# TODO: warn obsolete parameters if these are deprecated
|
|
201
257
|
hash = compat_parameters_copy_to_subsection_attributes(conf, PARSER_PARAMS)
|
|
202
258
|
|
|
259
|
+
if conf["format"]
|
|
260
|
+
if conf["format"].start_with?("/") && conf["format"].end_with?("/")
|
|
261
|
+
hash["@type"] = "regexp"
|
|
262
|
+
hash["expression"] = conf["format"][1..-2]
|
|
263
|
+
else
|
|
264
|
+
hash["@type"] = conf["format"]
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
if conf["types"]
|
|
269
|
+
delimiter = conf["types_delimiter"] || ','
|
|
270
|
+
label_delimiter = conf["types_label_delimiter"] || ':'
|
|
271
|
+
types = {}
|
|
272
|
+
conf['types'].split(delimiter).each do |pair|
|
|
273
|
+
key, value = pair.split(label_delimiter, 2)
|
|
274
|
+
types[key] = value
|
|
275
|
+
end
|
|
276
|
+
hash["types"] = JSON.dump(types)
|
|
277
|
+
end
|
|
278
|
+
if conf.has_key?('localtime') || conf.has_key?('utc')
|
|
279
|
+
if conf.has_key?('localtime') && conf.has_key?('utc')
|
|
280
|
+
raise Fluent::ConfigError, "both of utc and localtime are specified, use only one of them"
|
|
281
|
+
elsif conf.has_key?('localtime')
|
|
282
|
+
hash['localtime'] = Fluent::Config.bool_value(conf['localtime'])
|
|
283
|
+
elsif conf.has_key?('utc')
|
|
284
|
+
hash['localtime'] = !(Fluent::Config.bool_value(conf['utc']))
|
|
285
|
+
# Specifying "localtime false" means using UTC in TimeFormatter
|
|
286
|
+
# And specifying "utc" is different from specifying "timezone +0000"(it's not always UTC).
|
|
287
|
+
# There are difference between "Z" and "+0000" in timezone formatting.
|
|
288
|
+
# TODO: add kwargs to TimeFormatter to specify "using localtime", "using UTC" or "using specified timezone" in more explicit way
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
203
292
|
e = Fluent::Config::Element.new('parse', '', hash, [])
|
|
204
293
|
conf.elements << e
|
|
205
294
|
|
|
@@ -26,10 +26,14 @@ module Fluent
|
|
|
26
26
|
|
|
27
27
|
def router
|
|
28
28
|
@_event_emitter_used_actually = true
|
|
29
|
+
if @_event_emitter_lazy_init
|
|
30
|
+
@router = @primary_instance.router
|
|
31
|
+
end
|
|
29
32
|
@router
|
|
30
33
|
end
|
|
31
34
|
|
|
32
35
|
def router=(r)
|
|
36
|
+
# not recommended now...
|
|
33
37
|
@router = r
|
|
34
38
|
end
|
|
35
39
|
|
|
@@ -44,14 +48,23 @@ module Fluent
|
|
|
44
48
|
def event_emitter_router(label_name)
|
|
45
49
|
if label_name
|
|
46
50
|
Engine.root_agent.find_label(label_name).event_router
|
|
51
|
+
elsif self.respond_to?(:as_secondary) && self.as_secondary
|
|
52
|
+
if @primary_instance.has_router?
|
|
53
|
+
@_event_emitter_lazy_init = true
|
|
54
|
+
nil # primary plugin's event router is not initialized yet, here.
|
|
55
|
+
else
|
|
56
|
+
@primary_instance.context_router
|
|
57
|
+
end
|
|
47
58
|
else
|
|
48
|
-
Engine.root_agent.event_router
|
|
59
|
+
# `Engine.root_agent.event_router` is for testing
|
|
60
|
+
self.context_router || Engine.root_agent.event_router
|
|
49
61
|
end
|
|
50
62
|
end
|
|
51
63
|
|
|
52
64
|
def initialize
|
|
53
65
|
super
|
|
54
66
|
@_event_emitter_used_actually = false
|
|
67
|
+
@_event_emitter_lazy_init = false
|
|
55
68
|
@router = nil
|
|
56
69
|
end
|
|
57
70
|
|
|
@@ -25,7 +25,8 @@ module Fluent
|
|
|
25
25
|
return nil unless @_extract_enabled
|
|
26
26
|
|
|
27
27
|
if @_extract_tag_key && record.has_key?(@_extract_tag_key)
|
|
28
|
-
|
|
28
|
+
v = @_extract_keep_tag_key ? record[@_extract_tag_key] : record.delete(@_extract_tag_key)
|
|
29
|
+
return v.to_s
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
nil
|
|
@@ -35,7 +36,8 @@ module Fluent
|
|
|
35
36
|
return nil unless @_extract_enabled
|
|
36
37
|
|
|
37
38
|
if @_extract_time_key && record.has_key?(@_extract_time_key)
|
|
38
|
-
|
|
39
|
+
v = @_extract_keep_time_key ? record[@_extract_time_key] : record.delete(@_extract_time_key)
|
|
40
|
+
return @_extract_time_parser.call(v)
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
nil
|
|
@@ -45,7 +47,9 @@ module Fluent
|
|
|
45
47
|
include Fluent::Configurable
|
|
46
48
|
config_section :extract, required: false, multi: false, param_name: :extract_config do
|
|
47
49
|
config_param :tag_key, :string, default: nil
|
|
50
|
+
config_param :keep_tag_key, :bool, default: false
|
|
48
51
|
config_param :time_key, :string, default: nil
|
|
52
|
+
config_param :keep_time_key, :bool, default: false
|
|
49
53
|
|
|
50
54
|
# To avoid defining :time_type twice
|
|
51
55
|
config_param :time_type, :enum, list: [:float, :unixtime, :string], default: :float
|
|
@@ -64,7 +68,9 @@ module Fluent
|
|
|
64
68
|
super
|
|
65
69
|
@_extract_enabled = false
|
|
66
70
|
@_extract_tag_key = nil
|
|
71
|
+
@_extract_keep_tag_key = nil
|
|
67
72
|
@_extract_time_key = nil
|
|
73
|
+
@_extract_keep_time_key = nil
|
|
68
74
|
@_extract_time_parser = nil
|
|
69
75
|
end
|
|
70
76
|
|
|
@@ -73,15 +79,21 @@ module Fluent
|
|
|
73
79
|
|
|
74
80
|
if @extract_config
|
|
75
81
|
@_extract_tag_key = @extract_config.tag_key
|
|
82
|
+
@_extract_keep_tag_key = @extract_config.keep_tag_key
|
|
76
83
|
@_extract_time_key = @extract_config.time_key
|
|
77
84
|
if @_extract_time_key
|
|
85
|
+
@_extract_keep_time_key = @extract_config.keep_time_key
|
|
78
86
|
@_extract_time_parser = case @extract_config.time_type
|
|
79
|
-
when :float then
|
|
80
|
-
when :unixtime then
|
|
87
|
+
when :float then Fluent::NumericTimeParser.new(:float)
|
|
88
|
+
when :unixtime then Fluent::NumericTimeParser.new(:unixtime)
|
|
81
89
|
else
|
|
82
90
|
localtime = @extract_config.localtime && !@extract_config.utc
|
|
83
91
|
Fluent::TimeParser.new(@extract_config.time_format, localtime, @extract_config.timezone)
|
|
84
92
|
end
|
|
93
|
+
else
|
|
94
|
+
if @extract_config.time_format
|
|
95
|
+
log.warn "'time_format' specified without 'time_key', will be ignored"
|
|
96
|
+
end
|
|
85
97
|
end
|
|
86
98
|
|
|
87
99
|
@_extract_enabled = @_extract_tag_key || @_extract_time_key
|
|
@@ -24,7 +24,7 @@ module Fluent
|
|
|
24
24
|
module Formatter
|
|
25
25
|
def formatter_create(usage: '', type: nil, conf: nil, default_type: nil)
|
|
26
26
|
formatter = @_formatters[usage]
|
|
27
|
-
return formatter if formatter
|
|
27
|
+
return formatter if formatter && !type && !conf
|
|
28
28
|
|
|
29
29
|
type = if type
|
|
30
30
|
type
|
|
@@ -61,9 +61,9 @@ module Fluent
|
|
|
61
61
|
module FormatterParams
|
|
62
62
|
include Fluent::Configurable
|
|
63
63
|
# minimum section definition to instantiate formatter plugin instances
|
|
64
|
-
config_section :format, required: false, multi: true, param_name: :formatter_configs do
|
|
64
|
+
config_section :format, required: false, multi: true, init: true, param_name: :formatter_configs do
|
|
65
65
|
config_argument :usage, :string, default: ''
|
|
66
|
-
config_param :@type, :string
|
|
66
|
+
config_param :@type, :string # config_set_default required for :@type
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
|
@@ -82,15 +82,13 @@ module Fluent
|
|
|
82
82
|
def configure(conf)
|
|
83
83
|
super
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
@
|
|
87
|
-
|
|
88
|
-
raise Fluent::ConfigError, "duplicated formatter configured: #{section.usage}"
|
|
89
|
-
end
|
|
90
|
-
formatter = Plugin.new_formatter(section[:@type], parent: self)
|
|
91
|
-
formatter.configure(section.corresponding_config_element)
|
|
92
|
-
@_formatters[section.usage] = formatter
|
|
85
|
+
@formatter_configs.each do |section|
|
|
86
|
+
if @_formatters[section.usage]
|
|
87
|
+
raise Fluent::ConfigError, "duplicated formatter configured: #{section.usage}"
|
|
93
88
|
end
|
|
89
|
+
formatter = Plugin.new_formatter(section[:@type], parent: self)
|
|
90
|
+
formatter.configure(section.corresponding_config_element)
|
|
91
|
+
@_formatters[section.usage] = formatter
|
|
94
92
|
end
|
|
95
93
|
end
|
|
96
94
|
|
|
@@ -113,6 +113,10 @@ module Fluent
|
|
|
113
113
|
localtime = @inject_config.localtime && !@inject_config.utc
|
|
114
114
|
Fluent::TimeFormatter.new(@inject_config.time_format, localtime, @inject_config.timezone)
|
|
115
115
|
end
|
|
116
|
+
else
|
|
117
|
+
if @inject_config.time_format
|
|
118
|
+
log.warn "'time_format' specified without 'time_key', will be ignored"
|
|
119
|
+
end
|
|
116
120
|
end
|
|
117
121
|
|
|
118
122
|
@_inject_enabled = @_inject_hostname_key || @_inject_tag_key || @_inject_time_key
|
|
@@ -24,7 +24,7 @@ module Fluent
|
|
|
24
24
|
module Parser
|
|
25
25
|
def parser_create(usage: '', type: nil, conf: nil, default_type: nil)
|
|
26
26
|
parser = @_parsers[usage]
|
|
27
|
-
return parser if parser
|
|
27
|
+
return parser if parser && !type && !conf
|
|
28
28
|
|
|
29
29
|
type = if type
|
|
30
30
|
type
|
|
@@ -61,9 +61,9 @@ module Fluent
|
|
|
61
61
|
module ParserParams
|
|
62
62
|
include Fluent::Configurable
|
|
63
63
|
# minimum section definition to instantiate parser plugin instances
|
|
64
|
-
config_section :parse, required: false, multi: true, param_name: :parser_configs do
|
|
64
|
+
config_section :parse, required: false, multi: true, init: true, param_name: :parser_configs do
|
|
65
65
|
config_argument :usage, :string, default: ''
|
|
66
|
-
config_param :@type, :string
|
|
66
|
+
config_param :@type, :string # config_set_default required for :@type
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
data/lib/fluent/root_agent.rb
CHANGED
|
@@ -233,7 +233,7 @@ module Fluent
|
|
|
233
233
|
# <source> emits events to the top-level event router (RootAgent#event_router).
|
|
234
234
|
# Input#configure overwrites event_router to a label's event_router if it has `@label` parameter.
|
|
235
235
|
# See also 'fluentd/plugin/input.rb'
|
|
236
|
-
input.
|
|
236
|
+
input.context_router = @event_router
|
|
237
237
|
input.configure(conf)
|
|
238
238
|
@inputs << input
|
|
239
239
|
|
|
@@ -23,9 +23,13 @@ require 'timeout'
|
|
|
23
23
|
module Fluent
|
|
24
24
|
module Test
|
|
25
25
|
module Driver
|
|
26
|
+
class TestTimedOut < RuntimeError; end
|
|
27
|
+
|
|
26
28
|
class Base
|
|
27
29
|
attr_reader :instance, :logs
|
|
28
30
|
|
|
31
|
+
DEFAULT_TIMEOUT = 300
|
|
32
|
+
|
|
29
33
|
def initialize(klass, opts: {}, &block)
|
|
30
34
|
if klass.is_a?(Class)
|
|
31
35
|
if block
|
|
@@ -44,6 +48,8 @@ module Fluent
|
|
|
44
48
|
|
|
45
49
|
@logs = []
|
|
46
50
|
|
|
51
|
+
@test_clock_id = Process::CLOCK_MONOTONIC_RAW rescue Process::CLOCK_MONOTONIC
|
|
52
|
+
|
|
47
53
|
@run_post_conditions = []
|
|
48
54
|
@run_breaking_conditions = []
|
|
49
55
|
@broken = false
|
|
@@ -70,15 +76,25 @@ module Fluent
|
|
|
70
76
|
def run(timeout: nil, start: true, shutdown: true, &block)
|
|
71
77
|
instance_start if start
|
|
72
78
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
timeout ||= DEFAULT_TIMEOUT
|
|
80
|
+
stop_at = Process.clock_gettime(@test_clock_id) + timeout
|
|
81
|
+
@run_breaking_conditions << ->(){ Process.clock_gettime(@test_clock_id) >= stop_at }
|
|
82
|
+
|
|
83
|
+
if !block_given? && @run_post_conditions.empty? && @run_breaking_conditions.empty?
|
|
84
|
+
raise ArgumentError, "no stop conditions nor block specified"
|
|
78
85
|
end
|
|
79
86
|
|
|
87
|
+
sleep_with_watching_threads = ->(){
|
|
88
|
+
if @instance.respond_to?(:_threads)
|
|
89
|
+
@instance._threads.values.each{|t| t.join(0) }
|
|
90
|
+
end
|
|
91
|
+
sleep 0.1
|
|
92
|
+
}
|
|
93
|
+
|
|
80
94
|
begin
|
|
81
|
-
run_actual(timeout: timeout, &block)
|
|
95
|
+
retval = run_actual(timeout: timeout, &block)
|
|
96
|
+
sleep_with_watching_threads.call until stop?
|
|
97
|
+
retval
|
|
82
98
|
ensure
|
|
83
99
|
instance_shutdown if shutdown
|
|
84
100
|
end
|
|
@@ -87,18 +103,33 @@ module Fluent
|
|
|
87
103
|
def instance_start
|
|
88
104
|
unless @instance.started?
|
|
89
105
|
@instance.start
|
|
90
|
-
instance_hook_after_started
|
|
91
106
|
end
|
|
92
107
|
unless @instance.after_started?
|
|
93
108
|
@instance.after_start
|
|
94
109
|
end
|
|
110
|
+
|
|
111
|
+
if @instance.respond_to?(:thread_wait_until_start)
|
|
112
|
+
@instance.thread_wait_until_start
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
if @instance.respond_to?(:event_loop_wait_until_start)
|
|
116
|
+
@instance.event_loop_wait_until_start
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
instance_hook_after_started
|
|
95
120
|
end
|
|
96
121
|
|
|
97
122
|
def instance_hook_after_started
|
|
98
123
|
# insert hooks for tests available after instance.start
|
|
99
124
|
end
|
|
100
125
|
|
|
126
|
+
def instance_hook_before_stopped
|
|
127
|
+
# same with above
|
|
128
|
+
end
|
|
129
|
+
|
|
101
130
|
def instance_shutdown
|
|
131
|
+
instance_hook_before_stopped
|
|
132
|
+
|
|
102
133
|
@instance.stop unless @instance.stopped?
|
|
103
134
|
@instance.before_shutdown unless @instance.before_shutdown?
|
|
104
135
|
@instance.shutdown unless @instance.shutdown?
|
|
@@ -117,50 +148,33 @@ module Fluent
|
|
|
117
148
|
@instance.terminate unless @instance.terminated?
|
|
118
149
|
end
|
|
119
150
|
|
|
120
|
-
def run_actual(timeout:
|
|
151
|
+
def run_actual(timeout: DEFAULT_TIMEOUT, &block)
|
|
121
152
|
if @instance.respond_to?(:_threads)
|
|
122
|
-
until @instance._threads.values.all?(&:alive?)
|
|
123
|
-
sleep 0.01
|
|
124
|
-
end
|
|
153
|
+
sleep 0.1 until @instance._threads.values.all?(&:alive?)
|
|
125
154
|
end
|
|
126
155
|
|
|
127
156
|
if @instance.respond_to?(:event_loop_running?)
|
|
128
|
-
until @instance.event_loop_running?
|
|
129
|
-
sleep 0.01
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
if timeout
|
|
134
|
-
stop_at = Time.now + timeout
|
|
135
|
-
@run_breaking_conditions << ->(){ Time.now >= stop_at }
|
|
157
|
+
sleep 0.1 until @instance.event_loop_running?
|
|
136
158
|
end
|
|
137
159
|
|
|
138
|
-
if
|
|
139
|
-
|
|
160
|
+
if @instance.respond_to?(:_child_process_processes)
|
|
161
|
+
sleep 0.1 until @instance._child_process_processes.values.all?{|pinfo| pinfo.alive }
|
|
140
162
|
end
|
|
141
163
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
if timeout
|
|
149
|
-
begin
|
|
150
|
-
Timeout.timeout(timeout * 1.1) do |sec|
|
|
151
|
-
proc.call
|
|
152
|
-
end
|
|
153
|
-
rescue Timeout::Error
|
|
154
|
-
@broken = true
|
|
164
|
+
return_value = nil
|
|
165
|
+
begin
|
|
166
|
+
Timeout.timeout(timeout * 1.1) do |sec|
|
|
167
|
+
return_value = block.call if block_given?
|
|
155
168
|
end
|
|
156
|
-
|
|
157
|
-
|
|
169
|
+
rescue Timeout::Error
|
|
170
|
+
raise TestTimedOut, "Test case timed out with hard limit."
|
|
158
171
|
end
|
|
172
|
+
return_value
|
|
159
173
|
end
|
|
160
174
|
|
|
161
175
|
def stop?
|
|
162
176
|
# Should stop running if post conditions are not registered.
|
|
163
|
-
return true unless @run_post_conditions
|
|
177
|
+
return true unless @run_post_conditions || @run_post_conditions.empty?
|
|
164
178
|
|
|
165
179
|
# Should stop running if all of the post conditions are true.
|
|
166
180
|
return true if @run_post_conditions.all? {|proc| proc.call }
|