fluentd 0.14.7-x64-mingw32 → 0.14.10-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fluentd might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +2 -0
- data/CONTRIBUTING.md +6 -1
- data/ChangeLog +95 -0
- data/Rakefile +21 -0
- data/appveyor.yml +1 -0
- data/code-of-conduct.md +3 -0
- data/example/out_exec_filter.conf +42 -0
- data/fluentd.gemspec +1 -1
- data/lib/fluent/agent.rb +2 -2
- data/lib/fluent/command/binlog_reader.rb +1 -1
- data/lib/fluent/command/cat.rb +15 -4
- data/lib/fluent/compat/output.rb +14 -9
- data/lib/fluent/compat/parser.rb +141 -11
- data/lib/fluent/config/configure_proxy.rb +2 -11
- data/lib/fluent/config/section.rb +8 -1
- data/lib/fluent/configurable.rb +1 -3
- data/lib/fluent/env.rb +1 -1
- 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 +14 -35
- 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 +66 -265
- data/lib/fluent/plugin/in_http.rb +68 -65
- data/lib/fluent/plugin/in_monitor_agent.rb +8 -4
- data/lib/fluent/plugin/in_syslog.rb +42 -58
- data/lib/fluent/plugin/in_tail.rb +29 -14
- data/lib/fluent/plugin/in_tcp.rb +54 -14
- data/lib/fluent/plugin/in_udp.rb +49 -13
- 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 +172 -81
- data/lib/fluent/plugin/out_forward.rb +229 -206
- data/lib/fluent/plugin/out_stdout.rb +6 -21
- data/lib/fluent/plugin/output.rb +90 -59
- 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 +10 -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/event_loop.rb +24 -6
- 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 +16 -1
- data/lib/fluent/plugin_helper/parser.rb +3 -3
- data/lib/fluent/plugin_helper/server.rb +494 -0
- data/lib/fluent/plugin_helper/socket.rb +101 -0
- data/lib/fluent/plugin_helper/socket_option.rb +84 -0
- data/lib/fluent/plugin_helper/timer.rb +1 -0
- data/lib/fluent/root_agent.rb +1 -1
- data/lib/fluent/test/driver/base.rb +95 -49
- 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/lib/fluent/winsvc.rb +1 -1
- data/test/command/test_binlog_reader.rb +5 -1
- data/test/compat/test_parser.rb +10 -0
- data/test/config/test_configurable.rb +193 -0
- data/test/config/test_configure_proxy.rb +0 -43
- data/test/helper.rb +36 -1
- 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 +36 -100
- 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 +268 -347
- data/test/plugin/test_in_http.rb +310 -186
- data/test/plugin/test_in_monitor_agent.rb +65 -35
- data/test/plugin/test_in_syslog.rb +39 -3
- data/test/plugin/test_in_tcp.rb +78 -62
- data/test/plugin/test_in_udp.rb +101 -80
- 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 +637 -177
- data/test/plugin/test_out_forward.rb +242 -234
- 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_output_as_buffered.rb +60 -2
- 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_inject.rb +21 -0
- data/test/plugin_helper/test_parser.rb +6 -5
- data/test/plugin_helper/test_server.rb +905 -0
- data/test/test_event_time.rb +3 -1
- data/test/test_output.rb +53 -2
- data/test/test_plugin_classes.rb +20 -0
- data/test/test_root_agent.rb +139 -0
- data/test/test_test_drivers.rb +135 -0
- metadata +28 -8
- data/test/plugin/test_parser_base.rb +0 -32
@@ -123,7 +123,7 @@ module Fluent
|
|
123
123
|
end
|
124
124
|
|
125
125
|
# configured_in MUST be kept
|
126
|
-
merged.configured_in_section = self.configured_in_section
|
126
|
+
merged.configured_in_section = self.configured_in_section || other.configured_in_section
|
127
127
|
|
128
128
|
merged.argument = other.argument || self.argument
|
129
129
|
merged.params = other.params.merge(self.params)
|
@@ -177,7 +177,7 @@ module Fluent
|
|
177
177
|
self.class.new(@name, options)
|
178
178
|
end
|
179
179
|
|
180
|
-
merged.configured_in_section = self.configured_in_section
|
180
|
+
merged.configured_in_section = self.configured_in_section || other.configured_in_section
|
181
181
|
|
182
182
|
merged.argument = self.argument || other.argument
|
183
183
|
merged.params = other.params.merge(self.params)
|
@@ -339,15 +339,6 @@ module Fluent
|
|
339
339
|
sub_proxy = ConfigureProxy.new(name, type_lookup: @type_lookup, **kwargs)
|
340
340
|
sub_proxy.instance_exec(&block)
|
341
341
|
|
342
|
-
if sub_proxy.init?
|
343
|
-
if sub_proxy.argument && !sub_proxy.defaults.has_key?(sub_proxy.argument.first)
|
344
|
-
raise ArgumentError, "#{name}: init is specified, but default value of argument is missing"
|
345
|
-
end
|
346
|
-
if sub_proxy.params.keys.any?{|param_name| !sub_proxy.defaults.has_key?(param_name)}
|
347
|
-
raise ArgumentError, "#{name}: init is specified, but there're parameters without default values"
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
342
|
@params.delete(name)
|
352
343
|
@sections[name] = sub_proxy
|
353
344
|
|
@@ -147,7 +147,7 @@ module Fluent
|
|
147
147
|
# because they are expected to be removed entirely sometime in the future.
|
148
148
|
# Obsoleted: These obsolete features have been entirely removed from JavaScript and can no longer be used.
|
149
149
|
if opts[:deprecated]
|
150
|
-
logger.warn "'#{name}' parameter is deprecated: #{opts[:deprecated]}"
|
150
|
+
logger.warn "'#{name}' parameter is deprecated: #{opts[:deprecated]}" if logger
|
151
151
|
end
|
152
152
|
if opts[:obsoleted]
|
153
153
|
logger.error "config error in:\n#{conf}" if logger
|
@@ -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/env.rb
CHANGED
@@ -18,7 +18,7 @@ module Fluent
|
|
18
18
|
DEFAULT_CONFIG_PATH = ENV['FLUENT_CONF'] || '/etc/fluent/fluent.conf'
|
19
19
|
DEFAULT_PLUGIN_DIR = ENV['FLUENT_PLUGIN'] || '/etc/fluent/plugin'
|
20
20
|
DEFAULT_SOCKET_PATH = ENV['FLUENT_SOCKET'] || '/var/run/fluent/fluent.sock'
|
21
|
-
DEFAULT_OJ_OPTIONS = {bigdecimal_load: :float, mode: :compat}
|
21
|
+
DEFAULT_OJ_OPTIONS = {bigdecimal_load: :float, mode: :compat, use_to_json: true}
|
22
22
|
IS_WINDOWS = /mswin|mingw/ === RUBY_PLATFORM
|
23
23
|
private_constant :IS_WINDOWS
|
24
24
|
|
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
|
@@ -92,24 +92,22 @@ module Fluent::Plugin
|
|
92
92
|
'tag_suffix' => tag_suffix,
|
93
93
|
'hostname' => @hostname,
|
94
94
|
}
|
95
|
-
last_record = nil
|
96
95
|
es.each do |time, record|
|
97
|
-
|
98
|
-
|
99
|
-
'
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
96
|
+
begin
|
97
|
+
placeholder_values['time'] = @placeholder_expander.time_value(time)
|
98
|
+
placeholder_values['record'] = record
|
99
|
+
|
100
|
+
new_record = reform(record, placeholder_values)
|
101
|
+
if @renew_time_key && new_record.has_key?(@renew_time_key)
|
102
|
+
time = Fluent::EventTime.from_time(Time.at(new_record[@renew_time_key].to_f))
|
103
|
+
end
|
104
|
+
new_es.add(time, new_record)
|
105
|
+
rescue => e
|
106
|
+
router.emit_error_event(tag, time, record, e)
|
107
|
+
log.debug { "map:#{@map} record:#{record} placeholder_values:#{placeholder_values}" }
|
105
108
|
end
|
106
|
-
new_es.add(time, new_record)
|
107
109
|
end
|
108
110
|
new_es
|
109
|
-
rescue => e
|
110
|
-
log.warn "failed to reform records", error: e
|
111
|
-
log.warn_backtrace
|
112
|
-
log.debug "map:#{@map} record:#{last_record} placeholder_values:#{placeholder_values}"
|
113
111
|
end
|
114
112
|
|
115
113
|
private
|
@@ -204,9 +202,6 @@ module Fluent::Plugin
|
|
204
202
|
end
|
205
203
|
elsif value.kind_of?(Hash) # record, etc
|
206
204
|
value.each do |k, v|
|
207
|
-
unless placeholder_values.has_key?(k) # prevent overwriting reserved keys such as tag
|
208
|
-
placeholders.store("${#{k}}", v) # foo
|
209
|
-
end
|
210
205
|
placeholders.store(%Q[${#{key}["#{k}"]}], v) # record["foo"]
|
211
206
|
end
|
212
207
|
else # string, interger, float, and others?
|
@@ -309,30 +304,14 @@ module Fluent::Plugin
|
|
309
304
|
placeholders['hostname'],
|
310
305
|
)
|
311
306
|
rescue => e
|
312
|
-
|
313
|
-
log.warn_backtrace
|
314
|
-
nil
|
307
|
+
raise "failed to expand `#{str}` : error = #{e}"
|
315
308
|
end
|
316
309
|
|
317
310
|
class CleanroomExpander
|
318
311
|
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
|
-
Thread.current[:record_transformer_record] = record # for old version compatibility
|
322
312
|
instance_eval(__str_to_eval__)
|
323
313
|
end
|
324
314
|
|
325
|
-
# for old version compatibility
|
326
|
-
def method_missing(name)
|
327
|
-
key = name.to_s
|
328
|
-
record = Thread.current[:record_transformer_record]
|
329
|
-
if record.has_key?(key)
|
330
|
-
record[key]
|
331
|
-
else
|
332
|
-
raise NameError, "undefined local variable or method `#{key}'"
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
315
|
(Object.instance_methods).each do |m|
|
337
316
|
undef_method m unless m.to_s =~ /^__|respond_to_missing\?|object_id|public_methods|instance_eval|method_missing|define_singleton_method|respond_to\?|new_ostruct_member/
|
338
317
|
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
|