fluentd 0.14.4-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 +7 -0
- data/.github/ISSUE_TEMPLATE.md +6 -0
- data/.gitignore +26 -0
- data/.travis.yml +45 -0
- data/AUTHORS +2 -0
- data/CONTRIBUTING.md +35 -0
- data/COPYING +14 -0
- data/ChangeLog +276 -0
- data/Gemfile +9 -0
- data/README.md +51 -0
- data/Rakefile +53 -0
- data/Vagrantfile +17 -0
- data/appveyor.yml +41 -0
- data/bin/fluent-debug +5 -0
- data/example/copy_roundrobin.conf +39 -0
- data/example/filter_stdout.conf +22 -0
- data/example/in_forward.conf +11 -0
- data/example/in_http.conf +14 -0
- data/example/in_out_forward.conf +17 -0
- data/example/in_syslog.conf +15 -0
- data/example/in_tail.conf +14 -0
- data/example/in_tcp.conf +13 -0
- data/example/in_udp.conf +13 -0
- data/example/multi_filters.conf +61 -0
- data/example/out_buffered_null.conf +32 -0
- data/example/out_copy.conf +20 -0
- data/example/out_file.conf +13 -0
- data/example/out_forward.conf +35 -0
- data/example/out_forward_buf_file.conf +23 -0
- data/example/v0_12_filter.conf +78 -0
- data/example/v1_literal_example.conf +36 -0
- data/fluent.conf +139 -0
- data/fluentd.gemspec +51 -0
- data/lib/fluent/agent.rb +194 -0
- data/lib/fluent/command/bundler_injection.rb +45 -0
- data/lib/fluent/command/cat.rb +319 -0
- data/lib/fluent/command/debug.rb +102 -0
- data/lib/fluent/command/fluentd.rb +273 -0
- data/lib/fluent/compat/call_super_mixin.rb +67 -0
- data/lib/fluent/compat/exec_util.rb +129 -0
- data/lib/fluent/compat/file_util.rb +54 -0
- data/lib/fluent/compat/filter.rb +68 -0
- data/lib/fluent/compat/formatter.rb +111 -0
- data/lib/fluent/compat/formatter_utils.rb +85 -0
- data/lib/fluent/compat/handle_tag_and_time_mixin.rb +62 -0
- data/lib/fluent/compat/handle_tag_name_mixin.rb +53 -0
- data/lib/fluent/compat/input.rb +49 -0
- data/lib/fluent/compat/output.rb +677 -0
- data/lib/fluent/compat/output_chain.rb +60 -0
- data/lib/fluent/compat/parser.rb +180 -0
- data/lib/fluent/compat/parser_utils.rb +40 -0
- data/lib/fluent/compat/propagate_default.rb +62 -0
- data/lib/fluent/compat/record_filter_mixin.rb +34 -0
- data/lib/fluent/compat/set_tag_key_mixin.rb +50 -0
- data/lib/fluent/compat/set_time_key_mixin.rb +69 -0
- data/lib/fluent/compat/socket_util.rb +165 -0
- data/lib/fluent/compat/string_util.rb +34 -0
- data/lib/fluent/compat/structured_format_mixin.rb +26 -0
- data/lib/fluent/compat/type_converter.rb +90 -0
- data/lib/fluent/config.rb +56 -0
- data/lib/fluent/config/basic_parser.rb +123 -0
- data/lib/fluent/config/configure_proxy.rb +366 -0
- data/lib/fluent/config/dsl.rb +149 -0
- data/lib/fluent/config/element.rb +218 -0
- data/lib/fluent/config/error.rb +26 -0
- data/lib/fluent/config/literal_parser.rb +251 -0
- data/lib/fluent/config/parser.rb +107 -0
- data/lib/fluent/config/section.rb +212 -0
- data/lib/fluent/config/types.rb +136 -0
- data/lib/fluent/config/v1_parser.rb +190 -0
- data/lib/fluent/configurable.rb +176 -0
- data/lib/fluent/daemon.rb +15 -0
- data/lib/fluent/engine.rb +220 -0
- data/lib/fluent/env.rb +27 -0
- data/lib/fluent/event.rb +287 -0
- data/lib/fluent/event_router.rb +259 -0
- data/lib/fluent/filter.rb +21 -0
- data/lib/fluent/formatter.rb +23 -0
- data/lib/fluent/input.rb +21 -0
- data/lib/fluent/label.rb +38 -0
- data/lib/fluent/load.rb +36 -0
- data/lib/fluent/log.rb +445 -0
- data/lib/fluent/match.rb +141 -0
- data/lib/fluent/mixin.rb +31 -0
- data/lib/fluent/msgpack_factory.rb +62 -0
- data/lib/fluent/output.rb +26 -0
- data/lib/fluent/output_chain.rb +23 -0
- data/lib/fluent/parser.rb +23 -0
- data/lib/fluent/plugin.rb +161 -0
- data/lib/fluent/plugin/bare_output.rb +63 -0
- data/lib/fluent/plugin/base.rb +130 -0
- data/lib/fluent/plugin/buf_file.rb +154 -0
- data/lib/fluent/plugin/buf_memory.rb +34 -0
- data/lib/fluent/plugin/buffer.rb +603 -0
- data/lib/fluent/plugin/buffer/chunk.rb +160 -0
- data/lib/fluent/plugin/buffer/file_chunk.rb +323 -0
- data/lib/fluent/plugin/buffer/memory_chunk.rb +90 -0
- data/lib/fluent/plugin/exec_util.rb +22 -0
- data/lib/fluent/plugin/file_util.rb +22 -0
- data/lib/fluent/plugin/file_wrapper.rb +120 -0
- data/lib/fluent/plugin/filter.rb +93 -0
- data/lib/fluent/plugin/filter_grep.rb +75 -0
- data/lib/fluent/plugin/filter_record_transformer.rb +342 -0
- data/lib/fluent/plugin/filter_stdout.rb +53 -0
- data/lib/fluent/plugin/formatter.rb +45 -0
- data/lib/fluent/plugin/formatter_csv.rb +47 -0
- data/lib/fluent/plugin/formatter_hash.rb +29 -0
- data/lib/fluent/plugin/formatter_json.rb +44 -0
- data/lib/fluent/plugin/formatter_ltsv.rb +41 -0
- data/lib/fluent/plugin/formatter_msgpack.rb +29 -0
- data/lib/fluent/plugin/formatter_out_file.rb +78 -0
- data/lib/fluent/plugin/formatter_single_value.rb +34 -0
- data/lib/fluent/plugin/formatter_stdout.rb +74 -0
- data/lib/fluent/plugin/in_debug_agent.rb +64 -0
- data/lib/fluent/plugin/in_dummy.rb +135 -0
- data/lib/fluent/plugin/in_exec.rb +149 -0
- data/lib/fluent/plugin/in_forward.rb +366 -0
- data/lib/fluent/plugin/in_gc_stat.rb +52 -0
- data/lib/fluent/plugin/in_http.rb +422 -0
- data/lib/fluent/plugin/in_monitor_agent.rb +401 -0
- data/lib/fluent/plugin/in_object_space.rb +90 -0
- data/lib/fluent/plugin/in_syslog.rb +204 -0
- data/lib/fluent/plugin/in_tail.rb +838 -0
- data/lib/fluent/plugin/in_tcp.rb +41 -0
- data/lib/fluent/plugin/in_udp.rb +37 -0
- data/lib/fluent/plugin/in_unix.rb +201 -0
- data/lib/fluent/plugin/input.rb +33 -0
- data/lib/fluent/plugin/multi_output.rb +95 -0
- data/lib/fluent/plugin/out_buffered_null.rb +59 -0
- data/lib/fluent/plugin/out_buffered_stdout.rb +70 -0
- data/lib/fluent/plugin/out_copy.rb +42 -0
- data/lib/fluent/plugin/out_exec.rb +114 -0
- data/lib/fluent/plugin/out_exec_filter.rb +393 -0
- data/lib/fluent/plugin/out_file.rb +167 -0
- data/lib/fluent/plugin/out_forward.rb +646 -0
- data/lib/fluent/plugin/out_null.rb +27 -0
- data/lib/fluent/plugin/out_relabel.rb +28 -0
- data/lib/fluent/plugin/out_roundrobin.rb +80 -0
- data/lib/fluent/plugin/out_stdout.rb +48 -0
- data/lib/fluent/plugin/out_stream.rb +130 -0
- data/lib/fluent/plugin/output.rb +1020 -0
- data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
- data/lib/fluent/plugin/parser.rb +175 -0
- data/lib/fluent/plugin/parser_apache.rb +28 -0
- data/lib/fluent/plugin/parser_apache2.rb +84 -0
- data/lib/fluent/plugin/parser_apache_error.rb +26 -0
- data/lib/fluent/plugin/parser_csv.rb +33 -0
- data/lib/fluent/plugin/parser_json.rb +79 -0
- data/lib/fluent/plugin/parser_ltsv.rb +50 -0
- data/lib/fluent/plugin/parser_multiline.rb +104 -0
- data/lib/fluent/plugin/parser_nginx.rb +28 -0
- data/lib/fluent/plugin/parser_none.rb +36 -0
- data/lib/fluent/plugin/parser_regexp.rb +73 -0
- data/lib/fluent/plugin/parser_syslog.rb +82 -0
- data/lib/fluent/plugin/parser_tsv.rb +37 -0
- data/lib/fluent/plugin/socket_util.rb +22 -0
- data/lib/fluent/plugin/storage.rb +84 -0
- data/lib/fluent/plugin/storage_local.rb +132 -0
- data/lib/fluent/plugin/string_util.rb +22 -0
- data/lib/fluent/plugin_helper.rb +42 -0
- data/lib/fluent/plugin_helper/child_process.rb +298 -0
- data/lib/fluent/plugin_helper/compat_parameters.rb +224 -0
- data/lib/fluent/plugin_helper/event_emitter.rb +80 -0
- data/lib/fluent/plugin_helper/event_loop.rb +118 -0
- data/lib/fluent/plugin_helper/formatter.rb +149 -0
- data/lib/fluent/plugin_helper/inject.rb +125 -0
- data/lib/fluent/plugin_helper/parser.rb +147 -0
- data/lib/fluent/plugin_helper/retry_state.rb +177 -0
- data/lib/fluent/plugin_helper/storage.rb +331 -0
- data/lib/fluent/plugin_helper/thread.rb +147 -0
- data/lib/fluent/plugin_helper/timer.rb +90 -0
- data/lib/fluent/plugin_id.rb +63 -0
- data/lib/fluent/process.rb +504 -0
- data/lib/fluent/registry.rb +99 -0
- data/lib/fluent/root_agent.rb +314 -0
- data/lib/fluent/rpc.rb +94 -0
- data/lib/fluent/supervisor.rb +680 -0
- data/lib/fluent/system_config.rb +122 -0
- data/lib/fluent/test.rb +56 -0
- data/lib/fluent/test/base.rb +85 -0
- data/lib/fluent/test/driver/base.rb +179 -0
- data/lib/fluent/test/driver/base_owned.rb +70 -0
- data/lib/fluent/test/driver/base_owner.rb +125 -0
- data/lib/fluent/test/driver/event_feeder.rb +98 -0
- data/lib/fluent/test/driver/filter.rb +57 -0
- data/lib/fluent/test/driver/formatter.rb +30 -0
- data/lib/fluent/test/driver/input.rb +31 -0
- data/lib/fluent/test/driver/multi_output.rb +52 -0
- data/lib/fluent/test/driver/output.rb +76 -0
- data/lib/fluent/test/driver/parser.rb +30 -0
- data/lib/fluent/test/driver/test_event_router.rb +45 -0
- data/lib/fluent/test/filter_test.rb +77 -0
- data/lib/fluent/test/formatter_test.rb +65 -0
- data/lib/fluent/test/helpers.rb +79 -0
- data/lib/fluent/test/input_test.rb +172 -0
- data/lib/fluent/test/log.rb +73 -0
- data/lib/fluent/test/output_test.rb +156 -0
- data/lib/fluent/test/parser_test.rb +70 -0
- data/lib/fluent/time.rb +175 -0
- data/lib/fluent/timezone.rb +133 -0
- data/lib/fluent/unique_id.rb +39 -0
- data/lib/fluent/version.rb +21 -0
- data/lib/fluent/winsvc.rb +71 -0
- data/test/compat/test_calls_super.rb +166 -0
- data/test/compat/test_parser.rb +82 -0
- data/test/config/assertions.rb +42 -0
- data/test/config/test_config_parser.rb +507 -0
- data/test/config/test_configurable.rb +1194 -0
- data/test/config/test_configure_proxy.rb +386 -0
- data/test/config/test_dsl.rb +415 -0
- data/test/config/test_element.rb +403 -0
- data/test/config/test_literal_parser.rb +297 -0
- data/test/config/test_section.rb +184 -0
- data/test/config/test_system_config.rb +120 -0
- data/test/config/test_types.rb +171 -0
- data/test/helper.rb +119 -0
- data/test/plugin/data/2010/01/20100102-030405.log +0 -0
- data/test/plugin/data/2010/01/20100102-030406.log +0 -0
- data/test/plugin/data/2010/01/20100102.log +0 -0
- data/test/plugin/data/log/bar +0 -0
- data/test/plugin/data/log/foo/bar.log +0 -0
- data/test/plugin/data/log/test.log +0 -0
- data/test/plugin/test_bare_output.rb +118 -0
- data/test/plugin/test_base.rb +75 -0
- data/test/plugin/test_buf_file.rb +571 -0
- data/test/plugin/test_buf_memory.rb +42 -0
- data/test/plugin/test_buffer.rb +1200 -0
- data/test/plugin/test_buffer_chunk.rb +168 -0
- data/test/plugin/test_buffer_file_chunk.rb +771 -0
- data/test/plugin/test_buffer_memory_chunk.rb +265 -0
- data/test/plugin/test_file_util.rb +96 -0
- data/test/plugin/test_filter.rb +353 -0
- data/test/plugin/test_filter_grep.rb +119 -0
- data/test/plugin/test_filter_record_transformer.rb +600 -0
- data/test/plugin/test_filter_stdout.rb +211 -0
- data/test/plugin/test_formatter_csv.rb +94 -0
- data/test/plugin/test_formatter_json.rb +30 -0
- data/test/plugin/test_formatter_ltsv.rb +52 -0
- data/test/plugin/test_formatter_msgpack.rb +28 -0
- data/test/plugin/test_formatter_out_file.rb +95 -0
- data/test/plugin/test_formatter_single_value.rb +38 -0
- data/test/plugin/test_in_debug_agent.rb +28 -0
- data/test/plugin/test_in_dummy.rb +188 -0
- data/test/plugin/test_in_exec.rb +133 -0
- data/test/plugin/test_in_forward.rb +635 -0
- data/test/plugin/test_in_gc_stat.rb +39 -0
- data/test/plugin/test_in_http.rb +442 -0
- data/test/plugin/test_in_monitor_agent.rb +329 -0
- data/test/plugin/test_in_object_space.rb +64 -0
- data/test/plugin/test_in_syslog.rb +205 -0
- data/test/plugin/test_in_tail.rb +1001 -0
- data/test/plugin/test_in_tcp.rb +102 -0
- data/test/plugin/test_in_udp.rb +121 -0
- data/test/plugin/test_in_unix.rb +126 -0
- data/test/plugin/test_input.rb +122 -0
- data/test/plugin/test_multi_output.rb +180 -0
- data/test/plugin/test_out_buffered_null.rb +79 -0
- data/test/plugin/test_out_buffered_stdout.rb +122 -0
- data/test/plugin/test_out_copy.rb +160 -0
- data/test/plugin/test_out_exec.rb +155 -0
- data/test/plugin/test_out_exec_filter.rb +262 -0
- data/test/plugin/test_out_file.rb +383 -0
- data/test/plugin/test_out_forward.rb +590 -0
- data/test/plugin/test_out_null.rb +29 -0
- data/test/plugin/test_out_relabel.rb +28 -0
- data/test/plugin/test_out_roundrobin.rb +146 -0
- data/test/plugin/test_out_stdout.rb +92 -0
- data/test/plugin/test_out_stream.rb +93 -0
- data/test/plugin/test_output.rb +568 -0
- data/test/plugin/test_output_as_buffered.rb +1604 -0
- data/test/plugin/test_output_as_buffered_overflow.rb +250 -0
- data/test/plugin/test_output_as_buffered_retries.rb +839 -0
- data/test/plugin/test_output_as_buffered_secondary.rb +817 -0
- data/test/plugin/test_output_as_standard.rb +374 -0
- data/test/plugin/test_owned_by.rb +35 -0
- data/test/plugin/test_parser_apache.rb +42 -0
- data/test/plugin/test_parser_apache2.rb +38 -0
- data/test/plugin/test_parser_apache_error.rb +45 -0
- data/test/plugin/test_parser_base.rb +32 -0
- data/test/plugin/test_parser_csv.rb +104 -0
- data/test/plugin/test_parser_json.rb +107 -0
- data/test/plugin/test_parser_labeled_tsv.rb +129 -0
- data/test/plugin/test_parser_multiline.rb +100 -0
- data/test/plugin/test_parser_nginx.rb +48 -0
- data/test/plugin/test_parser_none.rb +53 -0
- data/test/plugin/test_parser_regexp.rb +277 -0
- data/test/plugin/test_parser_syslog.rb +66 -0
- data/test/plugin/test_parser_time.rb +46 -0
- data/test/plugin/test_parser_tsv.rb +121 -0
- data/test/plugin/test_storage.rb +167 -0
- data/test/plugin/test_storage_local.rb +8 -0
- data/test/plugin/test_string_util.rb +26 -0
- data/test/plugin_helper/test_child_process.rb +608 -0
- data/test/plugin_helper/test_compat_parameters.rb +242 -0
- data/test/plugin_helper/test_event_emitter.rb +51 -0
- data/test/plugin_helper/test_event_loop.rb +52 -0
- data/test/plugin_helper/test_formatter.rb +252 -0
- data/test/plugin_helper/test_inject.rb +487 -0
- data/test/plugin_helper/test_parser.rb +263 -0
- data/test/plugin_helper/test_retry_state.rb +399 -0
- data/test/plugin_helper/test_storage.rb +521 -0
- data/test/plugin_helper/test_thread.rb +164 -0
- data/test/plugin_helper/test_timer.rb +131 -0
- data/test/scripts/exec_script.rb +32 -0
- data/test/scripts/fluent/plugin/formatter_known.rb +8 -0
- data/test/scripts/fluent/plugin/out_test.rb +81 -0
- data/test/scripts/fluent/plugin/out_test2.rb +80 -0
- data/test/scripts/fluent/plugin/parser_known.rb +4 -0
- data/test/test_config.rb +179 -0
- data/test/test_configdsl.rb +148 -0
- data/test/test_event.rb +329 -0
- data/test/test_event_router.rb +331 -0
- data/test/test_event_time.rb +184 -0
- data/test/test_filter.rb +121 -0
- data/test/test_formatter.rb +319 -0
- data/test/test_input.rb +31 -0
- data/test/test_log.rb +572 -0
- data/test/test_match.rb +137 -0
- data/test/test_mixin.rb +351 -0
- data/test/test_output.rb +214 -0
- data/test/test_plugin_classes.rb +136 -0
- data/test/test_plugin_helper.rb +81 -0
- data/test/test_process.rb +48 -0
- data/test/test_root_agent.rb +278 -0
- data/test/test_supervisor.rb +339 -0
- data/test/test_time_formatter.rb +186 -0
- data/test/test_unique_id.rb +47 -0
- metadata +823 -0
@@ -0,0 +1,70 @@
|
|
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/output'
|
18
|
+
|
19
|
+
module Fluent::Plugin
|
20
|
+
class BufferedStdoutOutput < Output
|
21
|
+
Fluent::Plugin.register_output('buffered_stdout', self)
|
22
|
+
|
23
|
+
helpers :formatter, :inject, :compat_parameters
|
24
|
+
|
25
|
+
config_section :buffer do
|
26
|
+
config_set_default :chunk_keys, ['tag']
|
27
|
+
config_set_default :flush_at_shutdown, true
|
28
|
+
config_set_default :chunk_limit_size, 10 * 1024
|
29
|
+
end
|
30
|
+
|
31
|
+
DEFAULT_FORMAT_TYPE = 'json'
|
32
|
+
|
33
|
+
config_section :format do
|
34
|
+
config_set_default :@type, DEFAULT_FORMAT_TYPE
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_accessor :delayed
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
super
|
41
|
+
@delayed = false
|
42
|
+
end
|
43
|
+
|
44
|
+
def prefer_delayed_commit
|
45
|
+
@delayed
|
46
|
+
end
|
47
|
+
|
48
|
+
def configure(conf)
|
49
|
+
if conf['output_type'] && !conf['format']
|
50
|
+
conf['format'] = conf['output_type']
|
51
|
+
end
|
52
|
+
compat_parameters_convert(conf, :inject, :formatter)
|
53
|
+
super
|
54
|
+
@formatter = formatter_create(conf: conf.elements('format').first, default_type: DEFAULT_FORMAT_TYPE)
|
55
|
+
end
|
56
|
+
|
57
|
+
def write(chunk)
|
58
|
+
chunk.write_to($log)
|
59
|
+
end
|
60
|
+
|
61
|
+
def try_write(chunk)
|
62
|
+
chunk.write_to($log)
|
63
|
+
end
|
64
|
+
|
65
|
+
def format(tag, time, record)
|
66
|
+
record = inject_values_to_record(tag, time, record)
|
67
|
+
"#{Time.at(time).localtime} #{tag}: #{@formatter.format(tag, time, record).chomp}\n"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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/multi_output'
|
18
|
+
require 'fluent/config/error'
|
19
|
+
require 'fluent/event'
|
20
|
+
|
21
|
+
module Fluent::Plugin
|
22
|
+
class CopyOutput < MultiOutput
|
23
|
+
Fluent::Plugin.register_output('copy', self)
|
24
|
+
|
25
|
+
desc 'If true, pass different record to each `store` plugin.'
|
26
|
+
config_param :deep_copy, :bool, default: false
|
27
|
+
|
28
|
+
def process(tag, es)
|
29
|
+
unless es.repeatable?
|
30
|
+
m = Fluent::MultiEventStream.new
|
31
|
+
es.each {|time,record|
|
32
|
+
m.add(time, record)
|
33
|
+
}
|
34
|
+
es = m
|
35
|
+
end
|
36
|
+
|
37
|
+
outputs.each do |output|
|
38
|
+
output.emit_events(tag, @deep_copy ? es.dup : es)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,114 @@
|
|
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 'tempfile'
|
18
|
+
|
19
|
+
require 'fluent/plugin/output'
|
20
|
+
require 'fluent/config/error'
|
21
|
+
require 'fluent/plugin/exec_util'
|
22
|
+
require 'fluent/mixin' # for TimeFormatter
|
23
|
+
|
24
|
+
module Fluent::Plugin
|
25
|
+
class ExecOutput < Output
|
26
|
+
Fluent::Plugin.register_output('exec', self)
|
27
|
+
|
28
|
+
helpers :compat_parameters
|
29
|
+
|
30
|
+
desc 'The command (program) to execute. The exec plugin passes the path of a TSV file as the last argumen'
|
31
|
+
config_param :command, :string
|
32
|
+
desc 'Specify the comma-separated keys when using the tsv format.'
|
33
|
+
config_param :keys, default: [] do |val|
|
34
|
+
val.split(',')
|
35
|
+
end
|
36
|
+
desc 'The name of the key to use as the event tag. This replaces the value in the event record.'
|
37
|
+
config_param :tag_key, :string, default: nil
|
38
|
+
desc 'The name of the key to use as the event time. This replaces the the value in the event record.'
|
39
|
+
config_param :time_key, :string, default: nil
|
40
|
+
desc 'The format for event time used when the time_key parameter is specified. The default is UNIX time (integer).'
|
41
|
+
config_param :time_format, :string, default: nil
|
42
|
+
desc "The format used to map the incoming events to the program input. (#{Fluent::ExecUtil::SUPPORTED_FORMAT.keys.join(',')})"
|
43
|
+
config_param :format, default: :tsv, skip_accessor: true do |val|
|
44
|
+
f = Fluent::ExecUtil::SUPPORTED_FORMAT[val]
|
45
|
+
raise ConfigError, "Unsupported format '#{val}'" unless f
|
46
|
+
f
|
47
|
+
end
|
48
|
+
config_param :localtime, :bool, default: false
|
49
|
+
config_param :timezone, :string, default: nil
|
50
|
+
|
51
|
+
def compat_parameters_default_chunk_key
|
52
|
+
'time'
|
53
|
+
end
|
54
|
+
|
55
|
+
def configure(conf)
|
56
|
+
compat_parameters_convert(conf, :buffer, default_chunk_key: 'time')
|
57
|
+
|
58
|
+
super
|
59
|
+
|
60
|
+
@formatter = case @format
|
61
|
+
when :tsv
|
62
|
+
if @keys.empty?
|
63
|
+
raise Fluent::ConfigError, "keys option is required on exec output for tsv format"
|
64
|
+
end
|
65
|
+
Fluent::ExecUtil::TSVFormatter.new(@keys)
|
66
|
+
when :json
|
67
|
+
Fluent::ExecUtil::JSONFormatter.new
|
68
|
+
when :msgpack
|
69
|
+
Fluent::ExecUtil::MessagePackFormatter.new
|
70
|
+
end
|
71
|
+
|
72
|
+
if @time_key
|
73
|
+
if @time_format
|
74
|
+
tf = Fluent::TimeFormatter.new(@time_format, @localtime, @timezone)
|
75
|
+
@time_format_proc = tf.method(:format)
|
76
|
+
else
|
77
|
+
@time_format_proc = Proc.new { |time| time.to_s }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def format(tag, time, record)
|
83
|
+
out = ''
|
84
|
+
if @time_key
|
85
|
+
record[@time_key] = @time_format_proc.call(time)
|
86
|
+
end
|
87
|
+
if @tag_key
|
88
|
+
record[@tag_key] = tag
|
89
|
+
end
|
90
|
+
@formatter.call(record, out)
|
91
|
+
out
|
92
|
+
end
|
93
|
+
|
94
|
+
def write(chunk)
|
95
|
+
if chunk.respond_to?(:path)
|
96
|
+
prog = "#{@command} #{chunk.path}"
|
97
|
+
else
|
98
|
+
tmpfile = Tempfile.new("fluent-plugin-exec-")
|
99
|
+
tmpfile.binmode
|
100
|
+
chunk.write_to(tmpfile)
|
101
|
+
tmpfile.close
|
102
|
+
prog = "#{@command} #{tmpfile.path}"
|
103
|
+
end
|
104
|
+
|
105
|
+
system(prog)
|
106
|
+
ecode = $?.to_i
|
107
|
+
tmpfile.delete if tmpfile
|
108
|
+
|
109
|
+
if ecode != 0
|
110
|
+
raise "command returns #{ecode}: #{prog}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,393 @@
|
|
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 'yajl'
|
18
|
+
|
19
|
+
require 'fluent/output'
|
20
|
+
require 'fluent/env'
|
21
|
+
require 'fluent/time'
|
22
|
+
require 'fluent/timezone'
|
23
|
+
require 'fluent/plugin/exec_util'
|
24
|
+
require 'fluent/config/error'
|
25
|
+
|
26
|
+
module Fluent
|
27
|
+
class ExecFilterOutput < BufferedOutput
|
28
|
+
Plugin.register_output('exec_filter', self)
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
super
|
32
|
+
require 'fluent/timezone'
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'The command (program) to execute.'
|
36
|
+
config_param :command, :string
|
37
|
+
|
38
|
+
config_param :remove_prefix, :string, default: nil
|
39
|
+
config_param :add_prefix, :string, default: nil
|
40
|
+
|
41
|
+
desc "The format used to map the incoming event to the program input.(#{Fluent::ExecUtil::SUPPORTED_FORMAT.keys.join(',')})"
|
42
|
+
config_param :in_format, default: :tsv do |val|
|
43
|
+
f = Fluent::ExecUtil::SUPPORTED_FORMAT[val]
|
44
|
+
raise ConfigError, "Unsupported in_format '#{val}'" unless f
|
45
|
+
f
|
46
|
+
end
|
47
|
+
desc 'Specify comma-separated values for tsv format.'
|
48
|
+
config_param :in_keys, default: [] do |val|
|
49
|
+
val.split(',')
|
50
|
+
end
|
51
|
+
desc 'The name of the key to use as the event tag.'
|
52
|
+
config_param :in_tag_key, default: nil
|
53
|
+
desc 'The name of the key to use as the event time.'
|
54
|
+
config_param :in_time_key, default: nil
|
55
|
+
desc 'The format for event time used when the in_time_key parameter is specified.(Defauls is UNIX time)'
|
56
|
+
config_param :in_time_format, default: nil
|
57
|
+
|
58
|
+
desc "The format used to process the program output.(#{Fluent::ExecUtil::SUPPORTED_FORMAT.keys.join(',')})"
|
59
|
+
config_param :out_format, default: :tsv do |val|
|
60
|
+
f = Fluent::ExecUtil::SUPPORTED_FORMAT[val]
|
61
|
+
raise ConfigError, "Unsupported out_format '#{val}'" unless f
|
62
|
+
f
|
63
|
+
end
|
64
|
+
desc 'Specify comma-separated values for tsv format.'
|
65
|
+
config_param :out_keys, default: [] do |val| # for tsv format
|
66
|
+
val.split(',')
|
67
|
+
end
|
68
|
+
desc 'The name of the key to use as the event tag.'
|
69
|
+
config_param :out_tag_key, default: nil
|
70
|
+
desc 'The name of the key to use as the event time.'
|
71
|
+
config_param :out_time_key, default: nil
|
72
|
+
desc 'The format for event time used when the in_time_key parameter is specified.(Defauls is UNIX time)'
|
73
|
+
config_param :out_time_format, default: nil
|
74
|
+
|
75
|
+
config_param :tag, :string, default: nil
|
76
|
+
|
77
|
+
config_param :time_key, :string, default: nil
|
78
|
+
config_param :time_format, :string, default: nil
|
79
|
+
|
80
|
+
desc 'If true, use localtime with in_time_format.'
|
81
|
+
config_param :localtime, :bool, default: true
|
82
|
+
desc 'If true, use timezone with in_time_format.'
|
83
|
+
config_param :timezone, :string, default: nil
|
84
|
+
desc 'The number of spawned process for command.'
|
85
|
+
config_param :num_children, :integer, default: 1
|
86
|
+
|
87
|
+
desc 'Respawn command when command exit.'
|
88
|
+
# nil, 'none' or 0: no respawn, 'inf' or -1: infinite times, positive integer: try to respawn specified times only
|
89
|
+
config_param :child_respawn, :string, default: nil
|
90
|
+
|
91
|
+
# 0: output logs for all of messages to emit
|
92
|
+
config_param :suppress_error_log_interval, :time, default: 0
|
93
|
+
|
94
|
+
config_set_default :flush_interval, 1
|
95
|
+
|
96
|
+
def configure(conf)
|
97
|
+
if tag_key = conf['tag_key']
|
98
|
+
# TODO obsoleted?
|
99
|
+
@in_tag_key = tag_key
|
100
|
+
@out_tag_key = tag_key
|
101
|
+
end
|
102
|
+
|
103
|
+
if time_key = conf['time_key']
|
104
|
+
# TODO obsoleted?
|
105
|
+
@in_time_key = time_key
|
106
|
+
@out_time_key = time_key
|
107
|
+
end
|
108
|
+
|
109
|
+
if time_format = conf['time_format']
|
110
|
+
# TODO obsoleted?
|
111
|
+
@in_time_format = time_format
|
112
|
+
@out_time_format = time_format
|
113
|
+
end
|
114
|
+
|
115
|
+
super
|
116
|
+
|
117
|
+
if conf['localtime']
|
118
|
+
@localtime = true
|
119
|
+
elsif conf['utc']
|
120
|
+
@localtime = false
|
121
|
+
end
|
122
|
+
|
123
|
+
if conf['timezone']
|
124
|
+
@timezone = conf['timezone']
|
125
|
+
Fluent::Timezone.validate!(@timezone)
|
126
|
+
end
|
127
|
+
|
128
|
+
if !@tag && !@out_tag_key
|
129
|
+
raise ConfigError, "'tag' or 'out_tag_key' option is required on exec_filter output"
|
130
|
+
end
|
131
|
+
|
132
|
+
if @in_time_key
|
133
|
+
if f = @in_time_format
|
134
|
+
tf = TimeFormatter.new(f, @localtime, @timezone)
|
135
|
+
@time_format_proc = tf.method(:format)
|
136
|
+
else
|
137
|
+
@time_format_proc = Proc.new {|time| time.to_s }
|
138
|
+
end
|
139
|
+
elsif @in_time_format
|
140
|
+
log.warn "in_time_format effects nothing when in_time_key is not specified: #{conf}"
|
141
|
+
end
|
142
|
+
|
143
|
+
if @out_time_key
|
144
|
+
if f = @out_time_format
|
145
|
+
@time_parse_proc =
|
146
|
+
begin
|
147
|
+
strptime = Strptime.new(f)
|
148
|
+
Proc.new { |str| Fluent::EventTime.from_time(strptime.exec(str)) }
|
149
|
+
rescue
|
150
|
+
Proc.new {|str| Fluent::EventTime.from_time(Time.strptime(str, f)) }
|
151
|
+
end
|
152
|
+
else
|
153
|
+
@time_parse_proc = Proc.new {|str| Fluent::EventTime.from_time(Time.at(str.to_f)) }
|
154
|
+
end
|
155
|
+
elsif @out_time_format
|
156
|
+
log.warn "out_time_format effects nothing when out_time_key is not specified: #{conf}"
|
157
|
+
end
|
158
|
+
|
159
|
+
if @remove_prefix
|
160
|
+
@removed_prefix_string = @remove_prefix + '.'
|
161
|
+
@removed_length = @removed_prefix_string.length
|
162
|
+
end
|
163
|
+
if @add_prefix
|
164
|
+
@added_prefix_string = @add_prefix + '.'
|
165
|
+
end
|
166
|
+
|
167
|
+
case @in_format
|
168
|
+
when :tsv
|
169
|
+
if @in_keys.empty?
|
170
|
+
raise ConfigError, "in_keys option is required on exec_filter output for tsv in_format"
|
171
|
+
end
|
172
|
+
@formatter = Fluent::ExecUtil::TSVFormatter.new(@in_keys)
|
173
|
+
when :json
|
174
|
+
@formatter = Fluent::ExecUtil::JSONFormatter.new
|
175
|
+
when :msgpack
|
176
|
+
@formatter = Fluent::ExecUtil::MessagePackFormatter.new
|
177
|
+
end
|
178
|
+
|
179
|
+
case @out_format
|
180
|
+
when :tsv
|
181
|
+
if @out_keys.empty?
|
182
|
+
raise ConfigError, "out_keys option is required on exec_filter output for tsv in_format"
|
183
|
+
end
|
184
|
+
@parser = Fluent::ExecUtil::TSVParser.new(@out_keys, method(:on_message))
|
185
|
+
when :json
|
186
|
+
@parser = Fluent::ExecUtil::JSONParser.new(method(:on_message))
|
187
|
+
when :msgpack
|
188
|
+
@parser = Fluent::ExecUtil::MessagePackParser.new(method(:on_message))
|
189
|
+
end
|
190
|
+
|
191
|
+
@respawns = if @child_respawn.nil? or @child_respawn == 'none' or @child_respawn == '0'
|
192
|
+
0
|
193
|
+
elsif @child_respawn == 'inf' or @child_respawn == '-1'
|
194
|
+
-1
|
195
|
+
elsif @child_respawn =~ /^\d+$/
|
196
|
+
@child_respawn.to_i
|
197
|
+
else
|
198
|
+
raise ConfigError, "child_respawn option argument invalid: none(or 0), inf(or -1) or positive number"
|
199
|
+
end
|
200
|
+
|
201
|
+
@suppress_error_log_interval ||= 0
|
202
|
+
@next_log_time = Time.now.to_i
|
203
|
+
end
|
204
|
+
|
205
|
+
def start
|
206
|
+
super
|
207
|
+
|
208
|
+
@children = []
|
209
|
+
@rr = 0
|
210
|
+
begin
|
211
|
+
@num_children.times do
|
212
|
+
c = ChildProcess.new(@parser, @respawns, log)
|
213
|
+
c.start(@command)
|
214
|
+
@children << c
|
215
|
+
end
|
216
|
+
rescue
|
217
|
+
shutdown
|
218
|
+
raise
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def before_shutdown
|
223
|
+
log.debug "out_exec_filter#before_shutdown called"
|
224
|
+
@children.each {|c|
|
225
|
+
c.finished = true
|
226
|
+
}
|
227
|
+
sleep 0.5 # TODO wait time before killing child process
|
228
|
+
|
229
|
+
super
|
230
|
+
end
|
231
|
+
|
232
|
+
def shutdown
|
233
|
+
@children.reject! {|c|
|
234
|
+
c.shutdown
|
235
|
+
true
|
236
|
+
}
|
237
|
+
|
238
|
+
super
|
239
|
+
end
|
240
|
+
|
241
|
+
def format_stream(tag, es)
|
242
|
+
if @remove_prefix
|
243
|
+
if (tag[0, @removed_length] == @removed_prefix_string and tag.length > @removed_length) or tag == @removed_prefix
|
244
|
+
tag = tag[@removed_length..-1] || ''
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
out = ''
|
249
|
+
|
250
|
+
es.each {|time,record|
|
251
|
+
if @in_time_key
|
252
|
+
record[@in_time_key] = @time_format_proc.call(time)
|
253
|
+
end
|
254
|
+
if @in_tag_key
|
255
|
+
record[@in_tag_key] = tag
|
256
|
+
end
|
257
|
+
@formatter.call(record, out)
|
258
|
+
}
|
259
|
+
|
260
|
+
out
|
261
|
+
end
|
262
|
+
|
263
|
+
def write(chunk)
|
264
|
+
r = @rr = (@rr + 1) % @children.length
|
265
|
+
@children[r].write chunk
|
266
|
+
end
|
267
|
+
|
268
|
+
class ChildProcess
|
269
|
+
attr_accessor :finished
|
270
|
+
|
271
|
+
def initialize(parser, respawns=0, log = $log)
|
272
|
+
@pid = nil
|
273
|
+
@thread = nil
|
274
|
+
@parser = parser
|
275
|
+
@respawns = respawns
|
276
|
+
@mutex = Mutex.new
|
277
|
+
@finished = nil
|
278
|
+
@log = log
|
279
|
+
end
|
280
|
+
|
281
|
+
def start(command)
|
282
|
+
@command = command
|
283
|
+
@mutex.synchronize do
|
284
|
+
@io = IO.popen(command, "r+")
|
285
|
+
@pid = @io.pid
|
286
|
+
@io.sync = true
|
287
|
+
@thread = Thread.new(&method(:run))
|
288
|
+
end
|
289
|
+
@finished = false
|
290
|
+
end
|
291
|
+
|
292
|
+
def kill_child(join_wait)
|
293
|
+
begin
|
294
|
+
signal = Fluent.windows? ? :KILL : :TERM
|
295
|
+
Process.kill(signal, @pid)
|
296
|
+
rescue #Errno::ECHILD, Errno::ESRCH, Errno::EPERM
|
297
|
+
# Errno::ESRCH 'No such process', ignore
|
298
|
+
# child process killed by signal chained from fluentd process
|
299
|
+
end
|
300
|
+
if @thread.join(join_wait)
|
301
|
+
# @thread successfully shutdown
|
302
|
+
return
|
303
|
+
end
|
304
|
+
begin
|
305
|
+
Process.kill(:KILL, @pid)
|
306
|
+
rescue #Errno::ECHILD, Errno::ESRCH, Errno::EPERM
|
307
|
+
# ignore if successfully killed by :TERM
|
308
|
+
end
|
309
|
+
@thread.join
|
310
|
+
end
|
311
|
+
|
312
|
+
def shutdown
|
313
|
+
@finished = true
|
314
|
+
@mutex.synchronize do
|
315
|
+
kill_child(60) # TODO wait time
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
def write(chunk)
|
320
|
+
begin
|
321
|
+
chunk.write_to(@io)
|
322
|
+
rescue Errno::EPIPE => e
|
323
|
+
# Broken pipe (child process unexpectedly exited)
|
324
|
+
@log.warn "exec_filter Broken pipe, child process maybe exited.", command: @command
|
325
|
+
if try_respawn
|
326
|
+
retry # retry chunk#write_to with child respawned
|
327
|
+
else
|
328
|
+
raise e # to retry #write with other ChildProcess instance (when num_children > 1)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
def try_respawn
|
334
|
+
return false if @respawns == 0
|
335
|
+
@mutex.synchronize do
|
336
|
+
return false if @respawns == 0
|
337
|
+
|
338
|
+
kill_child(5) # TODO wait time
|
339
|
+
|
340
|
+
@io = IO.popen(@command, "r+")
|
341
|
+
@pid = @io.pid
|
342
|
+
@io.sync = true
|
343
|
+
@thread = Thread.new(&method(:run))
|
344
|
+
|
345
|
+
@respawns -= 1 if @respawns > 0
|
346
|
+
end
|
347
|
+
@log.warn "exec_filter child process successfully respawned.", command: @command, respawns: @respawns
|
348
|
+
true
|
349
|
+
end
|
350
|
+
|
351
|
+
def run
|
352
|
+
@parser.call(@io)
|
353
|
+
rescue
|
354
|
+
@log.error "exec_filter thread unexpectedly failed with an error.", command: @command, error: $!.to_s
|
355
|
+
@log.warn_backtrace $!.backtrace
|
356
|
+
ensure
|
357
|
+
_pid, stat = Process.waitpid2(@pid)
|
358
|
+
unless @finished
|
359
|
+
@log.error "exec_filter process unexpectedly exited.", command: @command, ecode: stat.to_i
|
360
|
+
unless @respawns == 0
|
361
|
+
@log.warn "exec_filter child process will respawn for next input data (respawns #{@respawns})."
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
def on_message(record)
|
368
|
+
if val = record.delete(@out_time_key)
|
369
|
+
time = @time_parse_proc.call(val)
|
370
|
+
else
|
371
|
+
time = Engine.now
|
372
|
+
end
|
373
|
+
|
374
|
+
if val = record.delete(@out_tag_key)
|
375
|
+
tag = if @add_prefix
|
376
|
+
@added_prefix_string + val
|
377
|
+
else
|
378
|
+
val
|
379
|
+
end
|
380
|
+
else
|
381
|
+
tag = @tag
|
382
|
+
end
|
383
|
+
|
384
|
+
router.emit(tag, time, record)
|
385
|
+
rescue
|
386
|
+
if @suppress_error_log_interval == 0 || Time.now.to_i > @next_log_time
|
387
|
+
log.error "exec_filter failed to emit", error: $!, record: Yajl.dump(record)
|
388
|
+
log.warn_backtrace $!.backtrace
|
389
|
+
@next_log_time = Time.now.to_i + @suppress_error_log_interval
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|