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,87 @@
|
|
|
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/extractor'
|
|
18
|
+
require 'stringio'
|
|
19
|
+
require 'zlib'
|
|
20
|
+
require 'zstd-ruby'
|
|
21
|
+
|
|
22
|
+
module Fluent
|
|
23
|
+
module Plugin
|
|
24
|
+
module Compressable
|
|
25
|
+
DEFAULT_DECOMPRESSION_SIZE_LIMIT = 256 * 1024 * 1024
|
|
26
|
+
|
|
27
|
+
def compress(data, type: :gzip, **kwargs)
|
|
28
|
+
output_io = kwargs[:output_io]
|
|
29
|
+
io = output_io || StringIO.new
|
|
30
|
+
if type == :gzip
|
|
31
|
+
writer = Zlib::GzipWriter.new(io)
|
|
32
|
+
elsif type == :zstd
|
|
33
|
+
writer = Zstd::StreamWriter.new(io)
|
|
34
|
+
else
|
|
35
|
+
raise ArgumentError, "Unknown compression type: #{type}"
|
|
36
|
+
end
|
|
37
|
+
writer.write(data)
|
|
38
|
+
writer.finish
|
|
39
|
+
output_io || io.string
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# compressed_data is String like `compress(data1) + compress(data2) + ... + compress(dataN)`
|
|
43
|
+
# https://www.ruby-forum.com/topic/971591#979503
|
|
44
|
+
def decompress(compressed_data = nil, output_io: nil, input_io: nil, type: :gzip)
|
|
45
|
+
case
|
|
46
|
+
when input_io && output_io
|
|
47
|
+
io_decompress(input_io, output_io, type)
|
|
48
|
+
when input_io
|
|
49
|
+
output_io = StringIO.new
|
|
50
|
+
io = io_decompress(input_io, output_io, type)
|
|
51
|
+
io.string
|
|
52
|
+
when compressed_data.nil? || compressed_data.empty?
|
|
53
|
+
# check compressed_data(String) is 0 length
|
|
54
|
+
compressed_data
|
|
55
|
+
when output_io
|
|
56
|
+
# execute after checking compressed_data is empty or not
|
|
57
|
+
io = StringIO.new(compressed_data)
|
|
58
|
+
io_decompress(io, output_io, type)
|
|
59
|
+
else
|
|
60
|
+
string_decompress(compressed_data, type)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def string_decompress(compressed_data, type = :gzip)
|
|
67
|
+
if type == :gzip
|
|
68
|
+
Extractor.decompress_gzip(compressed_data, limit: @decompression_size_limit || DEFAULT_DECOMPRESSION_SIZE_LIMIT)
|
|
69
|
+
elsif type == :zstd
|
|
70
|
+
Extractor.decompress_zstd(compressed_data, limit: @decompression_size_limit || DEFAULT_DECOMPRESSION_SIZE_LIMIT)
|
|
71
|
+
else
|
|
72
|
+
raise ArgumentError, "Unknown compression type: #{type}"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def io_decompress(input, output, type = :gzip)
|
|
77
|
+
if type == :gzip
|
|
78
|
+
Extractor.io_decompress_gzip(input, output, limit: @decompression_size_limit || DEFAULT_DECOMPRESSION_SIZE_LIMIT)
|
|
79
|
+
elsif type == :zstd
|
|
80
|
+
Extractor.io_decompress_zstd(input, output, limit: @decompression_size_limit || DEFAULT_DECOMPRESSION_SIZE_LIMIT)
|
|
81
|
+
else
|
|
82
|
+
raise ArgumentError, "Unknown compression type: #{type}"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
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/compat/exec_util'
|
|
18
|
+
|
|
19
|
+
module Fluent
|
|
20
|
+
# obsolete
|
|
21
|
+
ExecUtil = Fluent::Compat::ExecUtil
|
|
22
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
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 'stringio'
|
|
18
|
+
require 'zlib'
|
|
19
|
+
require 'zstd-ruby'
|
|
20
|
+
require 'fluent/error'
|
|
21
|
+
|
|
22
|
+
module Fluent
|
|
23
|
+
module Plugin
|
|
24
|
+
module Extractor
|
|
25
|
+
class SizeLimitError < UnrecoverableError; end
|
|
26
|
+
|
|
27
|
+
BYTES_TO_READ = 64 * 1024
|
|
28
|
+
INFLATE_BYTES_TO_READ = 1024
|
|
29
|
+
# Zstd::StreamReader#read takes a number of compressed bytes, unlike
|
|
30
|
+
# Zlib::GzipReader#read which takes decompressed bytes
|
|
31
|
+
ZSTD_BYTES_TO_READ = 1024
|
|
32
|
+
|
|
33
|
+
def self.decompress_gzip(compressed_data, limit:)
|
|
34
|
+
io = StringIO.new(compressed_data)
|
|
35
|
+
out = ''
|
|
36
|
+
loop do
|
|
37
|
+
reader = Zlib::GzipReader.new(io)
|
|
38
|
+
while (chunk = reader.read(BYTES_TO_READ))
|
|
39
|
+
out << chunk
|
|
40
|
+
if out.bytesize > limit
|
|
41
|
+
raise SizeLimitError, "Decompressed data exceeds limit of #{limit} bytes"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
unused = reader.unused
|
|
46
|
+
reader.finish
|
|
47
|
+
unless unused.nil?
|
|
48
|
+
adjust = unused.length
|
|
49
|
+
io.pos -= adjust
|
|
50
|
+
end
|
|
51
|
+
break if io.eof?
|
|
52
|
+
end
|
|
53
|
+
out
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.decompress_zstd(compressed_data, limit:)
|
|
57
|
+
io = StringIO.new(compressed_data)
|
|
58
|
+
reader = Zstd::StreamReader.new(io)
|
|
59
|
+
out = ''
|
|
60
|
+
loop do
|
|
61
|
+
out << reader.read(ZSTD_BYTES_TO_READ)
|
|
62
|
+
if out.bytesize > limit
|
|
63
|
+
raise SizeLimitError, "Decompressed data exceeds limit of #{limit} bytes"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Zstd::StreamReader doesn't provide unused data, so we have to manually adjust the position
|
|
67
|
+
break if io.eof?
|
|
68
|
+
end
|
|
69
|
+
out
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.decompress_deflate(compressed_data, limit:)
|
|
73
|
+
io = StringIO.new(compressed_data)
|
|
74
|
+
out = ''
|
|
75
|
+
begin
|
|
76
|
+
zstream = Zlib::Inflate.new
|
|
77
|
+
while (chunk = io.read(INFLATE_BYTES_TO_READ))
|
|
78
|
+
out << zstream.inflate(chunk)
|
|
79
|
+
if out.bytesize > limit
|
|
80
|
+
raise SizeLimitError, "Decompressed data exceeds limit of #{limit} bytes"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
out << zstream.finish
|
|
84
|
+
if out.bytesize > limit
|
|
85
|
+
raise SizeLimitError, "Decompressed data exceeds limit of #{limit} bytes"
|
|
86
|
+
end
|
|
87
|
+
ensure
|
|
88
|
+
zstream&.close
|
|
89
|
+
end
|
|
90
|
+
out
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def self.io_decompress_gzip(input, output, limit:)
|
|
94
|
+
size = 0
|
|
95
|
+
loop do
|
|
96
|
+
reader = Zlib::GzipReader.new(input)
|
|
97
|
+
while (chunk = reader.read(BYTES_TO_READ))
|
|
98
|
+
size += chunk.bytesize
|
|
99
|
+
if size > limit
|
|
100
|
+
raise SizeLimitError, "Decompressed data exceeds limit of #{limit} bytes"
|
|
101
|
+
end
|
|
102
|
+
output.write(chunk)
|
|
103
|
+
end
|
|
104
|
+
unused = reader.unused
|
|
105
|
+
reader.finish
|
|
106
|
+
unless unused.nil?
|
|
107
|
+
adjust = unused.length
|
|
108
|
+
input.pos -= adjust
|
|
109
|
+
end
|
|
110
|
+
break if input.eof?
|
|
111
|
+
end
|
|
112
|
+
output
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def self.io_decompress_zstd(input, output, limit:)
|
|
116
|
+
reader = Zstd::StreamReader.new(input)
|
|
117
|
+
size = 0
|
|
118
|
+
loop do
|
|
119
|
+
chunk = reader.read(ZSTD_BYTES_TO_READ)
|
|
120
|
+
size += chunk.bytesize
|
|
121
|
+
if size > limit
|
|
122
|
+
raise SizeLimitError, "Decompressed data exceeds limit of #{limit} bytes"
|
|
123
|
+
end
|
|
124
|
+
output.write(chunk)
|
|
125
|
+
# Zstd::StreamReader doesn't provide unused data, so we have to manually adjust the position
|
|
126
|
+
break if input.eof?
|
|
127
|
+
end
|
|
128
|
+
output
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
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/compat/file_util'
|
|
18
|
+
|
|
19
|
+
module Fluent
|
|
20
|
+
# obsolete
|
|
21
|
+
FileUtil = Fluent::Compat::FileUtil
|
|
22
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
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/base'
|
|
18
|
+
|
|
19
|
+
require 'fluent/event'
|
|
20
|
+
require 'fluent/log'
|
|
21
|
+
require 'fluent/plugin_id'
|
|
22
|
+
require 'fluent/plugin_helper'
|
|
23
|
+
|
|
24
|
+
module Fluent
|
|
25
|
+
module Plugin
|
|
26
|
+
class Filter < Base
|
|
27
|
+
include PluginId
|
|
28
|
+
include PluginLoggerMixin
|
|
29
|
+
include PluginHelper::Mixin
|
|
30
|
+
|
|
31
|
+
helpers_internal :event_emitter, :metrics
|
|
32
|
+
|
|
33
|
+
attr_reader :has_filter_with_time
|
|
34
|
+
|
|
35
|
+
def initialize
|
|
36
|
+
super
|
|
37
|
+
@has_filter_with_time = has_filter_with_time?
|
|
38
|
+
@emit_records_metrics = nil
|
|
39
|
+
@emit_size_metrics = nil
|
|
40
|
+
@counter_mutex = Mutex.new
|
|
41
|
+
@enable_size_metrics = false
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def configure(conf)
|
|
45
|
+
super
|
|
46
|
+
|
|
47
|
+
@emit_records_metrics = metrics_create(namespace: "fluentd", subsystem: "filter", name: "emit_records", help_text: "Number of count emit records")
|
|
48
|
+
@emit_size_metrics = metrics_create(namespace: "fluentd", subsystem: "filter", name: "emit_size", help_text: "Total size of emit events")
|
|
49
|
+
@enable_size_metrics = !!system_config.enable_size_metrics
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def statistics
|
|
53
|
+
stats = {
|
|
54
|
+
'emit_records' => @emit_records_metrics.get,
|
|
55
|
+
'emit_size' => @emit_size_metrics.get,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
{ 'filter' => stats }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def measure_metrics(es)
|
|
62
|
+
@emit_records_metrics.add(es.size)
|
|
63
|
+
@emit_size_metrics.add(es.to_msgpack_stream.bytesize) if @enable_size_metrics
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def filter(tag, time, record)
|
|
67
|
+
raise NotImplementedError, "BUG: filter plugins MUST implement this method"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def filter_with_time(tag, time, record)
|
|
71
|
+
raise NotImplementedError, "BUG: filter plugins MUST implement this method"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def filter_stream(tag, es)
|
|
75
|
+
new_es = MultiEventStream.new
|
|
76
|
+
if @has_filter_with_time
|
|
77
|
+
es.each do |time, record|
|
|
78
|
+
begin
|
|
79
|
+
filtered_time, filtered_record = filter_with_time(tag, time, record)
|
|
80
|
+
new_es.add(filtered_time, filtered_record) if filtered_time && filtered_record
|
|
81
|
+
rescue => e
|
|
82
|
+
router.emit_error_event(tag, time, record, e)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
else
|
|
86
|
+
es.each do |time, record|
|
|
87
|
+
begin
|
|
88
|
+
filtered_record = filter(tag, time, record)
|
|
89
|
+
new_es.add(time, filtered_record) if filtered_record
|
|
90
|
+
rescue => e
|
|
91
|
+
router.emit_error_event(tag, time, record, e)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
new_es
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def has_filter_with_time?
|
|
101
|
+
implmented_methods = self.class.instance_methods(false)
|
|
102
|
+
# Plugins that override `filter_stream` don't need check,
|
|
103
|
+
# because they may not call `filter` or `filter_with_time`
|
|
104
|
+
# for example fluentd/lib/fluent/plugin/filter_record_transformer.rb
|
|
105
|
+
return nil if implmented_methods.include?(:filter_stream)
|
|
106
|
+
case
|
|
107
|
+
when [:filter, :filter_with_time].all? { |e| implmented_methods.include?(e) }
|
|
108
|
+
raise "BUG: Filter plugins MUST implement either `filter` or `filter_with_time`"
|
|
109
|
+
when implmented_methods.include?(:filter)
|
|
110
|
+
false
|
|
111
|
+
when implmented_methods.include?(:filter_with_time)
|
|
112
|
+
true
|
|
113
|
+
else
|
|
114
|
+
raise NotImplementedError, "BUG: Filter plugins MUST implement either `filter` or `filter_with_time`"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,189 @@
|
|
|
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/filter'
|
|
18
|
+
require 'fluent/config/error'
|
|
19
|
+
require 'fluent/plugin/string_util'
|
|
20
|
+
|
|
21
|
+
module Fluent::Plugin
|
|
22
|
+
class GrepFilter < Filter
|
|
23
|
+
Fluent::Plugin.register_filter('grep', self)
|
|
24
|
+
|
|
25
|
+
def initialize
|
|
26
|
+
super
|
|
27
|
+
|
|
28
|
+
@_regexp_and_conditions = nil
|
|
29
|
+
@_exclude_and_conditions = nil
|
|
30
|
+
@_regexp_or_conditions = nil
|
|
31
|
+
@_exclude_or_conditions = nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# for test
|
|
35
|
+
attr_reader :_regexp_and_conditions, :_exclude_and_conditions, :_regexp_or_conditions, :_exclude_or_conditions
|
|
36
|
+
|
|
37
|
+
helpers :record_accessor
|
|
38
|
+
|
|
39
|
+
REGEXP_MAX_NUM = 20
|
|
40
|
+
|
|
41
|
+
(1..REGEXP_MAX_NUM).each {|i| config_param :"regexp#{i}", :string, default: nil, deprecated: "Use <regexp> section" }
|
|
42
|
+
(1..REGEXP_MAX_NUM).each {|i| config_param :"exclude#{i}", :string, default: nil, deprecated: "Use <exclude> section" }
|
|
43
|
+
|
|
44
|
+
config_section :regexp, param_name: :regexps, multi: true do
|
|
45
|
+
desc "The field name to which the regular expression is applied."
|
|
46
|
+
config_param :key, :string
|
|
47
|
+
desc "The regular expression."
|
|
48
|
+
config_param :pattern, :regexp
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
config_section :exclude, param_name: :excludes, multi: true do
|
|
52
|
+
desc "The field name to which the regular expression is applied."
|
|
53
|
+
config_param :key, :string
|
|
54
|
+
desc "The regular expression."
|
|
55
|
+
config_param :pattern, :regexp
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
config_section :and, param_name: :and_conditions, multi: true do
|
|
59
|
+
config_section :regexp, param_name: :regexps, multi: true do
|
|
60
|
+
desc "The field name to which the regular expression is applied."
|
|
61
|
+
config_param :key, :string
|
|
62
|
+
desc "The regular expression."
|
|
63
|
+
config_param :pattern, :regexp
|
|
64
|
+
end
|
|
65
|
+
config_section :exclude, param_name: :excludes, multi: true do
|
|
66
|
+
desc "The field name to which the regular expression is applied."
|
|
67
|
+
config_param :key, :string
|
|
68
|
+
desc "The regular expression."
|
|
69
|
+
config_param :pattern, :regexp
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
config_section :or, param_name: :or_conditions, multi: true do
|
|
74
|
+
config_section :regexp, param_name: :regexps, multi: true do
|
|
75
|
+
desc "The field name to which the regular expression is applied."
|
|
76
|
+
config_param :key, :string
|
|
77
|
+
desc "The regular expression."
|
|
78
|
+
config_param :pattern, :regexp
|
|
79
|
+
end
|
|
80
|
+
config_section :exclude, param_name: :excludes, multi: true do
|
|
81
|
+
desc "The field name to which the regular expression is applied."
|
|
82
|
+
config_param :key, :string
|
|
83
|
+
desc "The regular expression."
|
|
84
|
+
config_param :pattern, :regexp
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def configure(conf)
|
|
89
|
+
super
|
|
90
|
+
|
|
91
|
+
regexp_and_conditions = {}
|
|
92
|
+
regexp_or_conditions = {}
|
|
93
|
+
exclude_and_conditions = {}
|
|
94
|
+
exclude_or_conditions = {}
|
|
95
|
+
|
|
96
|
+
(1..REGEXP_MAX_NUM).each do |i|
|
|
97
|
+
next unless conf["regexp#{i}"]
|
|
98
|
+
key, regexp = conf["regexp#{i}"].split(/ /, 2)
|
|
99
|
+
raise Fluent::ConfigError, "regexp#{i} does not contain 2 parameters" unless regexp
|
|
100
|
+
raise Fluent::ConfigError, "regexp#{i} contains a duplicated key, #{key}" if regexp_and_conditions[key]
|
|
101
|
+
regexp_and_conditions[key] = Expression.new(record_accessor_create(key), Regexp.compile(regexp))
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
(1..REGEXP_MAX_NUM).each do |i|
|
|
105
|
+
next unless conf["exclude#{i}"]
|
|
106
|
+
key, exclude = conf["exclude#{i}"].split(/ /, 2)
|
|
107
|
+
raise Fluent::ConfigError, "exclude#{i} does not contain 2 parameters" unless exclude
|
|
108
|
+
raise Fluent::ConfigError, "exclude#{i} contains a duplicated key, #{key}" if exclude_or_conditions[key]
|
|
109
|
+
exclude_or_conditions[key] = Expression.new(record_accessor_create(key), Regexp.compile(exclude))
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
if @regexps.size > 1
|
|
113
|
+
log.info "Top level multiple <regexp> is interpreted as 'and' condition"
|
|
114
|
+
end
|
|
115
|
+
@regexps.each do |e|
|
|
116
|
+
raise Fluent::ConfigError, "Duplicate key: #{e.key}" if regexp_and_conditions.key?(e.key)
|
|
117
|
+
regexp_and_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
if @excludes.size > 1
|
|
121
|
+
log.info "Top level multiple <exclude> is interpreted as 'or' condition"
|
|
122
|
+
end
|
|
123
|
+
@excludes.each do |e|
|
|
124
|
+
raise Fluent::ConfigError, "Duplicate key: #{e.key}" if exclude_or_conditions.key?(e.key)
|
|
125
|
+
exclude_or_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
@and_conditions.each do |and_condition|
|
|
129
|
+
if !and_condition.regexps.empty? && !and_condition.excludes.empty?
|
|
130
|
+
raise Fluent::ConfigError, "Do not specify both <regexp> and <exclude> in <and>"
|
|
131
|
+
end
|
|
132
|
+
and_condition.regexps.each do |e|
|
|
133
|
+
raise Fluent::ConfigError, "Duplicate key in <and>: #{e.key}" if regexp_and_conditions.key?(e.key)
|
|
134
|
+
regexp_and_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
|
135
|
+
end
|
|
136
|
+
and_condition.excludes.each do |e|
|
|
137
|
+
raise Fluent::ConfigError, "Duplicate key in <and>: #{e.key}" if exclude_and_conditions.key?(e.key)
|
|
138
|
+
exclude_and_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
@or_conditions.each do |or_condition|
|
|
143
|
+
if !or_condition.regexps.empty? && !or_condition.excludes.empty?
|
|
144
|
+
raise Fluent::ConfigError, "Do not specify both <regexp> and <exclude> in <or>"
|
|
145
|
+
end
|
|
146
|
+
or_condition.regexps.each do |e|
|
|
147
|
+
raise Fluent::ConfigError, "Duplicate key in <or>: #{e.key}" if regexp_or_conditions.key?(e.key)
|
|
148
|
+
regexp_or_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
|
149
|
+
end
|
|
150
|
+
or_condition.excludes.each do |e|
|
|
151
|
+
raise Fluent::ConfigError, "Duplicate key in <or>: #{e.key}" if exclude_or_conditions.key?(e.key)
|
|
152
|
+
exclude_or_conditions[e.key] = Expression.new(record_accessor_create(e.key), e.pattern)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
@_regexp_and_conditions = regexp_and_conditions.values unless regexp_and_conditions.empty?
|
|
157
|
+
@_exclude_and_conditions = exclude_and_conditions.values unless exclude_and_conditions.empty?
|
|
158
|
+
@_regexp_or_conditions = regexp_or_conditions.values unless regexp_or_conditions.empty?
|
|
159
|
+
@_exclude_or_conditions = exclude_or_conditions.values unless exclude_or_conditions.empty?
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def filter(tag, time, record)
|
|
163
|
+
begin
|
|
164
|
+
if @_regexp_and_conditions && @_regexp_and_conditions.any? { |expression| !expression.match?(record) }
|
|
165
|
+
return nil
|
|
166
|
+
end
|
|
167
|
+
if @_regexp_or_conditions && @_regexp_or_conditions.none? { |expression| expression.match?(record) }
|
|
168
|
+
return nil
|
|
169
|
+
end
|
|
170
|
+
if @_exclude_and_conditions && @_exclude_and_conditions.all? { |expression| expression.match?(record) }
|
|
171
|
+
return nil
|
|
172
|
+
end
|
|
173
|
+
if @_exclude_or_conditions && @_exclude_or_conditions.any? { |expression| expression.match?(record) }
|
|
174
|
+
return nil
|
|
175
|
+
end
|
|
176
|
+
rescue => e
|
|
177
|
+
log.warn "failed to grep events", error: e
|
|
178
|
+
log.warn_backtrace
|
|
179
|
+
end
|
|
180
|
+
record
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
Expression = Struct.new(:key, :pattern) do
|
|
184
|
+
def match?(record)
|
|
185
|
+
::Fluent::StringUtil.match_regexp(pattern, key.call(record).to_s)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Fluentd
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#
|
|
16
|
+
|
|
17
|
+
require 'fluent/time'
|
|
18
|
+
require 'fluent/config/error'
|
|
19
|
+
require 'fluent/plugin/filter'
|
|
20
|
+
require 'fluent/plugin_helper/parser'
|
|
21
|
+
require 'fluent/plugin_helper/compat_parameters'
|
|
22
|
+
|
|
23
|
+
module Fluent::Plugin
|
|
24
|
+
class ParserFilter < Filter
|
|
25
|
+
Fluent::Plugin.register_filter('parser', self)
|
|
26
|
+
|
|
27
|
+
helpers :parser, :record_accessor, :compat_parameters
|
|
28
|
+
|
|
29
|
+
desc 'Specify field name in the record to parse.'
|
|
30
|
+
config_param :key_name, :string
|
|
31
|
+
desc 'Keep original key-value pair in parsed result.'
|
|
32
|
+
config_param :reserve_data, :bool, default: false
|
|
33
|
+
desc 'Keep original event time in parsed result.'
|
|
34
|
+
config_param :reserve_time, :bool, default: false
|
|
35
|
+
desc 'Remove "key_name" field from the record when parsing is succeeded'
|
|
36
|
+
config_param :remove_key_name_field, :bool, default: false
|
|
37
|
+
desc 'Store parsed values with specified key name prefix.'
|
|
38
|
+
config_param :inject_key_prefix, :string, default: nil
|
|
39
|
+
desc 'If true, invalid string is replaced with safe characters and re-parse it.'
|
|
40
|
+
config_param :replace_invalid_sequence, :bool, default: false
|
|
41
|
+
desc 'Store parsed values as a hash value in a field.'
|
|
42
|
+
config_param :hash_value_field, :string, default: nil
|
|
43
|
+
desc 'Emit invalid record to @ERROR label'
|
|
44
|
+
config_param :emit_invalid_record_to_error, :bool, default: true
|
|
45
|
+
|
|
46
|
+
attr_reader :parser
|
|
47
|
+
|
|
48
|
+
def configure(conf)
|
|
49
|
+
compat_parameters_convert(conf, :parser)
|
|
50
|
+
|
|
51
|
+
super
|
|
52
|
+
|
|
53
|
+
@accessor = record_accessor_create(@key_name)
|
|
54
|
+
@parser = parser_create
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
REPLACE_CHAR = '?'.freeze
|
|
58
|
+
|
|
59
|
+
def filter_stream(tag, es)
|
|
60
|
+
new_es = Fluent::MultiEventStream.new
|
|
61
|
+
es.each do |time, record|
|
|
62
|
+
begin
|
|
63
|
+
raw_value = @accessor.call(record)
|
|
64
|
+
if raw_value.nil?
|
|
65
|
+
new_es.add(time, handle_parsed(tag, record, time, {})) if @reserve_data
|
|
66
|
+
raise ArgumentError, "#{@key_name} does not exist"
|
|
67
|
+
else
|
|
68
|
+
filter_one_record(tag, time, record, raw_value) do |result_time, result_record|
|
|
69
|
+
new_es.add(result_time, result_record)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
rescue => e
|
|
73
|
+
router.emit_error_event(tag, time, record, e) if @emit_invalid_record_to_error
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
new_es
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def filter_one_record(tag, time, record, raw_value)
|
|
82
|
+
begin
|
|
83
|
+
@parser.parse(raw_value) do |t, values|
|
|
84
|
+
if values
|
|
85
|
+
t = if @reserve_time
|
|
86
|
+
time
|
|
87
|
+
else
|
|
88
|
+
t.nil? ? time : t
|
|
89
|
+
end
|
|
90
|
+
@accessor.delete(record) if @remove_key_name_field
|
|
91
|
+
else
|
|
92
|
+
router.emit_error_event(tag, time, record, Fluent::Plugin::Parser::ParserError.new("pattern not matched with data '#{raw_value}'")) if @emit_invalid_record_to_error
|
|
93
|
+
next unless @reserve_data
|
|
94
|
+
t = time
|
|
95
|
+
values = {}
|
|
96
|
+
end
|
|
97
|
+
yield(t, handle_parsed(tag, record, t, values))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
rescue Fluent::Plugin::Parser::ParserError => e
|
|
101
|
+
raise e
|
|
102
|
+
rescue ArgumentError => e
|
|
103
|
+
raise unless @replace_invalid_sequence
|
|
104
|
+
raise unless e.message.index("invalid byte sequence in") == 0
|
|
105
|
+
|
|
106
|
+
raw_value = raw_value.scrub(REPLACE_CHAR)
|
|
107
|
+
retry
|
|
108
|
+
rescue => e
|
|
109
|
+
raise Fluent::Plugin::Parser::ParserError, "parse failed #{e.message}"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def handle_parsed(tag, record, t, values)
|
|
114
|
+
if values && @inject_key_prefix
|
|
115
|
+
values = Hash[values.map { |k, v| [@inject_key_prefix + k, v] }]
|
|
116
|
+
end
|
|
117
|
+
r = @hash_value_field ? {@hash_value_field => values} : values
|
|
118
|
+
if @reserve_data
|
|
119
|
+
r = r ? record.merge(r) : record
|
|
120
|
+
end
|
|
121
|
+
r
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|