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
|
@@ -166,6 +166,13 @@ module Fluent
|
|
|
166
166
|
varname = subproxy.variable_name
|
|
167
167
|
elements = (conf.respond_to?(:elements) ? conf.elements : []).select{ |e| e.name == subproxy.name.to_s || e.name == subproxy.alias.to_s }
|
|
168
168
|
if elements.empty? && subproxy.init?
|
|
169
|
+
if subproxy.argument && !subproxy.defaults.has_key?(subproxy.argument.first)
|
|
170
|
+
raise ArgumentError, "#{name}: init is specified, but default value of argument is missing"
|
|
171
|
+
end
|
|
172
|
+
missing_keys = subproxy.params.keys.select{|param_name| !subproxy.defaults.has_key?(param_name)}
|
|
173
|
+
if !missing_keys.empty?
|
|
174
|
+
raise ArgumentError, "#{name}: init is specified, but there're parameters without default values:#{missing_keys.join(',')}"
|
|
175
|
+
end
|
|
169
176
|
elements << Fluent::Config::Element.new(subproxy.name.to_s, '', {}, [])
|
|
170
177
|
end
|
|
171
178
|
|
data/lib/fluent/configurable.rb
CHANGED
|
@@ -71,9 +71,7 @@ module Fluent
|
|
|
71
71
|
root.instance_eval{ @params.keys }.each do |param_name|
|
|
72
72
|
next if param_name.to_s.start_with?('@')
|
|
73
73
|
varname = "@#{param_name}".to_sym
|
|
74
|
-
|
|
75
|
-
instance_variable_set(varname, root[param_name])
|
|
76
|
-
end
|
|
74
|
+
instance_variable_set(varname, root[param_name])
|
|
77
75
|
end
|
|
78
76
|
|
|
79
77
|
self
|
data/lib/fluent/log.rb
CHANGED
|
@@ -446,7 +446,7 @@ module Fluent
|
|
|
446
446
|
|
|
447
447
|
# This class delegetes some methods which are used in `Fluent::Logger` to a instance variable(`dev`) in `Logger::LogDevice` class
|
|
448
448
|
# https://github.com/ruby/ruby/blob/7b2d47132ff8ee950b0f978ab772dee868d9f1b0/lib/logger.rb#L661
|
|
449
|
-
class LogDeviceIO < Logger::LogDevice
|
|
449
|
+
class LogDeviceIO < ::Logger::LogDevice
|
|
450
450
|
def flush
|
|
451
451
|
if @dev.respond_to?(:flush)
|
|
452
452
|
@dev.flush
|
data/lib/fluent/plugin/base.rb
CHANGED
|
@@ -31,6 +31,7 @@ module Fluent
|
|
|
31
31
|
def initialize
|
|
32
32
|
super
|
|
33
33
|
@_state = State.new(false, false, false, false, false, false, false, false, false)
|
|
34
|
+
@_context_router = nil
|
|
34
35
|
@under_plugin_development = false
|
|
35
36
|
end
|
|
36
37
|
|
|
@@ -45,6 +46,22 @@ module Fluent
|
|
|
45
46
|
self
|
|
46
47
|
end
|
|
47
48
|
|
|
49
|
+
def string_safe_encoding(str)
|
|
50
|
+
unless str.valid_encoding?
|
|
51
|
+
log.info "invalid byte sequence is replaced in `#{str}`" if self.respond_to?(:log)
|
|
52
|
+
str = str.scrub('?')
|
|
53
|
+
end
|
|
54
|
+
yield str
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def context_router=(router)
|
|
58
|
+
@_context_router = router
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def context_router
|
|
62
|
+
@_context_router
|
|
63
|
+
end
|
|
64
|
+
|
|
48
65
|
def start
|
|
49
66
|
@_state.start = true
|
|
50
67
|
self
|
|
@@ -0,0 +1,108 @@
|
|
|
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/time'
|
|
18
|
+
require 'fluent/config/error'
|
|
19
|
+
require 'fluent/plugin/filter'
|
|
20
|
+
require 'fluent/plugin_helper/parser'
|
|
21
|
+
require 'fluent/plugin_helper/compat_parameters'
|
|
22
|
+
|
|
23
|
+
module Fluent::Plugin
|
|
24
|
+
class ParserFilter < Filter
|
|
25
|
+
Fluent::Plugin.register_filter('parser', self)
|
|
26
|
+
|
|
27
|
+
helpers :parser, :compat_parameters
|
|
28
|
+
|
|
29
|
+
config_param :key_name, :string
|
|
30
|
+
config_param :reserve_data, :bool, default: false
|
|
31
|
+
config_param :reserve_time, :bool, default: false
|
|
32
|
+
config_param :inject_key_prefix, :string, default: nil
|
|
33
|
+
config_param :replace_invalid_sequence, :bool, default: false
|
|
34
|
+
config_param :hash_value_field, :string, default: nil
|
|
35
|
+
|
|
36
|
+
attr_reader :parser
|
|
37
|
+
|
|
38
|
+
def configure(conf)
|
|
39
|
+
compat_parameters_convert(conf, :parser)
|
|
40
|
+
|
|
41
|
+
super
|
|
42
|
+
|
|
43
|
+
@parser = parser_create
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
FAILED_RESULT = [nil, nil].freeze # reduce allocation cost
|
|
47
|
+
REPLACE_CHAR = '?'.freeze
|
|
48
|
+
|
|
49
|
+
def filter_with_time(tag, time, record)
|
|
50
|
+
raw_value = record[@key_name]
|
|
51
|
+
if raw_value.nil?
|
|
52
|
+
router.emit_error_event(tag, time, record, ArgumentError.new("#{@key_name} does not exist"))
|
|
53
|
+
if @reserve_data
|
|
54
|
+
return time, handle_parsed(tag, record, time, {})
|
|
55
|
+
else
|
|
56
|
+
return FAILED_RESULT
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
begin
|
|
60
|
+
@parser.parse(raw_value) do |t, values|
|
|
61
|
+
if values
|
|
62
|
+
t = if @reserve_time
|
|
63
|
+
time
|
|
64
|
+
else
|
|
65
|
+
t.nil? ? time : t
|
|
66
|
+
end
|
|
67
|
+
r = handle_parsed(tag, record, t, values)
|
|
68
|
+
return t, r
|
|
69
|
+
else
|
|
70
|
+
router.emit_error_event(tag, time, record, Fluent::Plugin::Parser::ParserError.new("pattern not match with data '#{raw_value}'"))
|
|
71
|
+
if @reserve_data
|
|
72
|
+
t = time
|
|
73
|
+
r = handle_parsed(tag, record, time, {})
|
|
74
|
+
return t, r
|
|
75
|
+
else
|
|
76
|
+
return FAILED_RESULT
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
rescue Fluent::Plugin::Parser::ParserError => e
|
|
81
|
+
router.emit_error_event(tag, time, record, e)
|
|
82
|
+
return FAILED_RESULT
|
|
83
|
+
rescue ArgumentError => e
|
|
84
|
+
raise unless @replace_invalid_sequence
|
|
85
|
+
raise unless e.message.index("invalid byte sequence in") == 0
|
|
86
|
+
|
|
87
|
+
raw_value = raw_value.scrub(REPLACE_CHAR)
|
|
88
|
+
retry
|
|
89
|
+
rescue => e
|
|
90
|
+
router.emit_error_event(tag, time, record, Fluent::Plugin::Parser::ParserError.new("parse failed #{e.message}"))
|
|
91
|
+
return FAILED_RESULT
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
def handle_parsed(tag, record, t, values)
|
|
98
|
+
if values && @inject_key_prefix
|
|
99
|
+
values = Hash[values.map { |k, v| [@inject_key_prefix + k, v] }]
|
|
100
|
+
end
|
|
101
|
+
r = @hash_value_field ? {@hash_value_field => values} : values
|
|
102
|
+
if @reserve_data
|
|
103
|
+
r = r ? record.merge(r) : record
|
|
104
|
+
end
|
|
105
|
+
r
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -38,7 +38,7 @@ module Fluent::Plugin
|
|
|
38
38
|
desc 'When set to true, the full Ruby syntax is enabled in the ${...} expression.'
|
|
39
39
|
config_param :enable_ruby, :bool, default: false
|
|
40
40
|
desc 'Use original value type.'
|
|
41
|
-
config_param :auto_typecast, :bool, default:
|
|
41
|
+
config_param :auto_typecast, :bool, default: true
|
|
42
42
|
|
|
43
43
|
def configure(conf)
|
|
44
44
|
super
|
|
@@ -95,10 +95,9 @@ module Fluent::Plugin
|
|
|
95
95
|
last_record = nil
|
|
96
96
|
es.each do |time, record|
|
|
97
97
|
last_record = record # for debug log
|
|
98
|
-
placeholder_values.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
})
|
|
98
|
+
placeholder_values['time'] = @placeholder_expander.time_value(time)
|
|
99
|
+
placeholder_values['record'] = record
|
|
100
|
+
|
|
102
101
|
new_record = reform(record, placeholder_values)
|
|
103
102
|
if @renew_time_key && new_record.has_key?(@renew_time_key)
|
|
104
103
|
time = Fluent::EventTime.from_time(Time.at(new_record[@renew_time_key].to_f))
|
|
@@ -316,8 +315,6 @@ module Fluent::Plugin
|
|
|
316
315
|
|
|
317
316
|
class CleanroomExpander
|
|
318
317
|
def expand(__str_to_eval__, tag, time, record, tag_parts, tag_prefix, tag_suffix, hostname)
|
|
319
|
-
tags = tag_parts # for old version compatibility
|
|
320
|
-
_ = tags # to suppress "unused variable" warning for tags
|
|
321
318
|
Thread.current[:record_transformer_record] = record # for old version compatibility
|
|
322
319
|
instance_eval(__str_to_eval__)
|
|
323
320
|
end
|
|
@@ -34,7 +34,7 @@ module Fluent::Plugin
|
|
|
34
34
|
def configure(conf)
|
|
35
35
|
compat_parameters_convert(conf, :inject, :formatter)
|
|
36
36
|
super
|
|
37
|
-
@formatter = formatter_create
|
|
37
|
+
@formatter = formatter_create
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def filter_stream(tag, es)
|
|
@@ -26,6 +26,11 @@ module Fluent
|
|
|
26
26
|
|
|
27
27
|
configured_in :format
|
|
28
28
|
|
|
29
|
+
PARSER_TYPES = [:text_per_line, :text, :binary]
|
|
30
|
+
def formatter_type
|
|
31
|
+
:text_per_line
|
|
32
|
+
end
|
|
33
|
+
|
|
29
34
|
def format(tag, time, record)
|
|
30
35
|
raise NotImplementedError, "Implement this method in child class"
|
|
31
36
|
end
|
|
@@ -21,6 +21,8 @@ module Fluent
|
|
|
21
21
|
class StdoutFormatter < Formatter
|
|
22
22
|
Plugin.register_formatter('stdout', self)
|
|
23
23
|
|
|
24
|
+
TIME_FORMAT = '%Y-%m-%d %H:%M:%S.%9N %z'
|
|
25
|
+
|
|
24
26
|
config_param :output_type, :string, default: 'json'
|
|
25
27
|
|
|
26
28
|
def configure(conf)
|
|
@@ -36,8 +38,7 @@ module Fluent
|
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
def format(tag, time, record)
|
|
39
|
-
|
|
40
|
-
"#{header}#{@sub_formatter.format(tag, time, record)}"
|
|
41
|
+
"#{Time.at(time).localtime.strftime(TIME_FORMAT)} #{tag}: #{@sub_formatter.format(tag, time, record).chomp}\n"
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
def stop
|
|
@@ -0,0 +1,34 @@
|
|
|
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/plugin/formatter'
|
|
18
|
+
|
|
19
|
+
module Fluent
|
|
20
|
+
module Plugin
|
|
21
|
+
class TSVFormatter < Formatter
|
|
22
|
+
Plugin.register_formatter('tsv', self)
|
|
23
|
+
|
|
24
|
+
desc 'Field names included in each lines'
|
|
25
|
+
config_param :keys, :array, value_type: :string
|
|
26
|
+
desc 'The delimiter character (or string) of TSV values'
|
|
27
|
+
config_param :delimiter, :string, default: "\t"
|
|
28
|
+
|
|
29
|
+
def format(tag, time, record)
|
|
30
|
+
@keys.map{|k| record[k].to_s }.join(@delimiter)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -14,136 +14,91 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
#
|
|
16
16
|
|
|
17
|
-
require 'strptime'
|
|
18
|
-
require 'yajl'
|
|
19
|
-
|
|
20
17
|
require 'fluent/plugin/input'
|
|
21
|
-
require '
|
|
22
|
-
require 'fluent/timezone'
|
|
23
|
-
require 'fluent/config/error'
|
|
18
|
+
require 'yajl'
|
|
24
19
|
|
|
25
20
|
module Fluent::Plugin
|
|
26
21
|
class ExecInput < Fluent::Plugin::Input
|
|
27
22
|
Fluent::Plugin.register_input('exec', self)
|
|
28
23
|
|
|
29
|
-
helpers :child_process
|
|
30
|
-
|
|
31
|
-
def initialize
|
|
32
|
-
super
|
|
33
|
-
require 'fluent/plugin/exec_util'
|
|
34
|
-
end
|
|
24
|
+
helpers :compat_parameters, :extract, :parser, :child_process
|
|
35
25
|
|
|
36
26
|
desc 'The command (program) to execute.'
|
|
37
27
|
config_param :command, :string
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
28
|
+
|
|
29
|
+
config_section :parse do
|
|
30
|
+
config_set_default :@type, 'tsv'
|
|
31
|
+
config_set_default :time_type, :float
|
|
32
|
+
config_set_default :time_key, nil
|
|
33
|
+
config_set_default :estimate_current_event, false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
config_section :extract do
|
|
37
|
+
config_set_default :time_type, :float
|
|
43
38
|
end
|
|
39
|
+
|
|
44
40
|
desc 'Tag of the output events.'
|
|
45
41
|
config_param :tag, :string, default: nil
|
|
46
|
-
desc 'The key to use as the event tag instead of the value in the event record. '
|
|
47
|
-
config_param :tag_key, :string, default: nil
|
|
48
|
-
desc 'The key to use as the event time instead of the value in the event record.'
|
|
49
|
-
config_param :time_key, :string, default: nil
|
|
50
|
-
desc 'The format of the event time used for the time_key parameter.'
|
|
51
|
-
config_param :time_format, :string, default: nil
|
|
52
42
|
desc 'The interval time between periodic program runs.'
|
|
53
43
|
config_param :run_interval, :time, default: nil
|
|
44
|
+
desc 'The default block size to read if parser requires partial read.'
|
|
45
|
+
config_param :read_block_size, :size, default: 10240 # 10k
|
|
54
46
|
|
|
55
|
-
|
|
56
|
-
super
|
|
57
|
-
|
|
58
|
-
if conf['localtime']
|
|
59
|
-
@localtime = true
|
|
60
|
-
elsif conf['utc']
|
|
61
|
-
@localtime = false
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
if conf['timezone']
|
|
65
|
-
@timezone = conf['timezone']
|
|
66
|
-
Fluent::Timezone.validate!(@timezone)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
if !@tag && !@tag_key
|
|
70
|
-
raise Fleunt::ConfigError, "'tag' or 'tag_key' option is required on exec input"
|
|
71
|
-
end
|
|
47
|
+
attr_reader :parser
|
|
72
48
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
rescue
|
|
81
|
-
Proc.new {|str| Fluent::EventTime.from_time(Time.strptime(str, f)) }
|
|
82
|
-
end
|
|
83
|
-
else
|
|
84
|
-
@time_parse_proc = Proc.new {|str| Fluent::EventTime.from_time(Time.at(str.to_f)) }
|
|
49
|
+
def configure(conf)
|
|
50
|
+
compat_parameters_convert(conf, :extract, :parser)
|
|
51
|
+
['parse', 'extract'].each do |subsection_name|
|
|
52
|
+
if subsection = conf.elements(subsection_name).first
|
|
53
|
+
if subsection.has_key?('time_format')
|
|
54
|
+
subsection['time_type'] ||= 'string'
|
|
55
|
+
end
|
|
85
56
|
end
|
|
86
57
|
end
|
|
87
58
|
|
|
88
|
-
|
|
89
|
-
end
|
|
59
|
+
super
|
|
90
60
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
when 'tsv'
|
|
94
|
-
if @keys.empty?
|
|
95
|
-
raise Fluent::ConfigError, "keys option is required on exec input for tsv format"
|
|
96
|
-
end
|
|
97
|
-
Fluent::ExecUtil::TSVParser.new(@keys, method(:on_message))
|
|
98
|
-
when 'json'
|
|
99
|
-
Fluent::ExecUtil::JSONParser.new(method(:on_message))
|
|
100
|
-
when 'msgpack'
|
|
101
|
-
Fluent::ExecUtil::MessagePackParser.new(method(:on_message))
|
|
102
|
-
else
|
|
103
|
-
Fluent::ExecUtil::TextParserWrapperParser.new(conf, method(:on_message))
|
|
61
|
+
if !@tag && (!@extract_config || !@extract_config.tag_key)
|
|
62
|
+
raise Fluent::ConfigError, "'tag' or 'tag_key' option is required on exec input"
|
|
104
63
|
end
|
|
64
|
+
@parser = parser_create
|
|
105
65
|
end
|
|
106
66
|
|
|
107
67
|
def start
|
|
108
68
|
super
|
|
109
69
|
|
|
110
70
|
if @run_interval
|
|
111
|
-
child_process_execute(:exec_input, @command, interval: @run_interval, mode: [:read])
|
|
112
|
-
run(io)
|
|
113
|
-
end
|
|
71
|
+
child_process_execute(:exec_input, @command, interval: @run_interval, mode: [:read], &method(:run))
|
|
114
72
|
else
|
|
115
|
-
child_process_execute(:exec_input, @command, immediate: true, mode: [:read])
|
|
116
|
-
run(io)
|
|
117
|
-
end
|
|
73
|
+
child_process_execute(:exec_input, @command, immediate: true, mode: [:read], &method(:run))
|
|
118
74
|
end
|
|
119
75
|
end
|
|
120
76
|
|
|
121
77
|
def run(io)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
if parsed_time
|
|
135
|
-
time = parsed_time
|
|
136
|
-
else
|
|
137
|
-
if val = record.delete(@time_key)
|
|
138
|
-
time = @time_parse_proc.call(val)
|
|
139
|
-
else
|
|
140
|
-
time = Fluent::EventTime.now
|
|
78
|
+
case
|
|
79
|
+
when @parser.implement?(:parse_io)
|
|
80
|
+
@parser.parse_io(io, &method(:on_record))
|
|
81
|
+
when @parser.implement?(:parse_partial_data)
|
|
82
|
+
until io.eof?
|
|
83
|
+
@parser.parse_partial_data(io.readpartial(@read_block_size), &method(:on_record))
|
|
84
|
+
end
|
|
85
|
+
when @parser.parser_type == :text_per_line
|
|
86
|
+
io.each_line do |line|
|
|
87
|
+
@parser.parse(line.chomp, &method(:on_record))
|
|
141
88
|
end
|
|
89
|
+
else
|
|
90
|
+
@parser.parse(io.read, &method(:on_record))
|
|
142
91
|
end
|
|
92
|
+
end
|
|
143
93
|
|
|
94
|
+
def on_record(time, record)
|
|
95
|
+
tag = extract_tag_from_record(record)
|
|
96
|
+
tag ||= @tag
|
|
97
|
+
time ||= extract_time_from_record(record) || Fluent::EventTime.now
|
|
144
98
|
router.emit(tag, time, record)
|
|
145
99
|
rescue => e
|
|
146
|
-
log.error "exec failed to emit",
|
|
100
|
+
log.error "exec failed to emit", tag: tag, record: Yajl.dump(record), error: e
|
|
101
|
+
router.emit_error_event(tag, time, record, e) if tag && time && record
|
|
147
102
|
end
|
|
148
103
|
end
|
|
149
104
|
end
|