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,204 @@
|
|
|
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/input'
|
|
18
|
+
|
|
19
|
+
module Fluent::Plugin
|
|
20
|
+
class TailInput < Fluent::Plugin::Input
|
|
21
|
+
module GroupWatchParams
|
|
22
|
+
include Fluent::Configurable
|
|
23
|
+
|
|
24
|
+
DEFAULT_KEY = /.*/
|
|
25
|
+
DEFAULT_LIMIT = -1
|
|
26
|
+
REGEXP_JOIN = "_"
|
|
27
|
+
|
|
28
|
+
config_section :group, param_name: :group, required: false, multi: false do
|
|
29
|
+
desc 'Regex for extracting group\'s metadata'
|
|
30
|
+
config_param :pattern,
|
|
31
|
+
:regexp,
|
|
32
|
+
default: /^\/var\/log\/containers\/(?<podname>[a-z0-9]([-a-z0-9]*[a-z0-9])?(\/[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace>[^_]+)_(?<container>.+)-(?<docker_id>[a-z0-9]{64})\.log$/
|
|
33
|
+
|
|
34
|
+
desc 'Period of time in which the group_line_limit is applied'
|
|
35
|
+
config_param :rate_period, :time, default: 5
|
|
36
|
+
|
|
37
|
+
config_section :rule, param_name: :rule, required: true, multi: true do
|
|
38
|
+
desc 'Key-value pairs for grouping'
|
|
39
|
+
config_param :match, :hash, value_type: :regexp, default: { namespace: [DEFAULT_KEY], podname: [DEFAULT_KEY] }
|
|
40
|
+
desc 'Maximum number of log lines allowed per group over a period of rate_period'
|
|
41
|
+
config_param :limit, :integer, default: DEFAULT_LIMIT
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
module GroupWatch
|
|
47
|
+
def self.included(mod)
|
|
48
|
+
mod.include GroupWatchParams
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
attr_reader :group_watchers, :default_group_key
|
|
52
|
+
|
|
53
|
+
def initialize
|
|
54
|
+
super
|
|
55
|
+
@group_watchers = {}
|
|
56
|
+
@group_keys = nil
|
|
57
|
+
@default_group_key = nil
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def configure(conf)
|
|
61
|
+
super
|
|
62
|
+
|
|
63
|
+
unless @group.nil?
|
|
64
|
+
## Ensuring correct time period syntax
|
|
65
|
+
@group.rule.each { |rule|
|
|
66
|
+
raise "Metadata Group Limit >= DEFAULT_LIMIT" unless rule.limit >= GroupWatchParams::DEFAULT_LIMIT
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@group_keys = Regexp.compile(@group.pattern).named_captures.keys
|
|
70
|
+
@default_group_key = ([GroupWatchParams::DEFAULT_KEY] * @group_keys.length).join(GroupWatchParams::REGEXP_JOIN)
|
|
71
|
+
|
|
72
|
+
## Ensures that "specific" rules (with larger number of `rule.match` keys)
|
|
73
|
+
## have a higher priority against "generic" rules (with less number of `rule.match` keys).
|
|
74
|
+
## This will be helpful when a file satisfies more than one rule.
|
|
75
|
+
@group.rule.sort_by! { |rule| -rule.match.length() }
|
|
76
|
+
construct_groupwatchers
|
|
77
|
+
@group_watchers[@default_group_key] ||= GroupWatcher.new(@group.rate_period, GroupWatchParams::DEFAULT_LIMIT)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def add_path_to_group_watcher(path, watcher)
|
|
82
|
+
return nil if @group.nil?
|
|
83
|
+
group_watcher = find_group_from_metadata(path)
|
|
84
|
+
group_watcher.add(path, watcher)
|
|
85
|
+
group_watcher
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def construct_group_key(named_captures)
|
|
89
|
+
match_rule = []
|
|
90
|
+
@group_keys.each { |key|
|
|
91
|
+
match_rule.append(named_captures.fetch(key, GroupWatchParams::DEFAULT_KEY))
|
|
92
|
+
}
|
|
93
|
+
match_rule = match_rule.join(GroupWatchParams::REGEXP_JOIN)
|
|
94
|
+
|
|
95
|
+
match_rule
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def construct_groupwatchers
|
|
99
|
+
@group.rule.each { |rule|
|
|
100
|
+
match_rule = construct_group_key(rule.match)
|
|
101
|
+
@group_watchers[match_rule] ||= GroupWatcher.new(@group.rate_period, rule.limit)
|
|
102
|
+
}
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def find_group(metadata)
|
|
106
|
+
metadata_key = construct_group_key(metadata)
|
|
107
|
+
gw_key = @group_watchers.keys.find { |regexp| metadata_key.match?(regexp) && regexp != @default_group_key }
|
|
108
|
+
gw_key ||= @default_group_key
|
|
109
|
+
|
|
110
|
+
@group_watchers[gw_key]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def find_group_from_metadata(path)
|
|
114
|
+
begin
|
|
115
|
+
metadata = @group.pattern.match(path).named_captures
|
|
116
|
+
group_watcher = find_group(metadata)
|
|
117
|
+
rescue
|
|
118
|
+
log.warn "Cannot find group from metadata, Adding file in the default group"
|
|
119
|
+
group_watcher = @group_watchers[@default_group_key]
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
group_watcher
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class GroupWatcher
|
|
127
|
+
attr_accessor :current_paths, :limit, :number_lines_read, :start_reading_time, :rate_period
|
|
128
|
+
|
|
129
|
+
FileCounter = Struct.new(
|
|
130
|
+
:number_lines_read,
|
|
131
|
+
:start_reading_time,
|
|
132
|
+
:watchers,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
def initialize(rate_period = 60, limit = -1)
|
|
136
|
+
@current_paths = {}
|
|
137
|
+
@rate_period = rate_period
|
|
138
|
+
@limit = limit
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def add(path, watcher)
|
|
142
|
+
(@current_paths[path] ||= FileCounter.new(0, nil, Set.new)).watchers << watcher
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def include?(path)
|
|
146
|
+
@current_paths.key?(path)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def size
|
|
150
|
+
@current_paths.size
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def delete(path, watcher)
|
|
154
|
+
counter = @current_paths[path]
|
|
155
|
+
return unless counter
|
|
156
|
+
counter.watchers.delete(watcher)
|
|
157
|
+
@current_paths.delete(path) if counter.watchers.empty?
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def update_reading_time(path)
|
|
161
|
+
@current_paths[path].start_reading_time ||= Fluent::Clock.now
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def update_lines_read(path, value)
|
|
165
|
+
@current_paths[path].number_lines_read += value
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def reset_counter(path)
|
|
169
|
+
@current_paths[path].start_reading_time = nil
|
|
170
|
+
@current_paths[path].number_lines_read = 0
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def time_spent_reading(path)
|
|
174
|
+
Fluent::Clock.now - @current_paths[path].start_reading_time
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def limit_time_period_reached?(path)
|
|
178
|
+
time_spent_reading(path) < @rate_period
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def limit_lines_reached?(path)
|
|
182
|
+
return true unless include?(path)
|
|
183
|
+
return true if @limit == 0
|
|
184
|
+
|
|
185
|
+
return false if @limit < 0
|
|
186
|
+
# Give every path at least one line. With more paths than the limit, the integer division
|
|
187
|
+
# leaves no allotment, and a path that has not started reading yet has no start time to compare.
|
|
188
|
+
return false if @current_paths[path].number_lines_read < [@limit / size, 1].max
|
|
189
|
+
|
|
190
|
+
# update_reading_time(path)
|
|
191
|
+
if limit_time_period_reached?(path) # Exceeds limit
|
|
192
|
+
true
|
|
193
|
+
else # Does not exceed limit
|
|
194
|
+
reset_counter(path)
|
|
195
|
+
false
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def to_s
|
|
200
|
+
super + " current_paths: #{@current_paths} rate_period: #{@rate_period} limit: #{@limit}"
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
@@ -0,0 +1,391 @@
|
|
|
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/input'
|
|
18
|
+
require 'fluent/clock'
|
|
19
|
+
require 'fluent/file_wrapper'
|
|
20
|
+
|
|
21
|
+
module Fluent::Plugin
|
|
22
|
+
class TailInput < Fluent::Plugin::Input
|
|
23
|
+
class TailWatcher
|
|
24
|
+
class FIFO
|
|
25
|
+
def initialize(encoding, log, max_line_size=nil, encoding_to_convert=nil)
|
|
26
|
+
@buffer = ''.force_encoding(encoding)
|
|
27
|
+
@eol = "\n".encode(encoding).freeze
|
|
28
|
+
@encoding_to_convert = encoding_to_convert
|
|
29
|
+
@max_line_size = max_line_size
|
|
30
|
+
@skip_current_line = false
|
|
31
|
+
@skipping_current_line_bytesize = 0
|
|
32
|
+
@log = log
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
attr_reader :buffer, :max_line_size
|
|
36
|
+
|
|
37
|
+
def <<(chunk)
|
|
38
|
+
@buffer << chunk
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def convert(s)
|
|
42
|
+
if @encoding_to_convert
|
|
43
|
+
s.encode!(@encoding_to_convert)
|
|
44
|
+
else
|
|
45
|
+
s
|
|
46
|
+
end
|
|
47
|
+
rescue
|
|
48
|
+
s.encode!(@encoding_to_convert, :invalid => :replace, :undef => :replace)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def read_lines(lines)
|
|
52
|
+
idx = @buffer.index(@eol)
|
|
53
|
+
has_skipped_line = false
|
|
54
|
+
|
|
55
|
+
until idx.nil?
|
|
56
|
+
# Using freeze and slice is faster than slice!
|
|
57
|
+
# See https://github.com/fluent/fluentd/pull/2527
|
|
58
|
+
@buffer.freeze
|
|
59
|
+
slice_position = idx + 1
|
|
60
|
+
rbuf = @buffer.slice(0, slice_position)
|
|
61
|
+
@buffer = @buffer.slice(slice_position, @buffer.size - slice_position)
|
|
62
|
+
idx = @buffer.index(@eol)
|
|
63
|
+
|
|
64
|
+
is_long_line = @max_line_size && (
|
|
65
|
+
@skip_current_line || rbuf.bytesize > @max_line_size
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if is_long_line
|
|
69
|
+
@log.warn "received line length is longer than #{@max_line_size}"
|
|
70
|
+
if @skip_current_line
|
|
71
|
+
@log.debug("The continuing line is finished. Finally discarded data: ") { convert(rbuf).chomp }
|
|
72
|
+
else
|
|
73
|
+
@log.debug("skipped line: ") { convert(rbuf).chomp }
|
|
74
|
+
end
|
|
75
|
+
has_skipped_line = true
|
|
76
|
+
@skip_current_line = false
|
|
77
|
+
@skipping_current_line_bytesize = 0
|
|
78
|
+
next
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
lines << convert(rbuf)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
is_long_current_line = @max_line_size && (
|
|
85
|
+
@skip_current_line || @buffer.bytesize > @max_line_size
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if is_long_current_line
|
|
89
|
+
@log.debug(
|
|
90
|
+
"The continuing current line length is longer than #{@max_line_size}." +
|
|
91
|
+
" The received data will be discarded until this line is finished." +
|
|
92
|
+
" Discarded data: "
|
|
93
|
+
) { convert(@buffer).chomp }
|
|
94
|
+
@skip_current_line = true
|
|
95
|
+
@skipping_current_line_bytesize += @buffer.bytesize
|
|
96
|
+
@buffer.clear
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
return has_skipped_line
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def reading_bytesize
|
|
103
|
+
return @skipping_current_line_bytesize if @skip_current_line
|
|
104
|
+
@buffer.bytesize
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
class IOHandler
|
|
109
|
+
BYTES_TO_READ = 64 * 1024
|
|
110
|
+
SHUTDOWN_TIMEOUT = 5
|
|
111
|
+
ASYNC_PENDING = :async_pending
|
|
112
|
+
|
|
113
|
+
attr_accessor :shutdown_timeout
|
|
114
|
+
|
|
115
|
+
def initialize(watcher, path:, read_lines_limit:, read_bytes_limit_per_second:, max_line_size: nil, log:, open_on_every_update:, encoding: Encoding::ASCII_8BIT, encoding_to_convert: nil, metrics:, &receive_lines)
|
|
116
|
+
@watcher = watcher
|
|
117
|
+
@path = path
|
|
118
|
+
@read_lines_limit = read_lines_limit
|
|
119
|
+
@read_bytes_limit_per_second = read_bytes_limit_per_second
|
|
120
|
+
@receive_lines = receive_lines
|
|
121
|
+
@open_on_every_update = open_on_every_update
|
|
122
|
+
@encoding = encoding
|
|
123
|
+
@fifo = FIFO.new(encoding, log, max_line_size, encoding_to_convert)
|
|
124
|
+
@lines = []
|
|
125
|
+
@io = nil
|
|
126
|
+
@notify_mutex = Mutex.new
|
|
127
|
+
@log = log
|
|
128
|
+
@start_reading_time = nil
|
|
129
|
+
@number_bytes_read = 0
|
|
130
|
+
@shutdown_start_time = nil
|
|
131
|
+
@shutdown_timeout = SHUTDOWN_TIMEOUT
|
|
132
|
+
@shutdown_mutex = Mutex.new
|
|
133
|
+
@eof = false
|
|
134
|
+
@metrics = metrics
|
|
135
|
+
@async_pending = false
|
|
136
|
+
@notify_pending = false
|
|
137
|
+
@pending_position = nil
|
|
138
|
+
@pending_read_more = false
|
|
139
|
+
|
|
140
|
+
@log.info "following tail of #{@path}"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def group_watcher
|
|
144
|
+
@watcher.group_watcher
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def on_notify
|
|
148
|
+
@notify_mutex.synchronize { handle_notify }
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def ready_to_shutdown(shutdown_start_time = nil)
|
|
152
|
+
@shutdown_mutex.synchronize {
|
|
153
|
+
@shutdown_start_time =
|
|
154
|
+
shutdown_start_time || Fluent::Clock.now
|
|
155
|
+
}
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def close
|
|
159
|
+
if @io && !@io.closed?
|
|
160
|
+
@io.close
|
|
161
|
+
@io = nil
|
|
162
|
+
@metrics.closed.inc
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def opened?
|
|
167
|
+
!!@io
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def eof?
|
|
171
|
+
@eof
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def drained?
|
|
175
|
+
@eof && @lines.empty? && !@async_pending
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def pending?
|
|
179
|
+
@async_pending
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Completes a receive callback that returned ASYNC_PENDING. The caller
|
|
183
|
+
# must invoke TailWatcher#on_notify when this returns true.
|
|
184
|
+
def complete_async(success)
|
|
185
|
+
@notify_mutex.synchronize do
|
|
186
|
+
raise 'no asynchronous receive is pending' unless @async_pending
|
|
187
|
+
|
|
188
|
+
begin
|
|
189
|
+
if success
|
|
190
|
+
@watcher.pe.update_pos(@pending_position)
|
|
191
|
+
@lines.clear
|
|
192
|
+
end
|
|
193
|
+
should_notify = (success && @pending_read_more) || @notify_pending
|
|
194
|
+
@pending_read_more = false if success
|
|
195
|
+
should_notify
|
|
196
|
+
rescue => error
|
|
197
|
+
@log.error error.to_s
|
|
198
|
+
@log.error_backtrace
|
|
199
|
+
@notify_pending
|
|
200
|
+
ensure
|
|
201
|
+
@async_pending = false
|
|
202
|
+
@notify_pending = false
|
|
203
|
+
@pending_position = nil
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
private
|
|
209
|
+
|
|
210
|
+
def limit_bytes_per_second_reached?
|
|
211
|
+
return false if @read_bytes_limit_per_second < 0 # not enabled by conf
|
|
212
|
+
return false if @number_bytes_read < @read_bytes_limit_per_second
|
|
213
|
+
|
|
214
|
+
@start_reading_time ||= Fluent::Clock.now
|
|
215
|
+
time_spent_reading = Fluent::Clock.now - @start_reading_time
|
|
216
|
+
@log.debug("time_spent_reading: #{time_spent_reading} #{ @watcher.path}")
|
|
217
|
+
|
|
218
|
+
if time_spent_reading < 1
|
|
219
|
+
true
|
|
220
|
+
else
|
|
221
|
+
@start_reading_time = nil
|
|
222
|
+
@number_bytes_read = 0
|
|
223
|
+
false
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def should_shutdown_now?
|
|
228
|
+
# Ensure to read all remaining lines, but abort immediately if it
|
|
229
|
+
# seems to take too long time.
|
|
230
|
+
@shutdown_mutex.synchronize {
|
|
231
|
+
return false if @shutdown_start_time.nil?
|
|
232
|
+
return Fluent::Clock.now - @shutdown_start_time > @shutdown_timeout
|
|
233
|
+
}
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def handle_notify
|
|
237
|
+
if @async_pending
|
|
238
|
+
@notify_pending = true
|
|
239
|
+
return
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# A notification may arrive while a rejected batch is waiting for capacity.
|
|
243
|
+
@pending_read_more = true unless @lines.empty?
|
|
244
|
+
|
|
245
|
+
if limit_bytes_per_second_reached? || group_watcher&.limit_lines_reached?(@path)
|
|
246
|
+
@metrics.throttled.inc
|
|
247
|
+
return
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
with_io do |io|
|
|
251
|
+
iobuf = ''.force_encoding(@encoding)
|
|
252
|
+
begin
|
|
253
|
+
read_more = false
|
|
254
|
+
has_skipped_line = false
|
|
255
|
+
|
|
256
|
+
if !io.nil? && @lines.empty?
|
|
257
|
+
begin
|
|
258
|
+
while true
|
|
259
|
+
@start_reading_time ||= Fluent::Clock.now
|
|
260
|
+
group_watcher&.update_reading_time(@path)
|
|
261
|
+
|
|
262
|
+
data = io.readpartial(BYTES_TO_READ, iobuf)
|
|
263
|
+
@eof = false
|
|
264
|
+
@number_bytes_read += data.bytesize
|
|
265
|
+
@fifo << data
|
|
266
|
+
|
|
267
|
+
n_lines_before_read = @lines.size
|
|
268
|
+
has_skipped_line = @fifo.read_lines(@lines) || has_skipped_line
|
|
269
|
+
group_watcher&.update_lines_read(@path, @lines.size - n_lines_before_read)
|
|
270
|
+
|
|
271
|
+
group_watcher_limit = group_watcher&.limit_lines_reached?(@path)
|
|
272
|
+
@log.debug "Reading Limit exceeded #{@path} #{group_watcher.number_lines_read}" if group_watcher_limit
|
|
273
|
+
|
|
274
|
+
if group_watcher_limit || limit_bytes_per_second_reached? || should_shutdown_now?
|
|
275
|
+
# Just get out from tailing loop.
|
|
276
|
+
@metrics.throttled.inc if group_watcher_limit || limit_bytes_per_second_reached?
|
|
277
|
+
read_more = false
|
|
278
|
+
break
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
if @lines.size >= @read_lines_limit
|
|
282
|
+
# not to use too much memory in case the file is very large
|
|
283
|
+
read_more = true
|
|
284
|
+
break
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
rescue EOFError
|
|
288
|
+
@eof = true
|
|
289
|
+
ensure
|
|
290
|
+
iobuf.clear
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
if @lines.empty?
|
|
295
|
+
@watcher.pe.update_pos(io.pos - @fifo.reading_bytesize) if has_skipped_line
|
|
296
|
+
else
|
|
297
|
+
received = @receive_lines.call(@lines, @watcher)
|
|
298
|
+
if received == ASYNC_PENDING
|
|
299
|
+
@pending_position = io.pos - @fifo.reading_bytesize
|
|
300
|
+
@pending_read_more ||= read_more
|
|
301
|
+
@async_pending = true
|
|
302
|
+
read_more = false
|
|
303
|
+
elsif received
|
|
304
|
+
@watcher.pe.update_pos(io.pos - @fifo.reading_bytesize)
|
|
305
|
+
@lines.clear
|
|
306
|
+
@pending_read_more = false
|
|
307
|
+
else
|
|
308
|
+
# A rejected worker submission must retain the continuation for retry.
|
|
309
|
+
@pending_read_more ||= read_more
|
|
310
|
+
read_more = false
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
end while read_more
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def open
|
|
318
|
+
io = Fluent::FileWrapper.open(@path)
|
|
319
|
+
io.seek(@watcher.pe.read_pos + @fifo.reading_bytesize)
|
|
320
|
+
@metrics.opened.inc
|
|
321
|
+
io
|
|
322
|
+
rescue RangeError
|
|
323
|
+
io.close if io
|
|
324
|
+
raise WatcherSetupError, "seek error with #{@path}: file position = #{@watcher.pe.read_pos.to_s(16)}, reading bytesize = #{@fifo.reading_bytesize.to_s(16)}"
|
|
325
|
+
rescue Errno::EACCES => e
|
|
326
|
+
@log.warn "#{e}"
|
|
327
|
+
nil
|
|
328
|
+
rescue Errno::ENOENT
|
|
329
|
+
nil
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def with_io
|
|
333
|
+
if @open_on_every_update
|
|
334
|
+
io = open
|
|
335
|
+
begin
|
|
336
|
+
yield io
|
|
337
|
+
ensure
|
|
338
|
+
io.close unless io.nil?
|
|
339
|
+
end
|
|
340
|
+
else
|
|
341
|
+
@io ||= open
|
|
342
|
+
yield @io
|
|
343
|
+
@eof = true if @io.nil?
|
|
344
|
+
end
|
|
345
|
+
rescue WatcherSetupError => e
|
|
346
|
+
close
|
|
347
|
+
@eof = true
|
|
348
|
+
raise e
|
|
349
|
+
rescue
|
|
350
|
+
@log.error $!.to_s
|
|
351
|
+
@log.error_backtrace
|
|
352
|
+
close
|
|
353
|
+
@eof = true
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
class NullIOHandler
|
|
358
|
+
def initialize
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def ready_to_shutdown(shutdown_start_time = nil)
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def io
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def on_notify
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def close
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def opened?
|
|
374
|
+
false
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def eof?
|
|
378
|
+
true
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def drained?
|
|
382
|
+
true
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def pending?
|
|
386
|
+
false
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
end
|