fluentd 1.20.0-aarch64-mingw-ucrt
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 +7 -0
- data/.rubocop.yml +116 -0
- data/ADOPTERS.md +5 -0
- data/AGENTS.md +46 -0
- data/AUTHORS +2 -0
- data/CHANGELOG.md +3324 -0
- data/CONTRIBUTING.md +45 -0
- data/GOVERNANCE.md +55 -0
- data/GithubWorkflow.md +78 -0
- data/LICENSE +202 -0
- data/MAINTAINERS.md +19 -0
- data/README.md +73 -0
- data/Rakefile +89 -0
- data/SECURITY.md +47 -0
- data/bin/fluent-binlog-reader +7 -0
- data/bin/fluent-ca-generate +6 -0
- data/bin/fluent-cap-ctl +7 -0
- data/bin/fluent-cat +5 -0
- data/bin/fluent-ctl +7 -0
- data/bin/fluent-debug +5 -0
- data/bin/fluent-gem +9 -0
- data/bin/fluent-plugin-config-format +5 -0
- data/bin/fluent-plugin-generate +5 -0
- data/bin/fluentd +15 -0
- data/code-of-conduct.md +3 -0
- data/docs/SECURITY_AUDIT.pdf +0 -0
- data/example/copy_roundrobin.conf +39 -0
- data/example/counter.conf +18 -0
- data/example/filter_stdout.conf +22 -0
- data/example/in_forward.conf +14 -0
- data/example/in_forward_client.conf +37 -0
- data/example/in_forward_shared_key.conf +15 -0
- data/example/in_forward_tls.conf +14 -0
- data/example/in_forward_users.conf +24 -0
- data/example/in_forward_workers.conf +21 -0
- data/example/in_http.conf +16 -0
- data/example/in_out_forward.conf +17 -0
- data/example/in_sample_blocks.conf +17 -0
- data/example/in_sample_with_compression.conf +23 -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/logevents.conf +25 -0
- data/example/multi_filters.conf +61 -0
- data/example/out_copy.conf +20 -0
- data/example/out_exec_filter.conf +42 -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/out_forward_client.conf +109 -0
- data/example/out_forward_heartbeat_none.conf +16 -0
- data/example/out_forward_sd.conf +17 -0
- data/example/out_forward_shared_key.conf +36 -0
- data/example/out_forward_tls.conf +18 -0
- data/example/out_forward_users.conf +65 -0
- data/example/out_null.conf +36 -0
- data/example/sd.yaml +8 -0
- data/example/secondary_file.conf +42 -0
- data/example/suppress_config_dump.conf +7 -0
- data/example/v0_12_filter.conf +78 -0
- data/example/v1_literal_example.conf +36 -0
- data/example/worker_section.conf +36 -0
- data/fluent.conf +139 -0
- data/lib/fluent/agent.rb +168 -0
- data/lib/fluent/capability.rb +87 -0
- data/lib/fluent/clock.rb +66 -0
- data/lib/fluent/command/binlog_reader.rb +244 -0
- data/lib/fluent/command/bundler_injection.rb +45 -0
- data/lib/fluent/command/ca_generate.rb +184 -0
- data/lib/fluent/command/cap_ctl.rb +174 -0
- data/lib/fluent/command/cat.rb +365 -0
- data/lib/fluent/command/ctl.rb +180 -0
- data/lib/fluent/command/debug.rb +103 -0
- data/lib/fluent/command/fluentd.rb +385 -0
- data/lib/fluent/command/plugin_config_formatter.rb +308 -0
- data/lib/fluent/command/plugin_generator.rb +365 -0
- data/lib/fluent/compat/call_super_mixin.rb +76 -0
- data/lib/fluent/compat/detach_process_mixin.rb +33 -0
- data/lib/fluent/compat/exec_util.rb +144 -0
- data/lib/fluent/compat/file_util.rb +54 -0
- data/lib/fluent/compat/filter.rb +68 -0
- data/lib/fluent/compat/formatter.rb +117 -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 +721 -0
- data/lib/fluent/compat/output_chain.rb +60 -0
- data/lib/fluent/compat/parser.rb +310 -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/basic_parser.rb +122 -0
- data/lib/fluent/config/configure_proxy.rb +424 -0
- data/lib/fluent/config/dsl.rb +152 -0
- data/lib/fluent/config/element.rb +265 -0
- data/lib/fluent/config/error.rb +44 -0
- data/lib/fluent/config/literal_parser.rb +305 -0
- data/lib/fluent/config/parser.rb +119 -0
- data/lib/fluent/config/section.rb +272 -0
- data/lib/fluent/config/types.rb +257 -0
- data/lib/fluent/config/v1_parser.rb +200 -0
- data/lib/fluent/config/yaml_parser/fluent_value.rb +47 -0
- data/lib/fluent/config/yaml_parser/loader.rb +124 -0
- data/lib/fluent/config/yaml_parser/parser.rb +179 -0
- data/lib/fluent/config/yaml_parser/section_builder.rb +107 -0
- data/lib/fluent/config/yaml_parser.rb +56 -0
- data/lib/fluent/config.rb +89 -0
- data/lib/fluent/configurable.rb +202 -0
- data/lib/fluent/counter/base_socket.rb +44 -0
- data/lib/fluent/counter/client.rb +297 -0
- data/lib/fluent/counter/error.rb +86 -0
- data/lib/fluent/counter/mutex_hash.rb +163 -0
- data/lib/fluent/counter/server.rb +273 -0
- data/lib/fluent/counter/store.rb +205 -0
- data/lib/fluent/counter/validator.rb +145 -0
- data/lib/fluent/counter.rb +23 -0
- data/lib/fluent/daemon.rb +14 -0
- data/lib/fluent/daemonizer.rb +88 -0
- data/lib/fluent/engine.rb +269 -0
- data/lib/fluent/env.rb +45 -0
- data/lib/fluent/error.rb +37 -0
- data/lib/fluent/event.rb +369 -0
- data/lib/fluent/event_router.rb +315 -0
- data/lib/fluent/ext_monitor_require.rb +28 -0
- data/lib/fluent/file_wrapper.rb +137 -0
- data/lib/fluent/filter.rb +21 -0
- data/lib/fluent/fluent_log_event_router.rb +139 -0
- data/lib/fluent/formatter.rb +23 -0
- data/lib/fluent/input.rb +21 -0
- data/lib/fluent/label.rb +46 -0
- data/lib/fluent/load.rb +33 -0
- data/lib/fluent/log/console_adapter.rb +66 -0
- data/lib/fluent/log.rb +775 -0
- data/lib/fluent/match.rb +187 -0
- data/lib/fluent/mixin.rb +31 -0
- data/lib/fluent/msgpack_factory.rb +111 -0
- data/lib/fluent/oj_options.rb +61 -0
- data/lib/fluent/output.rb +29 -0
- data/lib/fluent/output_chain.rb +23 -0
- data/lib/fluent/parser.rb +23 -0
- data/lib/fluent/plugin/bare_output.rb +88 -0
- data/lib/fluent/plugin/base.rb +219 -0
- data/lib/fluent/plugin/buf_file.rb +256 -0
- data/lib/fluent/plugin/buf_file_single.rb +272 -0
- data/lib/fluent/plugin/buf_memory.rb +34 -0
- data/lib/fluent/plugin/buffer/chunk.rb +313 -0
- data/lib/fluent/plugin/buffer/file_chunk.rb +432 -0
- data/lib/fluent/plugin/buffer/file_single_chunk.rb +325 -0
- data/lib/fluent/plugin/buffer/memory_chunk.rb +91 -0
- data/lib/fluent/plugin/buffer.rb +1063 -0
- data/lib/fluent/plugin/compressable.rb +87 -0
- data/lib/fluent/plugin/exec_util.rb +22 -0
- data/lib/fluent/plugin/extractor.rb +132 -0
- data/lib/fluent/plugin/file_util.rb +22 -0
- data/lib/fluent/plugin/filter.rb +119 -0
- data/lib/fluent/plugin/filter_grep.rb +189 -0
- data/lib/fluent/plugin/filter_parser.rb +124 -0
- data/lib/fluent/plugin/filter_record_transformer.rb +325 -0
- data/lib/fluent/plugin/filter_stdout.rb +53 -0
- data/lib/fluent/plugin/formatter.rb +75 -0
- data/lib/fluent/plugin/formatter_csv.rb +92 -0
- data/lib/fluent/plugin/formatter_hash.rb +35 -0
- data/lib/fluent/plugin/formatter_json.rb +62 -0
- data/lib/fluent/plugin/formatter_ltsv.rb +44 -0
- data/lib/fluent/plugin/formatter_msgpack.rb +33 -0
- data/lib/fluent/plugin/formatter_out_file.rb +55 -0
- data/lib/fluent/plugin/formatter_single_value.rb +36 -0
- data/lib/fluent/plugin/formatter_stdout.rb +76 -0
- data/lib/fluent/plugin/formatter_tsv.rb +40 -0
- data/lib/fluent/plugin/in_debug_agent.rb +71 -0
- data/lib/fluent/plugin/in_dummy.rb +18 -0
- data/lib/fluent/plugin/in_exec.rb +124 -0
- data/lib/fluent/plugin/in_forward.rb +489 -0
- data/lib/fluent/plugin/in_gc_stat.rb +72 -0
- data/lib/fluent/plugin/in_http.rb +737 -0
- data/lib/fluent/plugin/in_monitor_agent.rb +406 -0
- data/lib/fluent/plugin/in_object_space.rb +93 -0
- data/lib/fluent/plugin/in_sample.rb +148 -0
- data/lib/fluent/plugin/in_syslog.rb +346 -0
- data/lib/fluent/plugin/in_tail/compatibility.rb +111 -0
- data/lib/fluent/plugin/in_tail/dir_watcher.rb +713 -0
- data/lib/fluent/plugin/in_tail/group_watch.rb +204 -0
- data/lib/fluent/plugin/in_tail/io_handler.rb +391 -0
- data/lib/fluent/plugin/in_tail/line_feeder.rb +230 -0
- data/lib/fluent/plugin/in_tail/position_file.rb +269 -0
- data/lib/fluent/plugin/in_tail/stat_watcher.rb +52 -0
- data/lib/fluent/plugin/in_tail/tail_watcher.rb +276 -0
- data/lib/fluent/plugin/in_tail/worker_pool.rb +298 -0
- data/lib/fluent/plugin/in_tail.rb +917 -0
- data/lib/fluent/plugin/in_tcp.rb +230 -0
- data/lib/fluent/plugin/in_udp.rb +101 -0
- data/lib/fluent/plugin/in_unix.rb +197 -0
- data/lib/fluent/plugin/input.rb +71 -0
- data/lib/fluent/plugin/metrics.rb +119 -0
- data/lib/fluent/plugin/metrics_local.rb +96 -0
- data/lib/fluent/plugin/multi_output.rb +179 -0
- data/lib/fluent/plugin/out_buffer.rb +40 -0
- data/lib/fluent/plugin/out_copy.rb +120 -0
- data/lib/fluent/plugin/out_exec.rb +105 -0
- data/lib/fluent/plugin/out_exec_filter.rb +319 -0
- data/lib/fluent/plugin/out_file.rb +371 -0
- data/lib/fluent/plugin/out_forward/ack_handler.rb +176 -0
- data/lib/fluent/plugin/out_forward/connection_manager.rb +131 -0
- data/lib/fluent/plugin/out_forward/error.rb +28 -0
- data/lib/fluent/plugin/out_forward/failure_detector.rb +84 -0
- data/lib/fluent/plugin/out_forward/handshake_protocol.rb +125 -0
- data/lib/fluent/plugin/out_forward/load_balancer.rb +114 -0
- data/lib/fluent/plugin/out_forward/socket_cache.rb +177 -0
- data/lib/fluent/plugin/out_forward.rb +865 -0
- data/lib/fluent/plugin/out_http.rb +419 -0
- data/lib/fluent/plugin/out_null.rb +74 -0
- data/lib/fluent/plugin/out_relabel.rb +32 -0
- data/lib/fluent/plugin/out_roundrobin.rb +84 -0
- data/lib/fluent/plugin/out_secondary_file.rb +148 -0
- data/lib/fluent/plugin/out_stdout.rb +81 -0
- data/lib/fluent/plugin/out_stream.rb +130 -0
- data/lib/fluent/plugin/output.rb +1688 -0
- data/lib/fluent/plugin/owned_by_mixin.rb +41 -0
- data/lib/fluent/plugin/parser.rb +274 -0
- data/lib/fluent/plugin/parser_apache.rb +28 -0
- data/lib/fluent/plugin/parser_apache2.rb +88 -0
- data/lib/fluent/plugin/parser_apache_error.rb +26 -0
- data/lib/fluent/plugin/parser_csv.rb +124 -0
- data/lib/fluent/plugin/parser_json.rb +118 -0
- data/lib/fluent/plugin/parser_ltsv.rb +49 -0
- data/lib/fluent/plugin/parser_msgpack.rb +72 -0
- data/lib/fluent/plugin/parser_multiline.rb +152 -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 +68 -0
- data/lib/fluent/plugin/parser_syslog.rb +543 -0
- data/lib/fluent/plugin/parser_tsv.rb +47 -0
- data/lib/fluent/plugin/sd_file.rb +157 -0
- data/lib/fluent/plugin/sd_srv.rb +135 -0
- data/lib/fluent/plugin/sd_static.rb +58 -0
- data/lib/fluent/plugin/service_discovery.rb +65 -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 +166 -0
- data/lib/fluent/plugin/string_util.rb +22 -0
- data/lib/fluent/plugin.rb +206 -0
- data/lib/fluent/plugin_helper/cert_option.rb +199 -0
- data/lib/fluent/plugin_helper/child_process.rb +369 -0
- data/lib/fluent/plugin_helper/compat_parameters.rb +343 -0
- data/lib/fluent/plugin_helper/counter.rb +51 -0
- data/lib/fluent/plugin_helper/event_emitter.rb +112 -0
- data/lib/fluent/plugin_helper/event_loop.rb +170 -0
- data/lib/fluent/plugin_helper/extract.rb +104 -0
- data/lib/fluent/plugin_helper/formatter.rb +147 -0
- data/lib/fluent/plugin_helper/http_server/app.rb +81 -0
- data/lib/fluent/plugin_helper/http_server/methods.rb +35 -0
- data/lib/fluent/plugin_helper/http_server/request.rb +53 -0
- data/lib/fluent/plugin_helper/http_server/router.rb +54 -0
- data/lib/fluent/plugin_helper/http_server/server.rb +116 -0
- data/lib/fluent/plugin_helper/http_server/ssl_context_builder.rb +41 -0
- data/lib/fluent/plugin_helper/http_server.rb +129 -0
- data/lib/fluent/plugin_helper/inject.rb +154 -0
- data/lib/fluent/plugin_helper/metrics.rb +136 -0
- data/lib/fluent/plugin_helper/parser.rb +147 -0
- data/lib/fluent/plugin_helper/record_accessor.rb +207 -0
- data/lib/fluent/plugin_helper/retry_state.rb +219 -0
- data/lib/fluent/plugin_helper/server.rb +840 -0
- data/lib/fluent/plugin_helper/service_discovery/manager.rb +146 -0
- data/lib/fluent/plugin_helper/service_discovery/round_robin_balancer.rb +43 -0
- data/lib/fluent/plugin_helper/service_discovery.rb +125 -0
- data/lib/fluent/plugin_helper/socket.rb +288 -0
- data/lib/fluent/plugin_helper/socket_option.rb +98 -0
- data/lib/fluent/plugin_helper/storage.rb +349 -0
- data/lib/fluent/plugin_helper/thread.rb +180 -0
- data/lib/fluent/plugin_helper/timer.rb +92 -0
- data/lib/fluent/plugin_helper.rb +75 -0
- data/lib/fluent/plugin_id.rb +93 -0
- data/lib/fluent/process.rb +22 -0
- data/lib/fluent/registry.rb +117 -0
- data/lib/fluent/root_agent.rb +468 -0
- data/lib/fluent/rpc.rb +95 -0
- data/lib/fluent/source_only_buffer_agent.rb +102 -0
- data/lib/fluent/static_config_analysis.rb +195 -0
- data/lib/fluent/supervisor.rb +1347 -0
- data/lib/fluent/system_config.rb +213 -0
- data/lib/fluent/test/base.rb +83 -0
- data/lib/fluent/test/driver/base.rb +231 -0
- data/lib/fluent/test/driver/base_owned.rb +83 -0
- data/lib/fluent/test/driver/base_owner.rb +135 -0
- data/lib/fluent/test/driver/event_feeder.rb +98 -0
- data/lib/fluent/test/driver/filter.rb +61 -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 +53 -0
- data/lib/fluent/test/driver/output.rb +102 -0
- data/lib/fluent/test/driver/parser.rb +30 -0
- data/lib/fluent/test/driver/storage.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 +138 -0
- data/lib/fluent/test/input_test.rb +174 -0
- data/lib/fluent/test/log.rb +79 -0
- data/lib/fluent/test/output_test.rb +156 -0
- data/lib/fluent/test/parser_test.rb +70 -0
- data/lib/fluent/test/startup_shutdown.rb +44 -0
- data/lib/fluent/test.rb +61 -0
- data/lib/fluent/time.rb +513 -0
- data/lib/fluent/timezone.rb +171 -0
- data/lib/fluent/tls.rb +105 -0
- data/lib/fluent/unique_id.rb +39 -0
- data/lib/fluent/variable_store.rb +40 -0
- data/lib/fluent/version.rb +21 -0
- data/lib/fluent/win32api.rb +38 -0
- data/lib/fluent/winsvc.rb +130 -0
- data/templates/new_gem/.gitignore +8 -0
- data/templates/new_gem/Gemfile +3 -0
- data/templates/new_gem/README.md.erb +43 -0
- data/templates/new_gem/Rakefile +13 -0
- data/templates/new_gem/fluent-plugin.gemspec.erb +28 -0
- data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +14 -0
- data/templates/new_gem/lib/fluent/plugin/formatter.rb.erb +14 -0
- data/templates/new_gem/lib/fluent/plugin/input.rb.erb +11 -0
- data/templates/new_gem/lib/fluent/plugin/output.rb.erb +11 -0
- data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +15 -0
- data/templates/new_gem/lib/fluent/plugin/storage.rb.erb +40 -0
- data/templates/new_gem/test/helper.rb.erb +7 -0
- data/templates/new_gem/test/plugin/test_filter.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_formatter.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_input.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_output.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_parser.rb.erb +18 -0
- data/templates/new_gem/test/plugin/test_storage.rb.erb +18 -0
- data/templates/plugin_config_formatter/param.md-compact.erb +25 -0
- data/templates/plugin_config_formatter/param.md-table.erb +10 -0
- data/templates/plugin_config_formatter/param.md.erb +34 -0
- data/templates/plugin_config_formatter/section.md.erb +12 -0
- metadata +996 -0
|
@@ -0,0 +1,1347 @@
|
|
|
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 'fileutils'
|
|
18
|
+
require 'open3'
|
|
19
|
+
require 'pathname'
|
|
20
|
+
require 'find'
|
|
21
|
+
require 'set'
|
|
22
|
+
|
|
23
|
+
require 'fluent/config'
|
|
24
|
+
require 'fluent/counter'
|
|
25
|
+
require 'fluent/env'
|
|
26
|
+
require 'fluent/engine'
|
|
27
|
+
require 'fluent/error'
|
|
28
|
+
require 'fluent/log'
|
|
29
|
+
require 'fluent/plugin'
|
|
30
|
+
require 'fluent/rpc'
|
|
31
|
+
require 'fluent/system_config'
|
|
32
|
+
require 'fluent/msgpack_factory'
|
|
33
|
+
require 'fluent/variable_store'
|
|
34
|
+
require 'serverengine'
|
|
35
|
+
|
|
36
|
+
if Fluent.windows?
|
|
37
|
+
require 'win32/ipc'
|
|
38
|
+
require 'win32/event'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
module Fluent
|
|
42
|
+
module ServerModule
|
|
43
|
+
def before_run
|
|
44
|
+
@fluentd_conf = config[:fluentd_conf]
|
|
45
|
+
@rpc_endpoint = nil
|
|
46
|
+
@rpc_server = nil
|
|
47
|
+
@counter = nil
|
|
48
|
+
@socket_manager_server = nil
|
|
49
|
+
@starting_new_supervisor_with_zero_downtime = false
|
|
50
|
+
@new_supervisor_pid = nil
|
|
51
|
+
start_in_parallel = ENV.key?("FLUENT_RUNNING_IN_PARALLEL_WITH_OLD")
|
|
52
|
+
@zero_downtime_restart_mutex = Mutex.new
|
|
53
|
+
|
|
54
|
+
@fluentd_lock_dir = Dir.mktmpdir("fluentd-lock-")
|
|
55
|
+
ENV['FLUENTD_LOCK_DIR'] = @fluentd_lock_dir
|
|
56
|
+
|
|
57
|
+
if config[:rpc_endpoint] and not start_in_parallel
|
|
58
|
+
@rpc_endpoint = config[:rpc_endpoint]
|
|
59
|
+
@enable_get_dump = config[:enable_get_dump]
|
|
60
|
+
run_rpc_server
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
if Fluent.windows?
|
|
64
|
+
install_windows_event_handler
|
|
65
|
+
else
|
|
66
|
+
install_supervisor_signal_handlers
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if counter = config[:counter_server] and not start_in_parallel
|
|
70
|
+
run_counter_server(counter)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if config[:disable_shared_socket]
|
|
74
|
+
$log.info "shared socket for multiple workers is disabled"
|
|
75
|
+
elsif start_in_parallel
|
|
76
|
+
begin
|
|
77
|
+
raise "[BUG] SERVERENGINE_SOCKETMANAGER_PATH env var must exist when starting in parallel" unless ENV.key?('SERVERENGINE_SOCKETMANAGER_PATH')
|
|
78
|
+
@socket_manager_server = ServerEngine::SocketManager::Server.share_sockets_with_another_server(ENV['SERVERENGINE_SOCKETMANAGER_PATH'])
|
|
79
|
+
$log.info "zero-downtime-restart: took over the shared sockets", path: ENV['SERVERENGINE_SOCKETMANAGER_PATH']
|
|
80
|
+
rescue => e
|
|
81
|
+
$log.error "zero-downtime-restart: cancel sequence because failed to take over the shared sockets", error: e
|
|
82
|
+
raise
|
|
83
|
+
end
|
|
84
|
+
else
|
|
85
|
+
@socket_manager_server = ServerEngine::SocketManager::Server.open
|
|
86
|
+
ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = @socket_manager_server.path.to_s
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
stop_parallel_old_supervisor_after_delay if start_in_parallel
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def after_run
|
|
93
|
+
stop_windows_event_thread if Fluent.windows?
|
|
94
|
+
stop_rpc_server if @rpc_endpoint
|
|
95
|
+
stop_counter_server if @counter
|
|
96
|
+
cleanup_lock_dir
|
|
97
|
+
Fluent::Supervisor.cleanup_socketmanager_path unless @starting_new_supervisor_with_zero_downtime
|
|
98
|
+
ensure
|
|
99
|
+
notify_new_supervisor_that_old_one_has_stopped if @starting_new_supervisor_with_zero_downtime
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def cleanup_lock_dir
|
|
103
|
+
begin
|
|
104
|
+
Dir.each_child(@fluentd_lock_dir) do |name|
|
|
105
|
+
FileUtils.rm_f(File.join(@fluentd_lock_dir, name)) if File.fnmatch?("fluentd-*.lock", name)
|
|
106
|
+
end
|
|
107
|
+
rescue Errno::ENOENT
|
|
108
|
+
# Directory is already missing. Fall through and let rmdir below
|
|
109
|
+
# fail in the same way as the current implementation.
|
|
110
|
+
end
|
|
111
|
+
FileUtils.rmdir(@fluentd_lock_dir)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def run_rpc_server
|
|
115
|
+
@rpc_server = RPC::Server.new(@rpc_endpoint, $log)
|
|
116
|
+
|
|
117
|
+
# built-in RPC for signals
|
|
118
|
+
@rpc_server.mount_proc('/api/processes.interruptWorkers') { |req, res|
|
|
119
|
+
$log.debug "fluentd RPC got /api/processes.interruptWorkers request"
|
|
120
|
+
Process.kill :INT, Process.pid
|
|
121
|
+
nil
|
|
122
|
+
}
|
|
123
|
+
@rpc_server.mount_proc('/api/processes.killWorkers') { |req, res|
|
|
124
|
+
$log.debug "fluentd RPC got /api/processes.killWorkers request"
|
|
125
|
+
Process.kill :TERM, Process.pid
|
|
126
|
+
nil
|
|
127
|
+
}
|
|
128
|
+
@rpc_server.mount_proc('/api/processes.flushBuffersAndKillWorkers') { |req, res|
|
|
129
|
+
$log.debug "fluentd RPC got /api/processes.flushBuffersAndKillWorkers request"
|
|
130
|
+
if Fluent.windows?
|
|
131
|
+
supervisor_sigusr1_handler
|
|
132
|
+
stop(true)
|
|
133
|
+
else
|
|
134
|
+
Process.kill :USR1, Process.pid
|
|
135
|
+
Process.kill :TERM, Process.pid
|
|
136
|
+
end
|
|
137
|
+
nil
|
|
138
|
+
}
|
|
139
|
+
unless Fluent.windows?
|
|
140
|
+
@rpc_server.mount_proc('/api/processes.zeroDowntimeRestart') { |req, res|
|
|
141
|
+
$log.debug "fluentd RPC got /api/processes.zeroDowntimeRestart request"
|
|
142
|
+
Process.kill :USR2, Process.pid
|
|
143
|
+
nil
|
|
144
|
+
}
|
|
145
|
+
end
|
|
146
|
+
@rpc_server.mount_proc('/api/plugins.flushBuffers') { |req, res|
|
|
147
|
+
$log.debug "fluentd RPC got /api/plugins.flushBuffers request"
|
|
148
|
+
if Fluent.windows?
|
|
149
|
+
supervisor_sigusr1_handler
|
|
150
|
+
else
|
|
151
|
+
Process.kill :USR1, Process.pid
|
|
152
|
+
end
|
|
153
|
+
nil
|
|
154
|
+
}
|
|
155
|
+
@rpc_server.mount_proc('/api/config.reload') { |req, res|
|
|
156
|
+
$log.debug "fluentd RPC got /api/config.reload request"
|
|
157
|
+
if Fluent.windows?
|
|
158
|
+
# restart worker with auto restarting by killing
|
|
159
|
+
kill_worker
|
|
160
|
+
else
|
|
161
|
+
Process.kill :HUP, Process.pid
|
|
162
|
+
end
|
|
163
|
+
nil
|
|
164
|
+
}
|
|
165
|
+
@rpc_server.mount_proc('/api/config.dump') { |req, res|
|
|
166
|
+
$log.debug "fluentd RPC got /api/config.dump request"
|
|
167
|
+
$log.info "dump in-memory config"
|
|
168
|
+
supervisor_dump_config_handler
|
|
169
|
+
nil
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@rpc_server.mount_proc('/api/config.gracefulReload') { |req, res|
|
|
173
|
+
$log.debug "fluentd RPC got /api/config.gracefulReload request"
|
|
174
|
+
graceful_reload
|
|
175
|
+
nil
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if @enable_get_dump
|
|
179
|
+
@rpc_server.mount_proc('/api/config.getDump') { |req, res|
|
|
180
|
+
$log.debug "fluentd RPC got /api/config.getDump request"
|
|
181
|
+
$log.info "get dump in-memory config via HTTP"
|
|
182
|
+
res.body = supervisor_get_dump_config_handler
|
|
183
|
+
[nil, nil, res]
|
|
184
|
+
}
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
@rpc_server.start
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def stop_rpc_server
|
|
191
|
+
@rpc_server&.shutdown
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def run_counter_server(counter_conf)
|
|
195
|
+
@counter = Fluent::Counter::Server.new(
|
|
196
|
+
counter_conf.scope,
|
|
197
|
+
{host: counter_conf.bind, port: counter_conf.port, log: $log, path: counter_conf.backup_path}
|
|
198
|
+
)
|
|
199
|
+
@counter.start
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def stop_counter_server
|
|
203
|
+
@counter.stop
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def stop_parallel_old_supervisor_after_delay
|
|
207
|
+
Thread.new do
|
|
208
|
+
# Delay to wait the new workers to start up.
|
|
209
|
+
# Even if it takes a long time to start the new workers and stop the old Fluentd first,
|
|
210
|
+
# it is no problem because the socket buffer works, as long as the capacity is not exceeded.
|
|
211
|
+
sleep 10
|
|
212
|
+
old_pid = ENV["FLUENT_RUNNING_IN_PARALLEL_WITH_OLD"]&.to_i
|
|
213
|
+
if old_pid
|
|
214
|
+
$log.info "zero-downtime-restart: stop the old supervisor"
|
|
215
|
+
Process.kill :TERM, old_pid
|
|
216
|
+
end
|
|
217
|
+
rescue => e
|
|
218
|
+
$log.warn "zero-downtime-restart: failed to stop the old supervisor." +
|
|
219
|
+
" If the old one does not exist, please send SIGWINCH to this new process to start to work fully." +
|
|
220
|
+
" If it exists, something went wrong. Please kill the old one manually.",
|
|
221
|
+
error: e
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def notify_new_supervisor_that_old_one_has_stopped
|
|
226
|
+
if config[:pid_path]
|
|
227
|
+
new_pid = File.read(config[:pid_path]).to_i
|
|
228
|
+
else
|
|
229
|
+
raise "[BUG] new_supervisor_pid is not saved" unless @new_supervisor_pid
|
|
230
|
+
new_pid = @new_supervisor_pid
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
$log.info "zero-downtime-restart: notify the new supervisor (pid: #{new_pid}) that old one has stopped"
|
|
234
|
+
Process.kill :WINCH, new_pid
|
|
235
|
+
rescue => e
|
|
236
|
+
$log.error(
|
|
237
|
+
"zero-downtime-restart: failed to notify the new supervisor." +
|
|
238
|
+
" Please send SIGWINCH to the new supervisor process manually" +
|
|
239
|
+
" if it does not start to work fully.",
|
|
240
|
+
error: e
|
|
241
|
+
)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def install_supervisor_signal_handlers
|
|
245
|
+
return if Fluent.windows?
|
|
246
|
+
|
|
247
|
+
trap :HUP do
|
|
248
|
+
$log.debug "fluentd supervisor process get SIGHUP"
|
|
249
|
+
supervisor_sighup_handler
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
trap :USR1 do
|
|
253
|
+
$log.debug "fluentd supervisor process get SIGUSR1"
|
|
254
|
+
supervisor_sigusr1_handler
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
trap :USR2 do
|
|
258
|
+
$log.debug 'fluentd supervisor process got SIGUSR2'
|
|
259
|
+
if Fluent.windows?
|
|
260
|
+
graceful_reload
|
|
261
|
+
else
|
|
262
|
+
zero_downtime_restart
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
trap :WINCH do
|
|
267
|
+
$log.debug 'fluentd supervisor process got SIGWINCH'
|
|
268
|
+
cancel_source_only
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
if Fluent.windows?
|
|
273
|
+
# Override some methods of ServerEngine::MultiSpawnWorker
|
|
274
|
+
# Since Fluentd's Supervisor doesn't use ServerEngine's HUP, USR1 and USR2
|
|
275
|
+
# handlers (see install_supervisor_signal_handlers), they should be
|
|
276
|
+
# disabled also on Windows, just send commands to workers instead.
|
|
277
|
+
def restart(graceful)
|
|
278
|
+
@monitors.each do |m|
|
|
279
|
+
m.send_command(graceful ? "GRACEFUL_RESTART\n" : "IMMEDIATE_RESTART\n")
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def reload
|
|
284
|
+
@monitors.each do |m|
|
|
285
|
+
m.send_command("RELOAD\n")
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def install_windows_event_handler
|
|
291
|
+
return unless Fluent.windows?
|
|
292
|
+
|
|
293
|
+
@pid_signame = "fluentd_#{Process.pid}"
|
|
294
|
+
@signame = config[:signame]
|
|
295
|
+
|
|
296
|
+
Thread.new do
|
|
297
|
+
ipc = Win32::Ipc.new(nil)
|
|
298
|
+
events = [
|
|
299
|
+
{win32_event: Win32::Event.new("#{@pid_signame}_STOP_EVENT_THREAD"), action: :stop_event_thread},
|
|
300
|
+
{win32_event: Win32::Event.new("#{@pid_signame}"), action: :stop},
|
|
301
|
+
{win32_event: Win32::Event.new("#{@pid_signame}_HUP"), action: :hup},
|
|
302
|
+
{win32_event: Win32::Event.new("#{@pid_signame}_USR1"), action: :usr1},
|
|
303
|
+
{win32_event: Win32::Event.new("#{@pid_signame}_USR2"), action: :usr2},
|
|
304
|
+
{win32_event: Win32::Event.new("#{@pid_signame}_CONT"), action: :cont},
|
|
305
|
+
]
|
|
306
|
+
if @signame
|
|
307
|
+
signame_events = [
|
|
308
|
+
{win32_event: Win32::Event.new("#{@signame}"), action: :stop},
|
|
309
|
+
{win32_event: Win32::Event.new("#{@signame}_HUP"), action: :hup},
|
|
310
|
+
{win32_event: Win32::Event.new("#{@signame}_USR1"), action: :usr1},
|
|
311
|
+
{win32_event: Win32::Event.new("#{@signame}_USR2"), action: :usr2},
|
|
312
|
+
{win32_event: Win32::Event.new("#{@signame}_CONT"), action: :cont},
|
|
313
|
+
]
|
|
314
|
+
events.concat(signame_events)
|
|
315
|
+
end
|
|
316
|
+
begin
|
|
317
|
+
loop do
|
|
318
|
+
infinite = 0xFFFFFFFF
|
|
319
|
+
ipc_idx = ipc.wait_any(events.map {|e| e[:win32_event]}, infinite)
|
|
320
|
+
event_idx = ipc_idx - 1
|
|
321
|
+
|
|
322
|
+
if event_idx >= 0 && event_idx < events.length
|
|
323
|
+
$log.debug("Got Win32 event \"#{events[event_idx][:win32_event].name}\"")
|
|
324
|
+
else
|
|
325
|
+
$log.warn("Unexpected return value of Win32::Ipc#wait_any: #{ipc_idx}")
|
|
326
|
+
end
|
|
327
|
+
case events[event_idx][:action]
|
|
328
|
+
when :stop
|
|
329
|
+
stop(true)
|
|
330
|
+
when :hup
|
|
331
|
+
supervisor_sighup_handler
|
|
332
|
+
when :usr1
|
|
333
|
+
supervisor_sigusr1_handler
|
|
334
|
+
when :usr2
|
|
335
|
+
graceful_reload
|
|
336
|
+
when :cont
|
|
337
|
+
supervisor_dump_handler_for_windows
|
|
338
|
+
when :stop_event_thread
|
|
339
|
+
break
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
ensure
|
|
343
|
+
events.each { |event| event[:win32_event].close }
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def stop_windows_event_thread
|
|
349
|
+
if Fluent.windows?
|
|
350
|
+
ev = Win32::Event.open("#{@pid_signame}_STOP_EVENT_THREAD")
|
|
351
|
+
ev.set
|
|
352
|
+
ev.close
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def supervisor_sighup_handler
|
|
357
|
+
kill_worker
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
def supervisor_sigusr1_handler
|
|
361
|
+
reopen_log
|
|
362
|
+
send_signal_to_workers(:USR1)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def graceful_reload
|
|
366
|
+
conf = nil
|
|
367
|
+
t = Thread.new do
|
|
368
|
+
$log.info 'Reloading new config'
|
|
369
|
+
|
|
370
|
+
# Validate that loading config is valid at first
|
|
371
|
+
conf = Fluent::Config.build(
|
|
372
|
+
config_path: config[:config_path],
|
|
373
|
+
encoding: config[:conf_encoding],
|
|
374
|
+
additional_config: config[:inline_config],
|
|
375
|
+
use_v1_config: config[:use_v1_config],
|
|
376
|
+
type: config[:config_file_type],
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
Fluent::VariableStore.try_to_reset do
|
|
380
|
+
Fluent::Engine.reload_config(conf, supervisor: true)
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
t.report_on_exception = false # Error is handled by myself
|
|
385
|
+
t.join
|
|
386
|
+
|
|
387
|
+
reopen_log
|
|
388
|
+
send_signal_to_workers(:USR2)
|
|
389
|
+
@fluentd_conf = conf.to_s
|
|
390
|
+
rescue => e
|
|
391
|
+
$log.error "Failed to reload config file: #{e}"
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
def zero_downtime_restart
|
|
395
|
+
Thread.new do
|
|
396
|
+
@zero_downtime_restart_mutex.synchronize do
|
|
397
|
+
$log.info "start zero-downtime-restart sequence"
|
|
398
|
+
|
|
399
|
+
if @starting_new_supervisor_with_zero_downtime
|
|
400
|
+
$log.warn "zero-downtime-restart: canceled because it is already starting"
|
|
401
|
+
Thread.exit
|
|
402
|
+
end
|
|
403
|
+
if ENV.key?("FLUENT_RUNNING_IN_PARALLEL_WITH_OLD")
|
|
404
|
+
$log.warn "zero-downtime-restart: canceled because the previous sequence is still running"
|
|
405
|
+
Thread.exit
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
@starting_new_supervisor_with_zero_downtime = true
|
|
409
|
+
commands = [ServerEngine.ruby_bin_path, $0] + ARGV
|
|
410
|
+
env_to_add = {
|
|
411
|
+
"SERVERENGINE_SOCKETMANAGER_INTERNAL_TOKEN" => ServerEngine::SocketManager::INTERNAL_TOKEN,
|
|
412
|
+
"FLUENT_RUNNING_IN_PARALLEL_WITH_OLD" => "#{Process.pid}",
|
|
413
|
+
}
|
|
414
|
+
pid = Process.spawn(env_to_add, commands.join(" "))
|
|
415
|
+
@new_supervisor_pid = pid unless config[:daemonize]
|
|
416
|
+
|
|
417
|
+
if config[:daemonize]
|
|
418
|
+
Thread.new(pid) do |pid|
|
|
419
|
+
_, status = Process.wait2(pid)
|
|
420
|
+
# check if `ServerEngine::Daemon#daemonize_with_double_fork` succeeded or not
|
|
421
|
+
unless status.success?
|
|
422
|
+
@starting_new_supervisor_with_zero_downtime = false
|
|
423
|
+
$log.error "zero-downtime-restart: failed because new supervisor exits unexpectedly"
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
else
|
|
427
|
+
Thread.new(pid) do |pid|
|
|
428
|
+
_, status = Process.wait2(pid)
|
|
429
|
+
@starting_new_supervisor_with_zero_downtime = false
|
|
430
|
+
$log.error "zero-downtime-restart: failed because new supervisor exits unexpectedly", status: status
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
rescue => e
|
|
435
|
+
$log.error "zero-downtime-restart: failed", error: e
|
|
436
|
+
@starting_new_supervisor_with_zero_downtime = false
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
def cancel_source_only
|
|
441
|
+
if ENV.key?("FLUENT_RUNNING_IN_PARALLEL_WITH_OLD")
|
|
442
|
+
if config[:rpc_endpoint]
|
|
443
|
+
begin
|
|
444
|
+
@rpc_endpoint = config[:rpc_endpoint]
|
|
445
|
+
@enable_get_dump = config[:enable_get_dump]
|
|
446
|
+
run_rpc_server
|
|
447
|
+
rescue => e
|
|
448
|
+
$log.error "failed to start RPC server", error: e
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
if counter = config[:counter_server]
|
|
453
|
+
begin
|
|
454
|
+
run_counter_server(counter)
|
|
455
|
+
rescue => e
|
|
456
|
+
$log.error "failed to start counter server", error: e
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
$log.info "zero-downtime-restart: done all sequences, now new processes start to work fully"
|
|
461
|
+
ENV.delete("FLUENT_RUNNING_IN_PARALLEL_WITH_OLD")
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
send_signal_to_workers(:WINCH)
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
def supervisor_dump_handler_for_windows
|
|
468
|
+
# As for UNIX-like, SIGCONT signal to each process makes the process output its dump-file,
|
|
469
|
+
# and it is implemented before the implementation of the function for Windows.
|
|
470
|
+
# It is possible to trap SIGCONT and handle it here also on UNIX-like,
|
|
471
|
+
# but for backward compatibility, this handler is currently for a Windows-only.
|
|
472
|
+
raise "[BUG] This function is for Windows ONLY." unless Fluent.windows?
|
|
473
|
+
|
|
474
|
+
Thread.new do
|
|
475
|
+
begin
|
|
476
|
+
FluentSigdump.dump_windows
|
|
477
|
+
rescue => e
|
|
478
|
+
$log.error "failed to dump: #{e}"
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
send_signal_to_workers(:CONT)
|
|
483
|
+
rescue => e
|
|
484
|
+
$log.error "failed to dump: #{e}"
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
def kill_worker
|
|
488
|
+
if config[:worker_pid]
|
|
489
|
+
pids = config[:worker_pid].clone
|
|
490
|
+
config[:worker_pid].clear
|
|
491
|
+
pids.each_value do |pid|
|
|
492
|
+
if Fluent.windows?
|
|
493
|
+
Process.kill :KILL, pid
|
|
494
|
+
else
|
|
495
|
+
Process.kill :TERM, pid
|
|
496
|
+
end
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
def supervisor_dump_config_handler
|
|
502
|
+
$log.info @fluentd_conf
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
def supervisor_get_dump_config_handler
|
|
506
|
+
{ conf: @fluentd_conf }
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
def dump
|
|
510
|
+
super unless @stop
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
private
|
|
514
|
+
|
|
515
|
+
def reopen_log
|
|
516
|
+
if $log
|
|
517
|
+
# Creating new thread due to mutex can't lock
|
|
518
|
+
# in main thread during trap context
|
|
519
|
+
Thread.new do
|
|
520
|
+
$log.reopen!
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
def send_signal_to_workers(signal)
|
|
526
|
+
return unless config[:worker_pid]
|
|
527
|
+
|
|
528
|
+
if Fluent.windows?
|
|
529
|
+
send_command_to_workers(signal)
|
|
530
|
+
else
|
|
531
|
+
config[:worker_pid].each_value do |pid|
|
|
532
|
+
# don't rescue Errno::ESRCH here (invalid status)
|
|
533
|
+
Process.kill(signal, pid)
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
def send_command_to_workers(signal)
|
|
539
|
+
# Use SeverEngine's CommandSender on Windows
|
|
540
|
+
case signal
|
|
541
|
+
when :HUP
|
|
542
|
+
restart(false)
|
|
543
|
+
when :USR1
|
|
544
|
+
restart(true)
|
|
545
|
+
when :USR2
|
|
546
|
+
reload
|
|
547
|
+
when :CONT
|
|
548
|
+
dump_all_windows_workers
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
def dump_all_windows_workers
|
|
553
|
+
@monitors.each do |m|
|
|
554
|
+
m.send_command("DUMP\n")
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
module WorkerModule
|
|
560
|
+
def spawn(process_manager)
|
|
561
|
+
main_cmd = config[:main_cmd]
|
|
562
|
+
env = {
|
|
563
|
+
'SERVERENGINE_WORKER_ID' => @worker_id.to_i.to_s,
|
|
564
|
+
'FLUENT_INSTANCE_ID' => Fluent::INSTANCE_ID,
|
|
565
|
+
}
|
|
566
|
+
@pm = process_manager.spawn(env, *main_cmd)
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
def after_start
|
|
570
|
+
(config[:worker_pid] ||= {})[@worker_id] = @pm.pid
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
def dump
|
|
574
|
+
super unless @stop
|
|
575
|
+
end
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
class Supervisor
|
|
579
|
+
def self.serverengine_config(params = {})
|
|
580
|
+
# ServerEngine's "daemonize" option is boolean, and path of pid file is brought by "pid_path"
|
|
581
|
+
pid_path = params['daemonize']
|
|
582
|
+
daemonize = !!params['daemonize']
|
|
583
|
+
|
|
584
|
+
se_config = {
|
|
585
|
+
worker_type: 'spawn',
|
|
586
|
+
workers: params['workers'],
|
|
587
|
+
log_stdin: false,
|
|
588
|
+
log_stdout: false,
|
|
589
|
+
log_stderr: false,
|
|
590
|
+
enable_heartbeat: true,
|
|
591
|
+
auto_heartbeat: false,
|
|
592
|
+
unrecoverable_exit_codes: [2],
|
|
593
|
+
stop_immediately_at_unrecoverable_exit: true,
|
|
594
|
+
root_dir: params['root_dir'],
|
|
595
|
+
logger: $log,
|
|
596
|
+
log: $log&.out,
|
|
597
|
+
log_level: params['log_level'],
|
|
598
|
+
chuser: params['chuser'],
|
|
599
|
+
chgroup: params['chgroup'],
|
|
600
|
+
chumask: params['chumask'].is_a?(Integer) ? params['chumask'] : params['chumask']&.to_i(8),
|
|
601
|
+
daemonize: daemonize,
|
|
602
|
+
rpc_endpoint: params['rpc_endpoint'],
|
|
603
|
+
counter_server: params['counter_server'],
|
|
604
|
+
enable_get_dump: params['enable_get_dump'],
|
|
605
|
+
windows_daemon_cmdline: [ServerEngine.ruby_bin_path,
|
|
606
|
+
File.join(File.dirname(__FILE__), 'daemon.rb'),
|
|
607
|
+
ServerModule.name,
|
|
608
|
+
WorkerModule.name,
|
|
609
|
+
JSON.dump(params)],
|
|
610
|
+
command_sender: Fluent.windows? ? "pipe" : "signal",
|
|
611
|
+
config_path: params['fluentd_conf_path'],
|
|
612
|
+
fluentd_conf: params['fluentd_conf'],
|
|
613
|
+
conf_encoding: params['conf_encoding'],
|
|
614
|
+
inline_config: params['inline_config'],
|
|
615
|
+
use_v1_config: params['use_v1_config'],
|
|
616
|
+
config_file_type: params['config_file_type']&.to_sym,
|
|
617
|
+
main_cmd: params['main_cmd'],
|
|
618
|
+
signame: params['signame'],
|
|
619
|
+
disable_shared_socket: params['disable_shared_socket'],
|
|
620
|
+
restart_worker_interval: params['restart_worker_interval'],
|
|
621
|
+
}
|
|
622
|
+
se_config[:pid_path] = pid_path if daemonize
|
|
623
|
+
|
|
624
|
+
se_config
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
def self.default_options
|
|
628
|
+
{
|
|
629
|
+
config_path: Fluent::DEFAULT_CONFIG_PATH,
|
|
630
|
+
plugin_dirs: [Fluent::DEFAULT_PLUGIN_DIR],
|
|
631
|
+
log_level: Fluent::Log::LEVEL_INFO,
|
|
632
|
+
log_path: nil,
|
|
633
|
+
daemonize: nil,
|
|
634
|
+
libs: [],
|
|
635
|
+
setup_path: nil,
|
|
636
|
+
chuser: nil,
|
|
637
|
+
chgroup: nil,
|
|
638
|
+
chumask: "0",
|
|
639
|
+
root_dir: nil,
|
|
640
|
+
suppress_interval: 0,
|
|
641
|
+
suppress_repeated_stacktrace: true,
|
|
642
|
+
ignore_repeated_log_interval: nil,
|
|
643
|
+
without_source: nil,
|
|
644
|
+
with_source_only: nil,
|
|
645
|
+
enable_input_metrics: true,
|
|
646
|
+
enable_size_metrics: nil,
|
|
647
|
+
use_v1_config: true,
|
|
648
|
+
strict_config_value: nil,
|
|
649
|
+
supervise: true,
|
|
650
|
+
standalone_worker: false,
|
|
651
|
+
signame: nil,
|
|
652
|
+
conf_encoding: 'utf-8',
|
|
653
|
+
disable_shared_socket: nil,
|
|
654
|
+
config_file_type: :guess,
|
|
655
|
+
}
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
def self.cleanup_socketmanager_path
|
|
659
|
+
return if Fluent.windows?
|
|
660
|
+
return unless ENV.key?('SERVERENGINE_SOCKETMANAGER_PATH')
|
|
661
|
+
|
|
662
|
+
FileUtils.rm_f(ENV['SERVERENGINE_SOCKETMANAGER_PATH'])
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
def initialize(cl_opt)
|
|
666
|
+
@cl_opt = cl_opt
|
|
667
|
+
opt = self.class.default_options.merge(cl_opt)
|
|
668
|
+
|
|
669
|
+
@config_file_type = opt[:config_file_type]
|
|
670
|
+
@daemonize = opt[:daemonize]
|
|
671
|
+
@standalone_worker= opt[:standalone_worker]
|
|
672
|
+
@config_path = opt[:config_path]
|
|
673
|
+
@inline_config = opt[:inline_config]
|
|
674
|
+
@use_v1_config = opt[:use_v1_config]
|
|
675
|
+
@conf_encoding = opt[:conf_encoding]
|
|
676
|
+
@show_plugin_config = opt[:show_plugin_config]
|
|
677
|
+
@libs = opt[:libs]
|
|
678
|
+
@plugin_dirs = opt[:plugin_dirs]
|
|
679
|
+
@chgroup = opt[:chgroup]
|
|
680
|
+
@chuser = opt[:chuser]
|
|
681
|
+
@chumask = opt[:chumask]
|
|
682
|
+
@signame = opt[:signame]
|
|
683
|
+
|
|
684
|
+
# TODO: `@log_path`, `@log_rotate_age` and `@log_rotate_size` should be removed
|
|
685
|
+
# since it should be merged with SystemConfig in `build_system_config()`.
|
|
686
|
+
# We should always use `system_config.log.path`, `system_config.log.rotate_age`
|
|
687
|
+
# and `system_config.log.rotate_size`.
|
|
688
|
+
# However, currently, there is a bug that `system_config.log` parameters
|
|
689
|
+
# are not in `Fluent::SystemConfig::SYSTEM_CONFIG_PARAMETERS`, and these
|
|
690
|
+
# parameters are not merged in `build_system_config()`.
|
|
691
|
+
# Until we fix the bug of `Fluent::SystemConfig`, we need to use these instance variables.
|
|
692
|
+
@log_path = opt[:log_path]
|
|
693
|
+
@log_rotate_age = opt[:log_rotate_age]
|
|
694
|
+
@log_rotate_size = opt[:log_rotate_size]
|
|
695
|
+
|
|
696
|
+
@finished = false
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
def run_supervisor(dry_run: false)
|
|
700
|
+
if dry_run
|
|
701
|
+
$log.info "starting fluentd-#{Fluent::VERSION} as dry run mode", ruby: RUBY_VERSION
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
if @system_config.workers < 1
|
|
705
|
+
raise Fluent::ConfigError, "invalid number of workers (must be > 0):#{@system_config.workers}"
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
if Fluent.windows? && @system_config.with_source_only
|
|
709
|
+
raise Fluent::ConfigError, "with-source-only is not supported on Windows"
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
root_dir = @system_config.root_dir
|
|
713
|
+
if root_dir
|
|
714
|
+
if File.exist?(root_dir)
|
|
715
|
+
unless Dir.exist?(root_dir)
|
|
716
|
+
raise Fluent::InvalidRootDirectory, "non directory entry exists:#{root_dir}"
|
|
717
|
+
end
|
|
718
|
+
else
|
|
719
|
+
begin
|
|
720
|
+
FileUtils.mkdir_p(root_dir, mode: @system_config.dir_permission || Fluent::DEFAULT_DIR_PERMISSION)
|
|
721
|
+
rescue => e
|
|
722
|
+
raise Fluent::InvalidRootDirectory, "failed to create root directory:#{root_dir}, #{e.inspect}"
|
|
723
|
+
end
|
|
724
|
+
end
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
begin
|
|
728
|
+
ServerEngine::Privilege.change(@chuser, @chgroup)
|
|
729
|
+
MessagePackFactory.init(enable_time_support: @system_config.enable_msgpack_time_support)
|
|
730
|
+
Fluent::Engine.init(@system_config, supervisor_mode: true, start_in_parallel: ENV.key?("FLUENT_RUNNING_IN_PARALLEL_WITH_OLD"))
|
|
731
|
+
Fluent::Engine.run_configure(@conf, dry_run: dry_run)
|
|
732
|
+
rescue Fluent::ConfigError => e
|
|
733
|
+
$log.error 'config error', file: @config_path, error: e
|
|
734
|
+
$log.debug_backtrace
|
|
735
|
+
exit!(1)
|
|
736
|
+
rescue ScriptError => e # LoadError, NotImplementedError, SyntaxError
|
|
737
|
+
if e.respond_to?(:path)
|
|
738
|
+
$log.error e.message, path: e.path, error: e
|
|
739
|
+
else
|
|
740
|
+
$log.error e.message, error: e
|
|
741
|
+
end
|
|
742
|
+
$log.debug_backtrace
|
|
743
|
+
exit!(1)
|
|
744
|
+
rescue => e
|
|
745
|
+
$log.error "unexpected error", error: e
|
|
746
|
+
$log.debug_backtrace
|
|
747
|
+
exit!(1)
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
if dry_run
|
|
751
|
+
$log.info 'finished dry run mode'
|
|
752
|
+
exit 0
|
|
753
|
+
else
|
|
754
|
+
supervise
|
|
755
|
+
end
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
def options
|
|
759
|
+
{
|
|
760
|
+
'config_path' => @config_path,
|
|
761
|
+
'pid_file' => @daemonize,
|
|
762
|
+
'plugin_dirs' => @plugin_dirs,
|
|
763
|
+
'log_path' => @log_path,
|
|
764
|
+
'root_dir' => @system_config.root_dir,
|
|
765
|
+
}
|
|
766
|
+
end
|
|
767
|
+
|
|
768
|
+
def run_worker
|
|
769
|
+
Process.setproctitle("worker:#{@system_config.process_name}") if @process_name
|
|
770
|
+
|
|
771
|
+
if @standalone_worker && @system_config.workers != 1
|
|
772
|
+
raise Fluent::ConfigError, "invalid number of workers (must be 1 or unspecified) with --no-supervisor: #{@system_config.workers}"
|
|
773
|
+
end
|
|
774
|
+
|
|
775
|
+
if Fluent.windows? && @system_config.with_source_only
|
|
776
|
+
raise Fluent::ConfigError, "with-source-only is not supported on Windows"
|
|
777
|
+
end
|
|
778
|
+
|
|
779
|
+
install_main_process_signal_handlers
|
|
780
|
+
|
|
781
|
+
# This is the only log message for @standalone_worker
|
|
782
|
+
$log.info "starting fluentd-#{Fluent::VERSION} without supervision", pid: Process.pid, ruby: RUBY_VERSION if @standalone_worker
|
|
783
|
+
|
|
784
|
+
main_process do
|
|
785
|
+
create_socket_manager if @standalone_worker
|
|
786
|
+
if @standalone_worker
|
|
787
|
+
ServerEngine::Privilege.change(@chuser, @chgroup)
|
|
788
|
+
File.umask(@chumask.to_i(8))
|
|
789
|
+
end
|
|
790
|
+
MessagePackFactory.init(enable_time_support: @system_config.enable_msgpack_time_support)
|
|
791
|
+
Fluent::Engine.init(@system_config, start_in_parallel: ENV.key?("FLUENT_RUNNING_IN_PARALLEL_WITH_OLD"))
|
|
792
|
+
Fluent::Engine.run_configure(@conf)
|
|
793
|
+
enable_ruby_jit if @system_config.enable_jit
|
|
794
|
+
Fluent::Engine.run
|
|
795
|
+
self.class.cleanup_socketmanager_path if @standalone_worker
|
|
796
|
+
exit 0
|
|
797
|
+
end
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
def configure(supervisor: false)
|
|
801
|
+
setup_global_logger(supervisor: supervisor)
|
|
802
|
+
|
|
803
|
+
if @show_plugin_config
|
|
804
|
+
show_plugin_config
|
|
805
|
+
end
|
|
806
|
+
|
|
807
|
+
if @inline_config == '-'
|
|
808
|
+
$log.warn('the value "-" for `inline_config` is deprecated. See https://github.com/fluent/fluentd/issues/2711')
|
|
809
|
+
@inline_config = STDIN.read
|
|
810
|
+
end
|
|
811
|
+
parsed_files = Set.new
|
|
812
|
+
@conf = Fluent::Config.build(
|
|
813
|
+
config_path: @config_path,
|
|
814
|
+
encoding: @conf_encoding,
|
|
815
|
+
additional_config: @inline_config,
|
|
816
|
+
use_v1_config: @use_v1_config,
|
|
817
|
+
type: @config_file_type,
|
|
818
|
+
on_file_parsed: ->(path) { parsed_files << path },
|
|
819
|
+
)
|
|
820
|
+
@system_config = build_system_config(@conf)
|
|
821
|
+
|
|
822
|
+
# `<system> umask` sets the process umask, just like the `--umask` command
|
|
823
|
+
# line option. The command line option takes precedence when both are given.
|
|
824
|
+
if @system_config.umask && !@cl_opt.key?(:chumask)
|
|
825
|
+
@chumask = @system_config.umask
|
|
826
|
+
end
|
|
827
|
+
|
|
828
|
+
$log.info :supervisor, 'parsing config file is succeeded', path: @config_path
|
|
829
|
+
|
|
830
|
+
build_additional_configurations(parsed_files) do |additional_conf|
|
|
831
|
+
@conf += additional_conf
|
|
832
|
+
end
|
|
833
|
+
|
|
834
|
+
if Fluent.windows?
|
|
835
|
+
@conf.elements.each do |element|
|
|
836
|
+
next unless element.name == 'source'
|
|
837
|
+
if element['@type'] == 'tail' && element['pos_file']
|
|
838
|
+
$log.warn("Recommend adding #{File.dirname(element['pos_file'])} to the exclusion path of your antivirus software on Windows")
|
|
839
|
+
else
|
|
840
|
+
storage = element.elements.find { |v| v.name == 'storage' and v['@type'] == 'local' }
|
|
841
|
+
if storage
|
|
842
|
+
$log.warn("Recommend adding #{File.dirname(storage['path'])} to the exclusion path of your antivirus software on Windows")
|
|
843
|
+
end
|
|
844
|
+
end
|
|
845
|
+
end
|
|
846
|
+
end
|
|
847
|
+
|
|
848
|
+
@libs.each do |lib|
|
|
849
|
+
require lib
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
@plugin_dirs.each do |dir|
|
|
853
|
+
if Dir.exist?(dir)
|
|
854
|
+
dir = File.expand_path(dir)
|
|
855
|
+
Fluent::Plugin.add_plugin_dir(dir)
|
|
856
|
+
end
|
|
857
|
+
end
|
|
858
|
+
|
|
859
|
+
if supervisor
|
|
860
|
+
# plugins / configuration dumps
|
|
861
|
+
Gem::Specification.find_all.select { |x| x.name =~ /^fluent(d|-(plugin|mixin)-.*)$/ }.each do |spec|
|
|
862
|
+
$log.info("gem '#{spec.name}' version '#{spec.version}'")
|
|
863
|
+
end
|
|
864
|
+
end
|
|
865
|
+
end
|
|
866
|
+
|
|
867
|
+
private
|
|
868
|
+
|
|
869
|
+
def setup_global_logger(supervisor: false)
|
|
870
|
+
if supervisor
|
|
871
|
+
worker_id = 0
|
|
872
|
+
process_type = :supervisor
|
|
873
|
+
else
|
|
874
|
+
worker_id = ENV['SERVERENGINE_WORKER_ID'].to_i
|
|
875
|
+
process_type = case
|
|
876
|
+
when @standalone_worker then :standalone
|
|
877
|
+
when worker_id == 0 then :worker0
|
|
878
|
+
else :workers
|
|
879
|
+
end
|
|
880
|
+
end
|
|
881
|
+
|
|
882
|
+
# Parse configuration immediately to initialize logger in early stage.
|
|
883
|
+
# Since we can't confirm the log messages in this parsing process,
|
|
884
|
+
# we must parse the config again after initializing logger.
|
|
885
|
+
conf = Fluent::Config.build(
|
|
886
|
+
config_path: @config_path,
|
|
887
|
+
encoding: @conf_encoding,
|
|
888
|
+
additional_config: @inline_config,
|
|
889
|
+
use_v1_config: @use_v1_config,
|
|
890
|
+
type: @config_file_type,
|
|
891
|
+
on_file_parsed: nil,
|
|
892
|
+
)
|
|
893
|
+
system_config = build_system_config(conf)
|
|
894
|
+
|
|
895
|
+
# TODO: we should remove this logic. This merging process should be done
|
|
896
|
+
# in `build_system_config()`.
|
|
897
|
+
@log_path ||= system_config.log.path
|
|
898
|
+
@log_rotate_age ||= system_config.log.rotate_age
|
|
899
|
+
@log_rotate_size ||= system_config.log.rotate_size
|
|
900
|
+
|
|
901
|
+
rotate = @log_rotate_age || @log_rotate_size
|
|
902
|
+
actual_log_path = @log_path
|
|
903
|
+
|
|
904
|
+
# We need to prepare a unique path for each worker since Windows locks files.
|
|
905
|
+
if Fluent.windows? && rotate && @log_path && @log_path != "-"
|
|
906
|
+
actual_log_path = Fluent::Log.per_process_path(@log_path, process_type, worker_id)
|
|
907
|
+
end
|
|
908
|
+
|
|
909
|
+
if actual_log_path && actual_log_path != "-"
|
|
910
|
+
FileUtils.mkdir_p(File.dirname(actual_log_path)) unless File.exist?(actual_log_path)
|
|
911
|
+
if rotate
|
|
912
|
+
logdev = Fluent::LogDeviceIO.new(
|
|
913
|
+
actual_log_path,
|
|
914
|
+
shift_age: @log_rotate_age,
|
|
915
|
+
shift_size: @log_rotate_size,
|
|
916
|
+
)
|
|
917
|
+
else
|
|
918
|
+
logdev = File.open(actual_log_path, "a")
|
|
919
|
+
end
|
|
920
|
+
|
|
921
|
+
if @chuser || @chgroup
|
|
922
|
+
chuid = @chuser ? ServerEngine::Privilege.get_etc_passwd(@chuser).uid : nil
|
|
923
|
+
chgid = @chgroup ? ServerEngine::Privilege.get_etc_group(@chgroup).gid : nil
|
|
924
|
+
File.chown(chuid, chgid, actual_log_path)
|
|
925
|
+
end
|
|
926
|
+
|
|
927
|
+
if system_config.dir_permission
|
|
928
|
+
File.chmod(system_config.dir_permission || Fluent::DEFAULT_DIR_PERMISSION, File.dirname(actual_log_path))
|
|
929
|
+
end
|
|
930
|
+
else
|
|
931
|
+
logdev = STDOUT
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
$log = Fluent::Log.new(
|
|
935
|
+
# log_level: subtract 1 to match serverengine daemon logger side logging severity.
|
|
936
|
+
ServerEngine::DaemonLogger.new(logdev, log_level: system_config.log_level - 1),
|
|
937
|
+
path: actual_log_path,
|
|
938
|
+
process_type: process_type,
|
|
939
|
+
worker_id: worker_id,
|
|
940
|
+
format: system_config.log.format,
|
|
941
|
+
time_format: system_config.log.time_format,
|
|
942
|
+
suppress_repeated_stacktrace: system_config.suppress_repeated_stacktrace,
|
|
943
|
+
ignore_repeated_log_interval: system_config.ignore_repeated_log_interval,
|
|
944
|
+
ignore_same_log_interval: system_config.ignore_same_log_interval,
|
|
945
|
+
)
|
|
946
|
+
$log.force_stacktrace_level(system_config.log.forced_stacktrace_level) if system_config.force_stacktrace_level?
|
|
947
|
+
$log.enable_color(false) if actual_log_path
|
|
948
|
+
$log.enable_debug if system_config.log_level <= Fluent::Log::LEVEL_DEBUG
|
|
949
|
+
|
|
950
|
+
$log.info "init #{process_type} logger",
|
|
951
|
+
path: actual_log_path,
|
|
952
|
+
rotate_age: @log_rotate_age,
|
|
953
|
+
rotate_size: @log_rotate_size
|
|
954
|
+
end
|
|
955
|
+
|
|
956
|
+
def create_socket_manager
|
|
957
|
+
server = ServerEngine::SocketManager::Server.open
|
|
958
|
+
ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = server.path.to_s
|
|
959
|
+
end
|
|
960
|
+
|
|
961
|
+
def show_plugin_config
|
|
962
|
+
name, type = @show_plugin_config.split(":") # input:tail
|
|
963
|
+
$log.info "show_plugin_config option is deprecated. Use fluent-plugin-config-format --format=txt #{name} #{type}"
|
|
964
|
+
exit 0
|
|
965
|
+
end
|
|
966
|
+
|
|
967
|
+
def supervise
|
|
968
|
+
Process.setproctitle("supervisor:#{@system_config.process_name}") if @system_config.process_name
|
|
969
|
+
$log.info "starting fluentd-#{Fluent::VERSION}", pid: Process.pid, ruby: RUBY_VERSION
|
|
970
|
+
|
|
971
|
+
fluentd_spawn_cmd = build_spawn_command
|
|
972
|
+
$log.info "spawn command to main: ", cmdline: fluentd_spawn_cmd
|
|
973
|
+
|
|
974
|
+
params = {
|
|
975
|
+
'main_cmd' => fluentd_spawn_cmd,
|
|
976
|
+
'daemonize' => @daemonize,
|
|
977
|
+
'inline_config' => @inline_config,
|
|
978
|
+
'chuser' => @chuser,
|
|
979
|
+
'chgroup' => @chgroup,
|
|
980
|
+
'chumask' => @chumask,
|
|
981
|
+
'fluentd_conf_path' => @config_path,
|
|
982
|
+
'fluentd_conf' => @conf.to_s,
|
|
983
|
+
'use_v1_config' => @use_v1_config,
|
|
984
|
+
'config_file_type' => @config_file_type,
|
|
985
|
+
'conf_encoding' => @conf_encoding,
|
|
986
|
+
'signame' => @signame,
|
|
987
|
+
|
|
988
|
+
'workers' => @system_config.workers,
|
|
989
|
+
'root_dir' => @system_config.root_dir,
|
|
990
|
+
'log_level' => @system_config.log_level,
|
|
991
|
+
'rpc_endpoint' => @system_config.rpc_endpoint,
|
|
992
|
+
'enable_get_dump' => @system_config.enable_get_dump,
|
|
993
|
+
'counter_server' => @system_config.counter_server,
|
|
994
|
+
'disable_shared_socket' => @system_config.disable_shared_socket,
|
|
995
|
+
'restart_worker_interval' => @system_config.restart_worker_interval,
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
se = ServerEngine.create(ServerModule, WorkerModule) {
|
|
999
|
+
# Note: This is called only at the initialization of ServerEngine, since
|
|
1000
|
+
# Fluentd overwrites all related SIGNAL(HUP,USR1,USR2) and have own reloading feature.
|
|
1001
|
+
Fluent::Supervisor.serverengine_config(params)
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
se.run
|
|
1005
|
+
end
|
|
1006
|
+
|
|
1007
|
+
def install_main_process_signal_handlers
|
|
1008
|
+
# Fluentd worker process (worker of ServerEngine) don't use code in serverengine to set signal handlers,
|
|
1009
|
+
# because it does almost nothing.
|
|
1010
|
+
# This method is the only method to set signal handlers in Fluentd worker process.
|
|
1011
|
+
|
|
1012
|
+
# When user use Ctrl + C not SIGINT, SIGINT is sent to all process in same process group.
|
|
1013
|
+
# ServerEngine server process will send SIGTERM to child(spawned) processes by that SIGINT, so
|
|
1014
|
+
# worker process SHOULD NOT do anything with SIGINT, SHOULD just ignore.
|
|
1015
|
+
trap :INT do
|
|
1016
|
+
$log.debug "fluentd main process get SIGINT"
|
|
1017
|
+
|
|
1018
|
+
# When Fluentd is launched without supervisor, worker should handle ctrl-c by itself
|
|
1019
|
+
if @standalone_worker
|
|
1020
|
+
@finished = true
|
|
1021
|
+
$log.debug "getting start to shutdown main process"
|
|
1022
|
+
Fluent::Engine.stop
|
|
1023
|
+
end
|
|
1024
|
+
end
|
|
1025
|
+
|
|
1026
|
+
trap :TERM do
|
|
1027
|
+
$log.debug "fluentd main process get SIGTERM"
|
|
1028
|
+
unless @finished
|
|
1029
|
+
@finished = true
|
|
1030
|
+
$log.debug "getting start to shutdown main process"
|
|
1031
|
+
Fluent::Engine.stop
|
|
1032
|
+
end
|
|
1033
|
+
end
|
|
1034
|
+
|
|
1035
|
+
if Fluent.windows?
|
|
1036
|
+
install_main_process_command_handlers
|
|
1037
|
+
else
|
|
1038
|
+
trap :USR1 do
|
|
1039
|
+
flush_buffer
|
|
1040
|
+
end
|
|
1041
|
+
|
|
1042
|
+
trap :USR2 do
|
|
1043
|
+
# Leave the old GracefulReload feature, just in case.
|
|
1044
|
+
# We can send SIGUSR2 to the worker process to use this old GracefulReload feature.
|
|
1045
|
+
# (Note: Normally, we can send SIGUSR2 to the supervisor process to use
|
|
1046
|
+
# zero-downtime-restart feature as GracefulReload on non-Windows.)
|
|
1047
|
+
reload_config
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
trap :CONT do
|
|
1051
|
+
dump_non_windows
|
|
1052
|
+
end
|
|
1053
|
+
|
|
1054
|
+
trap :WINCH do
|
|
1055
|
+
cancel_source_only
|
|
1056
|
+
end
|
|
1057
|
+
end
|
|
1058
|
+
end
|
|
1059
|
+
|
|
1060
|
+
def install_main_process_command_handlers
|
|
1061
|
+
command_pipe = $stdin.dup
|
|
1062
|
+
$stdin.reopen(File::NULL, "rb")
|
|
1063
|
+
command_pipe.binmode
|
|
1064
|
+
command_pipe.sync = true
|
|
1065
|
+
|
|
1066
|
+
Thread.new do
|
|
1067
|
+
loop do
|
|
1068
|
+
cmd = command_pipe.gets
|
|
1069
|
+
break unless cmd
|
|
1070
|
+
|
|
1071
|
+
case cmd.chomp!
|
|
1072
|
+
when "GRACEFUL_STOP", "IMMEDIATE_STOP"
|
|
1073
|
+
$log.debug "fluentd main process get #{cmd} command"
|
|
1074
|
+
@finished = true
|
|
1075
|
+
$log.debug "getting start to shutdown main process"
|
|
1076
|
+
Fluent::Engine.stop
|
|
1077
|
+
break
|
|
1078
|
+
when "GRACEFUL_RESTART"
|
|
1079
|
+
$log.debug "fluentd main process get #{cmd} command"
|
|
1080
|
+
flush_buffer
|
|
1081
|
+
when "RELOAD"
|
|
1082
|
+
$log.debug "fluentd main process get #{cmd} command"
|
|
1083
|
+
reload_config
|
|
1084
|
+
when "DUMP"
|
|
1085
|
+
$log.debug "fluentd main process get #{cmd} command"
|
|
1086
|
+
dump_windows
|
|
1087
|
+
else
|
|
1088
|
+
$log.warn "fluentd main process get unknown command [#{cmd}]"
|
|
1089
|
+
end
|
|
1090
|
+
end
|
|
1091
|
+
end
|
|
1092
|
+
end
|
|
1093
|
+
|
|
1094
|
+
def flush_buffer
|
|
1095
|
+
# Creating new thread due to mutex can't lock
|
|
1096
|
+
# in main thread during trap context
|
|
1097
|
+
Thread.new do
|
|
1098
|
+
begin
|
|
1099
|
+
$log.debug "fluentd main process get SIGUSR1"
|
|
1100
|
+
$log.info "force flushing buffered events"
|
|
1101
|
+
$log.reopen!
|
|
1102
|
+
Fluent::Engine.flush!
|
|
1103
|
+
$log.debug "flushing thread: flushed"
|
|
1104
|
+
rescue Exception => e
|
|
1105
|
+
$log.warn "flushing thread error: #{e}"
|
|
1106
|
+
end
|
|
1107
|
+
end
|
|
1108
|
+
end
|
|
1109
|
+
|
|
1110
|
+
def cancel_source_only
|
|
1111
|
+
Thread.new do
|
|
1112
|
+
begin
|
|
1113
|
+
$log.debug "fluentd main process get SIGWINCH"
|
|
1114
|
+
$log.info "try to cancel with-source-only mode"
|
|
1115
|
+
Fluent::Engine.cancel_source_only!
|
|
1116
|
+
rescue Exception => e
|
|
1117
|
+
$log.warn "failed to cancel source only", error: e
|
|
1118
|
+
end
|
|
1119
|
+
end
|
|
1120
|
+
end
|
|
1121
|
+
|
|
1122
|
+
def reload_config
|
|
1123
|
+
Thread.new do
|
|
1124
|
+
$log.debug('worker got SIGUSR2')
|
|
1125
|
+
|
|
1126
|
+
begin
|
|
1127
|
+
parsed_files = Set.new
|
|
1128
|
+
conf = Fluent::Config.build(
|
|
1129
|
+
config_path: @config_path,
|
|
1130
|
+
encoding: @conf_encoding,
|
|
1131
|
+
additional_config: @inline_config,
|
|
1132
|
+
use_v1_config: @use_v1_config,
|
|
1133
|
+
type: @config_file_type,
|
|
1134
|
+
on_file_parsed: ->(path) { parsed_files << path },
|
|
1135
|
+
)
|
|
1136
|
+
|
|
1137
|
+
build_additional_configurations(parsed_files) do |additional_conf|
|
|
1138
|
+
conf += additional_conf
|
|
1139
|
+
end
|
|
1140
|
+
|
|
1141
|
+
Fluent::VariableStore.try_to_reset do
|
|
1142
|
+
Fluent::Engine.reload_config(conf)
|
|
1143
|
+
end
|
|
1144
|
+
rescue => e
|
|
1145
|
+
# it is guaranteed that config file is valid by supervisor side. but it's not atomic because of using signals to commnicate between worker and super
|
|
1146
|
+
# So need this rescue code
|
|
1147
|
+
$log.error("failed to reload config: #{e}")
|
|
1148
|
+
next
|
|
1149
|
+
end
|
|
1150
|
+
|
|
1151
|
+
@conf = conf
|
|
1152
|
+
end
|
|
1153
|
+
end
|
|
1154
|
+
|
|
1155
|
+
def dump_non_windows
|
|
1156
|
+
begin
|
|
1157
|
+
Sigdump.dump unless @finished
|
|
1158
|
+
rescue => e
|
|
1159
|
+
$log.error("failed to dump: #{e}")
|
|
1160
|
+
end
|
|
1161
|
+
end
|
|
1162
|
+
|
|
1163
|
+
def dump_windows
|
|
1164
|
+
Thread.new do
|
|
1165
|
+
begin
|
|
1166
|
+
FluentSigdump.dump_windows
|
|
1167
|
+
rescue => e
|
|
1168
|
+
$log.error("failed to dump: #{e}")
|
|
1169
|
+
end
|
|
1170
|
+
end
|
|
1171
|
+
end
|
|
1172
|
+
|
|
1173
|
+
def logging_with_console_output
|
|
1174
|
+
yield $log
|
|
1175
|
+
unless $log.stdout?
|
|
1176
|
+
logger = ServerEngine::DaemonLogger.new(STDOUT)
|
|
1177
|
+
log = Fluent::Log.new(logger)
|
|
1178
|
+
log.level = @system_config.log_level
|
|
1179
|
+
console = log.enable_debug
|
|
1180
|
+
yield console
|
|
1181
|
+
end
|
|
1182
|
+
end
|
|
1183
|
+
|
|
1184
|
+
def main_process(&block)
|
|
1185
|
+
if @system_config.process_name
|
|
1186
|
+
if @system_config.workers > 1
|
|
1187
|
+
Process.setproctitle("worker:#{@system_config.process_name}#{ENV['SERVERENGINE_WORKER_ID']}")
|
|
1188
|
+
else
|
|
1189
|
+
Process.setproctitle("worker:#{@system_config.process_name}")
|
|
1190
|
+
end
|
|
1191
|
+
end
|
|
1192
|
+
|
|
1193
|
+
unrecoverable_error = false
|
|
1194
|
+
|
|
1195
|
+
begin
|
|
1196
|
+
block.call
|
|
1197
|
+
rescue Fluent::ConfigError => e
|
|
1198
|
+
logging_with_console_output do |log|
|
|
1199
|
+
log.error "config error", file: @config_path, error: e
|
|
1200
|
+
log.debug_backtrace
|
|
1201
|
+
end
|
|
1202
|
+
unrecoverable_error = true
|
|
1203
|
+
rescue Fluent::UnrecoverableError => e
|
|
1204
|
+
logging_with_console_output do |log|
|
|
1205
|
+
log.error e.message, error: e
|
|
1206
|
+
log.error_backtrace
|
|
1207
|
+
end
|
|
1208
|
+
unrecoverable_error = true
|
|
1209
|
+
rescue ScriptError => e # LoadError, NotImplementedError, SyntaxError
|
|
1210
|
+
logging_with_console_output do |log|
|
|
1211
|
+
if e.respond_to?(:path)
|
|
1212
|
+
log.error e.message, path: e.path, error: e
|
|
1213
|
+
else
|
|
1214
|
+
log.error e.message, error: e
|
|
1215
|
+
end
|
|
1216
|
+
log.error_backtrace
|
|
1217
|
+
end
|
|
1218
|
+
unrecoverable_error = true
|
|
1219
|
+
rescue => e
|
|
1220
|
+
logging_with_console_output do |log|
|
|
1221
|
+
log.error "unexpected error", error: e
|
|
1222
|
+
log.error_backtrace
|
|
1223
|
+
end
|
|
1224
|
+
end
|
|
1225
|
+
|
|
1226
|
+
exit!(unrecoverable_error ? 2 : 1)
|
|
1227
|
+
end
|
|
1228
|
+
|
|
1229
|
+
def enable_ruby_jit
|
|
1230
|
+
unless defined?(RubyVM::YJIT) && RubyVM::YJIT.respond_to?(:enable)
|
|
1231
|
+
$log.info "Ruby JIT is not available on this Ruby"
|
|
1232
|
+
return
|
|
1233
|
+
end
|
|
1234
|
+
|
|
1235
|
+
if RubyVM::YJIT.enable
|
|
1236
|
+
$log.info "enabled Ruby JIT"
|
|
1237
|
+
else
|
|
1238
|
+
$log.warn "failed to enable Ruby JIT"
|
|
1239
|
+
end
|
|
1240
|
+
end
|
|
1241
|
+
|
|
1242
|
+
def build_system_config(conf)
|
|
1243
|
+
system_config = SystemConfig.create(conf, @cl_opt[:strict_config_value])
|
|
1244
|
+
# Prefer the options explicitly specified in the command line
|
|
1245
|
+
#
|
|
1246
|
+
# TODO: There is a bug that `system_config.log.rotate_age/rotate_size` are
|
|
1247
|
+
# not merged with the command line options since they are not in
|
|
1248
|
+
# `SYSTEM_CONFIG_PARAMETERS`.
|
|
1249
|
+
# We have to fix this bug.
|
|
1250
|
+
opt = {}
|
|
1251
|
+
Fluent::SystemConfig::SYSTEM_CONFIG_PARAMETERS.each do |param|
|
|
1252
|
+
if @cl_opt.key?(param) && !@cl_opt[param].nil?
|
|
1253
|
+
opt[param] = @cl_opt[param]
|
|
1254
|
+
end
|
|
1255
|
+
end
|
|
1256
|
+
system_config.overwrite_variables(**opt)
|
|
1257
|
+
system_config
|
|
1258
|
+
end
|
|
1259
|
+
|
|
1260
|
+
def build_additional_configurations(parsed_files)
|
|
1261
|
+
if @system_config.config_include_dir&.empty?
|
|
1262
|
+
$log.info :supervisor, 'configuration include directory is disabled'
|
|
1263
|
+
return
|
|
1264
|
+
end
|
|
1265
|
+
begin
|
|
1266
|
+
supported_suffixes = [".conf", ".yaml", ".yml"]
|
|
1267
|
+
Find.find(@system_config.config_include_dir) do |path|
|
|
1268
|
+
next if File.directory?(path)
|
|
1269
|
+
next unless supported_suffixes.include?(File.extname(path))
|
|
1270
|
+
# NOTE: both types of normal config (.conf) and YAML will be loaded.
|
|
1271
|
+
# Thus, it does not care whether @config_path is .conf or .yml.
|
|
1272
|
+
if parsed_files.include?(path)
|
|
1273
|
+
$log.info :supervisor, 'skip auto loading, it was already loaded', path: path
|
|
1274
|
+
next
|
|
1275
|
+
end
|
|
1276
|
+
|
|
1277
|
+
$log.info :supervisor, 'loading additional configuration file', path: path
|
|
1278
|
+
yield Fluent::Config.build(config_path: path,
|
|
1279
|
+
encoding: @conf_encoding,
|
|
1280
|
+
use_v1_config: @use_v1_config,
|
|
1281
|
+
type: :guess,
|
|
1282
|
+
on_file_parsed: nil)
|
|
1283
|
+
end
|
|
1284
|
+
rescue Errno::ENOENT
|
|
1285
|
+
$log.info :supervisor, 'inaccessible include directory was specified', path: @system_config.config_include_dir
|
|
1286
|
+
end
|
|
1287
|
+
end
|
|
1288
|
+
|
|
1289
|
+
RUBY_ENCODING_OPTIONS_REGEX = %r{\A(-E|--encoding=|--internal-encoding=|--external-encoding=)}.freeze
|
|
1290
|
+
|
|
1291
|
+
def build_spawn_command
|
|
1292
|
+
if ENV['TEST_RUBY_PATH']
|
|
1293
|
+
fluentd_spawn_cmd = [ENV['TEST_RUBY_PATH']]
|
|
1294
|
+
else
|
|
1295
|
+
fluentd_spawn_cmd = [ServerEngine.ruby_bin_path]
|
|
1296
|
+
end
|
|
1297
|
+
|
|
1298
|
+
rubyopt = ENV['RUBYOPT']
|
|
1299
|
+
if rubyopt
|
|
1300
|
+
encodes, others = rubyopt.split(' ').partition { |e| e.match?(RUBY_ENCODING_OPTIONS_REGEX) }
|
|
1301
|
+
fluentd_spawn_cmd.concat(others)
|
|
1302
|
+
|
|
1303
|
+
adopted_encodes = encodes.empty? ? ['-Eascii-8bit:ascii-8bit'] : encodes
|
|
1304
|
+
fluentd_spawn_cmd.concat(adopted_encodes)
|
|
1305
|
+
else
|
|
1306
|
+
fluentd_spawn_cmd << '-Eascii-8bit:ascii-8bit'
|
|
1307
|
+
end
|
|
1308
|
+
|
|
1309
|
+
# Adding `-h` so that it can avoid ruby's command blocking
|
|
1310
|
+
# e.g. `ruby -Eascii-8bit:ascii-8bit` will block. but `ruby -Eascii-8bit:ascii-8bit -h` won't.
|
|
1311
|
+
_, e, s = Open3.capture3(*fluentd_spawn_cmd, "-h")
|
|
1312
|
+
if s.exitstatus != 0
|
|
1313
|
+
$log.error('Invalid option is passed to RUBYOPT', command: fluentd_spawn_cmd, error: e)
|
|
1314
|
+
exit s.exitstatus
|
|
1315
|
+
end
|
|
1316
|
+
|
|
1317
|
+
fluentd_spawn_cmd << $0
|
|
1318
|
+
fluentd_spawn_cmd += $fluentdargv
|
|
1319
|
+
fluentd_spawn_cmd << '--under-supervisor'
|
|
1320
|
+
|
|
1321
|
+
fluentd_spawn_cmd
|
|
1322
|
+
end
|
|
1323
|
+
end
|
|
1324
|
+
|
|
1325
|
+
module FluentSigdump
|
|
1326
|
+
def self.dump_windows
|
|
1327
|
+
raise "[BUG] WindowsSigdump::dump is for Windows ONLY." unless Fluent.windows?
|
|
1328
|
+
|
|
1329
|
+
# Sigdump outputs under `/tmp` dir without `SIGDUMP_PATH` specified,
|
|
1330
|
+
# but `/tmp` dir may not exist on Windows by default.
|
|
1331
|
+
# So use the systemroot-temp-dir instead.
|
|
1332
|
+
dump_filepath = ENV['SIGDUMP_PATH'].nil? || ENV['SIGDUMP_PATH'].empty? \
|
|
1333
|
+
? "#{ENV['windir']}/Temp/fluentd-sigdump-#{Process.pid}.log"
|
|
1334
|
+
: get_path_with_pid(ENV['SIGDUMP_PATH'])
|
|
1335
|
+
|
|
1336
|
+
require 'sigdump'
|
|
1337
|
+
Sigdump.dump(dump_filepath)
|
|
1338
|
+
|
|
1339
|
+
$log.info "dump to #{dump_filepath}."
|
|
1340
|
+
end
|
|
1341
|
+
|
|
1342
|
+
def self.get_path_with_pid(raw_path)
|
|
1343
|
+
path = Pathname.new(raw_path)
|
|
1344
|
+
path.sub_ext("-#{Process.pid}#{path.extname}").to_s
|
|
1345
|
+
end
|
|
1346
|
+
end
|
|
1347
|
+
end
|