fluentd 0.12.40 → 1.6.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fluentd might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
- data/.github/ISSUE_TEMPLATE.md +17 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +13 -0
- data/.gitignore +5 -0
- data/.gitlab/cicd-template.yaml +10 -0
- data/.gitlab-ci.yml +147 -0
- data/.travis.yml +56 -20
- data/ADOPTERS.md +5 -0
- data/CHANGELOG.md +1369 -0
- data/CONTRIBUTING.md +16 -5
- data/GOVERNANCE.md +55 -0
- data/Gemfile +5 -0
- data/GithubWorkflow.md +78 -0
- data/LICENSE +202 -0
- data/MAINTAINERS.md +7 -0
- data/README.md +23 -11
- data/Rakefile +48 -2
- data/Vagrantfile +17 -0
- data/appveyor.yml +37 -0
- data/bin/fluent-binlog-reader +7 -0
- data/bin/fluent-ca-generate +6 -0
- data/bin/fluent-plugin-config-format +5 -0
- data/bin/fluent-plugin-generate +5 -0
- data/bin/fluentd +3 -0
- data/code-of-conduct.md +3 -0
- data/example/copy_roundrobin.conf +39 -0
- data/example/counter.conf +18 -0
- data/example/in_dummy_blocks.conf +17 -0
- data/example/in_dummy_with_compression.conf +23 -0
- data/example/in_forward.conf +7 -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 +3 -1
- data/example/in_out_forward.conf +17 -0
- data/example/logevents.conf +25 -0
- data/example/multi_filters.conf +61 -0
- data/example/out_exec_filter.conf +42 -0
- data/example/out_forward.conf +13 -13
- 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_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/secondary_file.conf +42 -0
- data/example/suppress_config_dump.conf +7 -0
- data/example/worker_section.conf +36 -0
- data/fluent.conf +29 -0
- data/fluentd.gemspec +21 -11
- data/lib/fluent/agent.rb +67 -90
- data/lib/fluent/clock.rb +62 -0
- data/lib/fluent/command/binlog_reader.rb +244 -0
- data/lib/fluent/command/ca_generate.rb +181 -0
- data/lib/fluent/command/cat.rb +42 -18
- data/lib/fluent/command/debug.rb +12 -10
- data/lib/fluent/command/fluentd.rb +153 -5
- data/lib/fluent/command/plugin_config_formatter.rb +292 -0
- data/lib/fluent/command/plugin_generator.rb +324 -0
- data/lib/fluent/compat/call_super_mixin.rb +67 -0
- data/lib/fluent/compat/detach_process_mixin.rb +33 -0
- data/lib/fluent/compat/exec_util.rb +129 -0
- data/lib/fluent/compat/file_util.rb +54 -0
- data/lib/fluent/compat/filter.rb +68 -0
- data/lib/fluent/compat/formatter.rb +111 -0
- data/lib/fluent/compat/formatter_utils.rb +85 -0
- data/lib/fluent/compat/handle_tag_and_time_mixin.rb +62 -0
- data/lib/fluent/compat/handle_tag_name_mixin.rb +53 -0
- data/lib/fluent/compat/input.rb +49 -0
- data/lib/fluent/compat/output.rb +718 -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/configure_proxy.rb +210 -62
- data/lib/fluent/config/dsl.rb +12 -5
- data/lib/fluent/config/element.rb +107 -9
- data/lib/fluent/config/literal_parser.rb +9 -3
- data/lib/fluent/config/parser.rb +4 -4
- data/lib/fluent/config/section.rb +51 -14
- data/lib/fluent/config/types.rb +28 -13
- data/lib/fluent/config/v1_parser.rb +3 -5
- data/lib/fluent/config.rb +23 -20
- data/lib/fluent/configurable.rb +79 -21
- data/lib/fluent/counter/base_socket.rb +46 -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 +15 -0
- data/lib/fluent/engine.rb +102 -65
- data/lib/fluent/env.rb +7 -3
- data/lib/fluent/error.rb +30 -0
- data/lib/fluent/event.rb +197 -21
- data/lib/fluent/event_router.rb +93 -10
- data/lib/fluent/filter.rb +2 -50
- data/lib/fluent/formatter.rb +4 -293
- data/lib/fluent/input.rb +2 -32
- data/lib/fluent/label.rb +10 -2
- data/lib/fluent/load.rb +3 -3
- data/lib/fluent/log.rb +348 -81
- data/lib/fluent/match.rb +37 -36
- data/lib/fluent/mixin.rb +12 -176
- data/lib/fluent/msgpack_factory.rb +62 -0
- data/lib/fluent/output.rb +10 -612
- data/lib/fluent/output_chain.rb +23 -0
- data/lib/fluent/parser.rb +4 -800
- data/lib/fluent/plugin/bare_output.rb +63 -0
- data/lib/fluent/plugin/base.rb +192 -0
- data/lib/fluent/plugin/buf_file.rb +128 -174
- data/lib/fluent/plugin/buf_memory.rb +9 -92
- data/lib/fluent/plugin/buffer/chunk.rb +221 -0
- data/lib/fluent/plugin/buffer/file_chunk.rb +383 -0
- data/lib/fluent/plugin/buffer/memory_chunk.rb +90 -0
- data/lib/fluent/plugin/buffer.rb +779 -0
- data/lib/fluent/plugin/compressable.rb +92 -0
- data/lib/fluent/plugin/exec_util.rb +3 -108
- data/lib/fluent/plugin/file_util.rb +4 -34
- data/lib/fluent/plugin/file_wrapper.rb +120 -0
- data/lib/fluent/plugin/filter.rb +93 -0
- data/lib/fluent/plugin/filter_grep.rb +117 -34
- data/lib/fluent/plugin/filter_parser.rb +85 -62
- data/lib/fluent/plugin/filter_record_transformer.rb +27 -39
- data/lib/fluent/plugin/filter_stdout.rb +15 -12
- data/lib/fluent/plugin/formatter.rb +50 -0
- data/lib/fluent/plugin/formatter_csv.rb +52 -0
- data/lib/fluent/plugin/formatter_hash.rb +33 -0
- data/lib/fluent/plugin/formatter_json.rb +55 -0
- data/lib/fluent/plugin/formatter_ltsv.rb +42 -0
- data/lib/fluent/plugin/formatter_msgpack.rb +33 -0
- data/lib/fluent/plugin/formatter_out_file.rb +51 -0
- data/lib/fluent/plugin/formatter_single_value.rb +34 -0
- data/lib/fluent/plugin/formatter_stdout.rb +76 -0
- data/lib/fluent/plugin/formatter_tsv.rb +38 -0
- data/lib/fluent/plugin/in_debug_agent.rb +17 -6
- data/lib/fluent/plugin/in_dummy.rb +47 -20
- data/lib/fluent/plugin/in_exec.rb +55 -123
- data/lib/fluent/plugin/in_forward.rb +299 -216
- data/lib/fluent/plugin/in_gc_stat.rb +14 -36
- data/lib/fluent/plugin/in_http.rb +204 -91
- data/lib/fluent/plugin/in_monitor_agent.rb +186 -258
- data/lib/fluent/plugin/in_object_space.rb +13 -41
- data/lib/fluent/plugin/in_syslog.rb +112 -134
- data/lib/fluent/plugin/in_tail.rb +408 -745
- data/lib/fluent/plugin/in_tcp.rb +66 -9
- data/lib/fluent/plugin/in_udp.rb +60 -11
- data/lib/fluent/plugin/{in_stream.rb → in_unix.rb} +8 -4
- data/lib/fluent/plugin/input.rb +37 -0
- data/lib/fluent/plugin/multi_output.rb +158 -0
- data/lib/fluent/plugin/out_copy.rb +23 -35
- data/lib/fluent/plugin/out_exec.rb +67 -70
- data/lib/fluent/plugin/out_exec_filter.rb +204 -271
- data/lib/fluent/plugin/out_file.rb +267 -73
- data/lib/fluent/plugin/out_forward.rb +854 -325
- data/lib/fluent/plugin/out_null.rb +42 -9
- data/lib/fluent/plugin/out_relabel.rb +9 -5
- data/lib/fluent/plugin/out_roundrobin.rb +18 -37
- data/lib/fluent/plugin/out_secondary_file.rb +133 -0
- data/lib/fluent/plugin/out_stdout.rb +43 -10
- data/lib/fluent/plugin/out_stream.rb +7 -2
- data/lib/fluent/plugin/output.rb +1498 -0
- data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
- data/lib/fluent/plugin/parser.rb +191 -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 +39 -0
- data/lib/fluent/plugin/parser_json.rb +94 -0
- data/lib/fluent/plugin/parser_ltsv.rb +49 -0
- data/lib/fluent/plugin/parser_msgpack.rb +50 -0
- data/lib/fluent/plugin/parser_multiline.rb +106 -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 +142 -0
- data/lib/fluent/plugin/parser_tsv.rb +42 -0
- data/lib/fluent/plugin/socket_util.rb +3 -143
- data/lib/fluent/plugin/storage.rb +84 -0
- data/lib/fluent/plugin/storage_local.rb +164 -0
- data/lib/fluent/plugin/string_util.rb +3 -15
- data/lib/fluent/plugin.rb +122 -121
- data/lib/fluent/plugin_helper/cert_option.rb +178 -0
- data/lib/fluent/plugin_helper/child_process.rb +364 -0
- data/lib/fluent/plugin_helper/compat_parameters.rb +333 -0
- data/lib/fluent/plugin_helper/counter.rb +51 -0
- data/lib/fluent/plugin_helper/event_emitter.rb +93 -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 +79 -0
- data/lib/fluent/plugin_helper/http_server/compat/server.rb +81 -0
- data/lib/fluent/plugin_helper/http_server/compat/webrick_handler.rb +58 -0
- data/lib/fluent/plugin_helper/http_server/methods.rb +35 -0
- data/lib/fluent/plugin_helper/http_server/request.rb +42 -0
- data/lib/fluent/plugin_helper/http_server/router.rb +54 -0
- data/lib/fluent/plugin_helper/http_server/server.rb +87 -0
- data/lib/fluent/plugin_helper/http_server.rb +76 -0
- data/lib/fluent/plugin_helper/inject.rb +151 -0
- data/lib/fluent/plugin_helper/parser.rb +147 -0
- data/lib/fluent/plugin_helper/record_accessor.rb +210 -0
- data/lib/fluent/plugin_helper/retry_state.rb +205 -0
- data/lib/fluent/plugin_helper/server.rb +807 -0
- data/lib/fluent/plugin_helper/socket.rb +250 -0
- data/lib/fluent/plugin_helper/socket_option.rb +80 -0
- data/lib/fluent/plugin_helper/storage.rb +349 -0
- data/lib/fluent/plugin_helper/thread.rb +179 -0
- data/lib/fluent/plugin_helper/timer.rb +92 -0
- data/lib/fluent/plugin_helper.rb +73 -0
- data/lib/fluent/plugin_id.rb +80 -0
- data/lib/fluent/process.rb +3 -489
- data/lib/fluent/registry.rb +52 -10
- data/lib/fluent/root_agent.rb +204 -42
- data/lib/fluent/supervisor.rb +597 -359
- data/lib/fluent/system_config.rb +131 -42
- data/lib/fluent/test/base.rb +6 -54
- data/lib/fluent/test/driver/base.rb +224 -0
- data/lib/fluent/test/driver/base_owned.rb +70 -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 +57 -0
- data/lib/fluent/test/driver/formatter.rb +30 -0
- data/lib/fluent/test/driver/input.rb +31 -0
- data/lib/fluent/test/driver/multi_output.rb +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/test_event_router.rb +45 -0
- data/lib/fluent/test/filter_test.rb +0 -1
- data/lib/fluent/test/formatter_test.rb +4 -1
- data/lib/fluent/test/helpers.rb +58 -10
- data/lib/fluent/test/input_test.rb +27 -19
- data/lib/fluent/test/log.rb +79 -0
- data/lib/fluent/test/output_test.rb +28 -39
- data/lib/fluent/test/parser_test.rb +3 -1
- data/lib/fluent/test/startup_shutdown.rb +46 -0
- data/lib/fluent/test.rb +33 -1
- data/lib/fluent/time.rb +450 -1
- data/lib/fluent/timezone.rb +27 -3
- data/lib/fluent/{status.rb → unique_id.rb} +15 -24
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +85 -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 +27 -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/test/helper.rb.erb +8 -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/plugin_config_formatter/param.md-compact.erb +25 -0
- data/templates/plugin_config_formatter/param.md.erb +34 -0
- data/templates/plugin_config_formatter/section.md.erb +12 -0
- data/test/command/test_binlog_reader.rb +346 -0
- data/test/command/test_ca_generate.rb +70 -0
- data/test/command/test_fluentd.rb +901 -0
- data/test/command/test_plugin_config_formatter.rb +276 -0
- data/test/command/test_plugin_generator.rb +92 -0
- data/test/compat/test_calls_super.rb +166 -0
- data/test/compat/test_parser.rb +92 -0
- data/test/config/test_config_parser.rb +126 -2
- data/test/config/test_configurable.rb +946 -187
- data/test/config/test_configure_proxy.rb +424 -74
- data/test/config/test_dsl.rb +11 -11
- data/test/config/test_element.rb +500 -0
- data/test/config/test_literal_parser.rb +8 -0
- data/test/config/test_plugin_configuration.rb +56 -0
- data/test/config/test_section.rb +79 -7
- data/test/config/test_system_config.rb +122 -35
- data/test/config/test_types.rb +38 -0
- data/test/counter/test_client.rb +559 -0
- data/test/counter/test_error.rb +44 -0
- data/test/counter/test_mutex_hash.rb +179 -0
- data/test/counter/test_server.rb +589 -0
- data/test/counter/test_store.rb +258 -0
- data/test/counter/test_validator.rb +137 -0
- data/test/helper.rb +89 -6
- data/test/helpers/fuzzy_assert.rb +89 -0
- data/test/plugin/test_bare_output.rb +118 -0
- data/test/plugin/test_base.rb +115 -0
- data/test/plugin/test_buf_file.rb +823 -460
- data/test/plugin/test_buf_memory.rb +32 -194
- data/test/plugin/test_buffer.rb +1233 -0
- data/test/plugin/test_buffer_chunk.rb +198 -0
- data/test/plugin/test_buffer_file_chunk.rb +844 -0
- data/test/plugin/test_buffer_memory_chunk.rb +338 -0
- data/test/plugin/test_compressable.rb +84 -0
- data/test/plugin/test_filter.rb +357 -0
- data/test/plugin/test_filter_grep.rb +540 -29
- data/test/plugin/test_filter_parser.rb +439 -452
- data/test/plugin/test_filter_record_transformer.rb +123 -166
- data/test/plugin/test_filter_stdout.rb +160 -72
- data/test/plugin/test_formatter_csv.rb +111 -0
- data/test/plugin/test_formatter_hash.rb +35 -0
- data/test/plugin/test_formatter_json.rb +51 -0
- data/test/plugin/test_formatter_ltsv.rb +62 -0
- data/test/plugin/test_formatter_msgpack.rb +28 -0
- data/test/plugin/test_formatter_out_file.rb +95 -0
- data/test/plugin/test_formatter_single_value.rb +38 -0
- data/test/plugin/test_formatter_tsv.rb +68 -0
- data/test/plugin/test_in_debug_agent.rb +24 -1
- data/test/plugin/test_in_dummy.rb +111 -18
- data/test/plugin/test_in_exec.rb +200 -113
- data/test/plugin/test_in_forward.rb +990 -387
- data/test/plugin/test_in_gc_stat.rb +10 -8
- data/test/plugin/test_in_http.rb +600 -224
- data/test/plugin/test_in_monitor_agent.rb +690 -0
- data/test/plugin/test_in_object_space.rb +24 -8
- data/test/plugin/test_in_syslog.rb +154 -215
- data/test/plugin/test_in_tail.rb +1006 -707
- data/test/plugin/test_in_tcp.rb +125 -48
- data/test/plugin/test_in_udp.rb +204 -63
- data/test/plugin/{test_in_stream.rb → test_in_unix.rb} +14 -13
- data/test/plugin/test_input.rb +126 -0
- data/test/plugin/test_metadata.rb +89 -0
- data/test/plugin/test_multi_output.rb +180 -0
- data/test/plugin/test_out_copy.rb +117 -112
- data/test/plugin/test_out_exec.rb +258 -53
- data/test/plugin/test_out_exec_filter.rb +538 -115
- data/test/plugin/test_out_file.rb +865 -178
- data/test/plugin/test_out_forward.rb +998 -210
- data/test/plugin/test_out_null.rb +105 -0
- data/test/plugin/test_out_relabel.rb +28 -0
- data/test/plugin/test_out_roundrobin.rb +36 -29
- data/test/plugin/test_out_secondary_file.rb +458 -0
- data/test/plugin/test_out_stdout.rb +135 -37
- data/test/plugin/test_out_stream.rb +18 -0
- data/test/plugin/test_output.rb +984 -0
- data/test/plugin/test_output_as_buffered.rb +2021 -0
- data/test/plugin/test_output_as_buffered_backup.rb +312 -0
- data/test/plugin/test_output_as_buffered_compress.rb +165 -0
- data/test/plugin/test_output_as_buffered_overflow.rb +250 -0
- data/test/plugin/test_output_as_buffered_retries.rb +911 -0
- data/test/plugin/test_output_as_buffered_secondary.rb +874 -0
- data/test/plugin/test_output_as_standard.rb +374 -0
- data/test/plugin/test_owned_by.rb +35 -0
- data/test/plugin/test_parser.rb +359 -0
- data/test/plugin/test_parser_apache.rb +42 -0
- data/test/plugin/test_parser_apache2.rb +47 -0
- data/test/plugin/test_parser_apache_error.rb +45 -0
- data/test/plugin/test_parser_csv.rb +103 -0
- data/test/plugin/test_parser_json.rb +138 -0
- data/test/plugin/test_parser_labeled_tsv.rb +145 -0
- data/test/plugin/test_parser_multiline.rb +100 -0
- data/test/plugin/test_parser_nginx.rb +88 -0
- data/test/plugin/test_parser_none.rb +52 -0
- data/test/plugin/test_parser_regexp.rb +289 -0
- data/test/plugin/test_parser_syslog.rb +441 -0
- data/test/plugin/test_parser_tsv.rb +122 -0
- data/test/plugin/test_storage.rb +167 -0
- data/test/plugin/test_storage_local.rb +335 -0
- data/test/plugin_helper/data/cert/cert-key.pem +27 -0
- data/test/plugin_helper/data/cert/cert-with-no-newline.pem +19 -0
- data/test/plugin_helper/data/cert/cert.pem +19 -0
- data/test/plugin_helper/http_server/test_app.rb +65 -0
- data/test/plugin_helper/http_server/test_route.rb +32 -0
- data/test/plugin_helper/test_cert_option.rb +16 -0
- data/test/plugin_helper/test_child_process.rb +794 -0
- data/test/plugin_helper/test_compat_parameters.rb +353 -0
- data/test/plugin_helper/test_event_emitter.rb +51 -0
- data/test/plugin_helper/test_event_loop.rb +52 -0
- data/test/plugin_helper/test_extract.rb +194 -0
- data/test/plugin_helper/test_formatter.rb +255 -0
- data/test/plugin_helper/test_http_server_helper.rb +205 -0
- data/test/plugin_helper/test_inject.rb +519 -0
- data/test/plugin_helper/test_parser.rb +264 -0
- data/test/plugin_helper/test_record_accessor.rb +197 -0
- data/test/plugin_helper/test_retry_state.rb +442 -0
- data/test/plugin_helper/test_server.rb +1714 -0
- data/test/plugin_helper/test_storage.rb +542 -0
- data/test/plugin_helper/test_thread.rb +164 -0
- data/test/plugin_helper/test_timer.rb +132 -0
- data/test/scripts/exec_script.rb +0 -6
- data/test/scripts/fluent/plugin/formatter1/formatter_test1.rb +7 -0
- data/test/scripts/fluent/plugin/formatter2/formatter_test2.rb +7 -0
- data/test/scripts/fluent/plugin/out_test.rb +23 -15
- data/test/scripts/fluent/plugin/out_test2.rb +80 -0
- data/test/test_clock.rb +164 -0
- data/test/test_config.rb +16 -7
- data/test/test_configdsl.rb +2 -2
- data/test/test_event.rb +360 -13
- data/test/test_event_router.rb +108 -11
- data/test/test_event_time.rb +199 -0
- data/test/test_filter.rb +48 -6
- data/test/test_formatter.rb +11 -391
- data/test/test_input.rb +1 -1
- data/test/test_log.rb +591 -31
- data/test/test_mixin.rb +1 -1
- data/test/test_output.rb +121 -185
- data/test/test_plugin.rb +251 -0
- data/test/test_plugin_classes.rb +177 -10
- data/test/test_plugin_helper.rb +81 -0
- data/test/test_plugin_id.rb +101 -0
- data/test/test_process.rb +8 -42
- data/test/test_root_agent.rb +766 -21
- data/test/test_supervisor.rb +481 -0
- data/test/test_test_drivers.rb +135 -0
- data/test/test_time_formatter.rb +282 -0
- data/test/test_time_parser.rb +231 -0
- data/test/test_unique_id.rb +47 -0
- metadata +454 -60
- data/COPYING +0 -14
- data/ChangeLog +0 -666
- data/lib/fluent/buffer.rb +0 -365
- data/lib/fluent/plugin/in_status.rb +0 -76
- data/test/plugin/test_in_status.rb +0 -38
- data/test/test_buffer.rb +0 -624
- data/test/test_parser.rb +0 -1305
@@ -0,0 +1,984 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'fluent/plugin/output'
|
3
|
+
require 'fluent/plugin/buffer'
|
4
|
+
require 'fluent/event'
|
5
|
+
|
6
|
+
require 'json'
|
7
|
+
require 'time'
|
8
|
+
require 'timeout'
|
9
|
+
|
10
|
+
module FluentPluginOutputTest
|
11
|
+
class DummyBareOutput < Fluent::Plugin::Output
|
12
|
+
def register(name, &block)
|
13
|
+
instance_variable_set("@#{name}", block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
class DummySyncOutput < DummyBareOutput
|
17
|
+
def initialize
|
18
|
+
super
|
19
|
+
@process = nil
|
20
|
+
end
|
21
|
+
def process(tag, es)
|
22
|
+
@process ? @process.call(tag, es) : nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
class DummyAsyncOutput < DummyBareOutput
|
26
|
+
def initialize
|
27
|
+
super
|
28
|
+
@format = nil
|
29
|
+
@write = nil
|
30
|
+
end
|
31
|
+
def format(tag, time, record)
|
32
|
+
@format ? @format.call(tag, time, record) : [tag, time, record].to_json
|
33
|
+
end
|
34
|
+
def write(chunk)
|
35
|
+
@write ? @write.call(chunk) : nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
class DummyAsyncStandardOutput < DummyBareOutput
|
39
|
+
def initialize
|
40
|
+
super
|
41
|
+
@write = nil
|
42
|
+
end
|
43
|
+
def write(chunk)
|
44
|
+
@write ? @write.call(chunk) : nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
class DummyDelayedOutput < DummyBareOutput
|
48
|
+
def initialize
|
49
|
+
super
|
50
|
+
@format = nil
|
51
|
+
@try_write = nil
|
52
|
+
end
|
53
|
+
def format(tag, time, record)
|
54
|
+
@format ? @format.call(tag, time, record) : [tag, time, record].to_json
|
55
|
+
end
|
56
|
+
def try_write(chunk)
|
57
|
+
@try_write ? @try_write.call(chunk) : nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
class DummyDelayedStandardOutput < DummyBareOutput
|
61
|
+
def initialize
|
62
|
+
super
|
63
|
+
@try_write = nil
|
64
|
+
end
|
65
|
+
def try_write(chunk)
|
66
|
+
@try_write ? @try_write.call(chunk) : nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
class DummyFullFeatureOutput < DummyBareOutput
|
70
|
+
def initialize
|
71
|
+
super
|
72
|
+
@prefer_buffered_processing = nil
|
73
|
+
@prefer_delayed_commit = nil
|
74
|
+
@process = nil
|
75
|
+
@format = nil
|
76
|
+
@write = nil
|
77
|
+
@try_write = nil
|
78
|
+
end
|
79
|
+
def prefer_buffered_processing
|
80
|
+
@prefer_buffered_processing ? @prefer_buffered_processing.call : false
|
81
|
+
end
|
82
|
+
def prefer_delayed_commit
|
83
|
+
@prefer_delayed_commit ? @prefer_delayed_commit.call : false
|
84
|
+
end
|
85
|
+
def process(tag, es)
|
86
|
+
@process ? @process.call(tag, es) : nil
|
87
|
+
end
|
88
|
+
def format(tag, time, record)
|
89
|
+
@format ? @format.call(tag, time, record) : [tag, time, record].to_json
|
90
|
+
end
|
91
|
+
def write(chunk)
|
92
|
+
@write ? @write.call(chunk) : nil
|
93
|
+
end
|
94
|
+
def try_write(chunk)
|
95
|
+
@try_write ? @try_write.call(chunk) : nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class OutputTest < Test::Unit::TestCase
|
101
|
+
class << self
|
102
|
+
def startup
|
103
|
+
$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '../scripts'))
|
104
|
+
require 'fluent/plugin/out_test'
|
105
|
+
end
|
106
|
+
|
107
|
+
def shutdown
|
108
|
+
$LOAD_PATH.shift
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def create_output(type=:full)
|
113
|
+
case type
|
114
|
+
when :bare then FluentPluginOutputTest::DummyBareOutput.new
|
115
|
+
when :sync then FluentPluginOutputTest::DummySyncOutput.new
|
116
|
+
when :buffered then FluentPluginOutputTest::DummyAsyncOutput.new
|
117
|
+
when :standard then FluentPluginOutputTest::DummyAsyncStandardOutput.new
|
118
|
+
when :delayed then FluentPluginOutputTest::DummyDelayedOutput.new
|
119
|
+
when :sdelayed then FluentPluginOutputTest::DummyDelayedStandardOutput.new
|
120
|
+
when :full then FluentPluginOutputTest::DummyFullFeatureOutput.new
|
121
|
+
else
|
122
|
+
raise ArgumentError, "unknown type: #{type}"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
def create_metadata(timekey: nil, tag: nil, variables: nil)
|
126
|
+
Fluent::Plugin::Buffer::Metadata.new(timekey, tag, variables)
|
127
|
+
end
|
128
|
+
def create_chunk(timekey: nil, tag: nil, variables: nil)
|
129
|
+
m = Fluent::Plugin::Buffer::Metadata.new(timekey, tag, variables)
|
130
|
+
Fluent::Plugin::Buffer::MemoryChunk.new(m)
|
131
|
+
end
|
132
|
+
def waiting(seconds)
|
133
|
+
begin
|
134
|
+
Timeout.timeout(seconds) do
|
135
|
+
yield
|
136
|
+
end
|
137
|
+
rescue Timeout::Error
|
138
|
+
STDERR.print(*@i.log.out.logs)
|
139
|
+
raise
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
sub_test_case 'basic output feature' do
|
144
|
+
setup do
|
145
|
+
@i = create_output(:full)
|
146
|
+
end
|
147
|
+
|
148
|
+
test 'are not available with multi workers configuration in default' do
|
149
|
+
assert_false @i.multi_workers_ready?
|
150
|
+
end
|
151
|
+
|
152
|
+
test '#implement? can return features for plugin instances' do
|
153
|
+
i1 = FluentPluginOutputTest::DummyBareOutput.new
|
154
|
+
assert !i1.implement?(:synchronous)
|
155
|
+
assert !i1.implement?(:buffered)
|
156
|
+
assert !i1.implement?(:delayed_commit)
|
157
|
+
assert !i1.implement?(:custom_format)
|
158
|
+
|
159
|
+
i2 = FluentPluginOutputTest::DummySyncOutput.new
|
160
|
+
assert i2.implement?(:synchronous)
|
161
|
+
assert !i2.implement?(:buffered)
|
162
|
+
assert !i2.implement?(:delayed_commit)
|
163
|
+
assert !i2.implement?(:custom_format)
|
164
|
+
|
165
|
+
i3 = FluentPluginOutputTest::DummyAsyncOutput.new
|
166
|
+
assert !i3.implement?(:synchronous)
|
167
|
+
assert i3.implement?(:buffered)
|
168
|
+
assert !i3.implement?(:delayed_commit)
|
169
|
+
assert i3.implement?(:custom_format)
|
170
|
+
|
171
|
+
i4 = FluentPluginOutputTest::DummyAsyncStandardOutput.new
|
172
|
+
assert !i4.implement?(:synchronous)
|
173
|
+
assert i4.implement?(:buffered)
|
174
|
+
assert !i4.implement?(:delayed_commit)
|
175
|
+
assert !i4.implement?(:custom_format)
|
176
|
+
|
177
|
+
i5 = FluentPluginOutputTest::DummyDelayedOutput.new
|
178
|
+
assert !i5.implement?(:synchronous)
|
179
|
+
assert !i5.implement?(:buffered)
|
180
|
+
assert i5.implement?(:delayed_commit)
|
181
|
+
assert i5.implement?(:custom_format)
|
182
|
+
|
183
|
+
i6 = FluentPluginOutputTest::DummyDelayedStandardOutput.new
|
184
|
+
assert !i6.implement?(:synchronous)
|
185
|
+
assert !i6.implement?(:buffered)
|
186
|
+
assert i6.implement?(:delayed_commit)
|
187
|
+
assert !i6.implement?(:custom_format)
|
188
|
+
|
189
|
+
i6 = FluentPluginOutputTest::DummyFullFeatureOutput.new
|
190
|
+
assert i6.implement?(:synchronous)
|
191
|
+
assert i6.implement?(:buffered)
|
192
|
+
assert i6.implement?(:delayed_commit)
|
193
|
+
assert i6.implement?(:custom_format)
|
194
|
+
end
|
195
|
+
|
196
|
+
test 'plugin lifecycle for configure/start/stop/before_shutdown/shutdown/after_shutdown/close/terminate' do
|
197
|
+
assert !@i.configured?
|
198
|
+
@i.configure(config_element())
|
199
|
+
assert @i.configured?
|
200
|
+
assert !@i.started?
|
201
|
+
@i.start
|
202
|
+
assert @i.started?
|
203
|
+
assert !@i.after_started?
|
204
|
+
@i.after_start
|
205
|
+
assert @i.after_started?
|
206
|
+
assert !@i.stopped?
|
207
|
+
@i.stop
|
208
|
+
assert @i.stopped?
|
209
|
+
assert !@i.before_shutdown?
|
210
|
+
@i.before_shutdown
|
211
|
+
assert @i.before_shutdown?
|
212
|
+
assert !@i.shutdown?
|
213
|
+
@i.shutdown
|
214
|
+
assert @i.shutdown?
|
215
|
+
assert !@i.after_shutdown?
|
216
|
+
@i.after_shutdown
|
217
|
+
assert @i.after_shutdown?
|
218
|
+
assert !@i.closed?
|
219
|
+
@i.close
|
220
|
+
assert @i.closed?
|
221
|
+
assert !@i.terminated?
|
222
|
+
@i.terminate
|
223
|
+
assert @i.terminated?
|
224
|
+
end
|
225
|
+
|
226
|
+
data(:new_api => :chunk,
|
227
|
+
:old_api => :metadata)
|
228
|
+
test '#extract_placeholders does nothing if chunk key is not specified' do |api|
|
229
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
230
|
+
assert !@i.chunk_key_time
|
231
|
+
assert !@i.chunk_key_tag
|
232
|
+
assert_equal [], @i.chunk_keys
|
233
|
+
tmpl = "/mypath/%Y/%m/%d/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
|
234
|
+
t = event_time('2016-04-11 20:30:00 +0900')
|
235
|
+
v = {key1: "value1", key2: "value2"}
|
236
|
+
c = if api == :chunk
|
237
|
+
create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
|
238
|
+
else
|
239
|
+
create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
|
240
|
+
end
|
241
|
+
assert_equal tmpl, @i.extract_placeholders(tmpl, c)
|
242
|
+
end
|
243
|
+
|
244
|
+
data(:new_api => :chunk,
|
245
|
+
:old_api => :metadata)
|
246
|
+
test '#extract_placeholders can extract time if time key and range are configured' do |api|
|
247
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
|
248
|
+
assert @i.chunk_key_time
|
249
|
+
assert !@i.chunk_key_tag
|
250
|
+
assert_equal [], @i.chunk_keys
|
251
|
+
tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
|
252
|
+
t = event_time('2016-04-11 20:30:00 +0900')
|
253
|
+
v = {key1: "value1", key2: "value2"}
|
254
|
+
c = if api == :chunk
|
255
|
+
create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
|
256
|
+
else
|
257
|
+
create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
|
258
|
+
end
|
259
|
+
assert_equal "/mypath/2016/04/11/20-30/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail", @i.extract_placeholders(tmpl, c)
|
260
|
+
end
|
261
|
+
|
262
|
+
data(:new_api => :chunk,
|
263
|
+
:old_api => :metadata)
|
264
|
+
test '#extract_placeholders can extract tag and parts of tag if tag is configured' do |api|
|
265
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag', {})]))
|
266
|
+
assert !@i.chunk_key_time
|
267
|
+
assert @i.chunk_key_tag
|
268
|
+
assert_equal [], @i.chunk_keys
|
269
|
+
tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
|
270
|
+
t = event_time('2016-04-11 20:30:00 +0900')
|
271
|
+
v = {key1: "value1", key2: "value2"}
|
272
|
+
c = if api == :chunk
|
273
|
+
create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
|
274
|
+
else
|
275
|
+
create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
|
276
|
+
end
|
277
|
+
assert_equal "/mypath/%Y/%m/%d/%H-%M/fluentd.test.output/test/output/${key1}/${key2}/tail", @i.extract_placeholders(tmpl, c)
|
278
|
+
end
|
279
|
+
|
280
|
+
data(:new_api => :chunk,
|
281
|
+
:old_api => :metadata)
|
282
|
+
test '#extract_placeholders can extract variables if variables are configured' do |api|
|
283
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'key1,key2', {})]))
|
284
|
+
assert !@i.chunk_key_time
|
285
|
+
assert !@i.chunk_key_tag
|
286
|
+
assert_equal ['key1','key2'], @i.chunk_keys
|
287
|
+
tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
|
288
|
+
t = event_time('2016-04-11 20:30:00 +0900')
|
289
|
+
v = {key1: "value1", key2: "value2"}
|
290
|
+
c = if api == :chunk
|
291
|
+
create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
|
292
|
+
else
|
293
|
+
create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
|
294
|
+
end
|
295
|
+
assert_equal "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/value1/value2/tail", @i.extract_placeholders(tmpl, c)
|
296
|
+
end
|
297
|
+
|
298
|
+
data(:new_api => :chunk,
|
299
|
+
:old_api => :metadata)
|
300
|
+
test '#extract_placeholders can extract nested variables if variables are configured with dot notation' do |api|
|
301
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'key,$.nest.key', {})]))
|
302
|
+
assert !@i.chunk_key_time
|
303
|
+
assert !@i.chunk_key_tag
|
304
|
+
assert_equal ['key','$.nest.key'], @i.chunk_keys
|
305
|
+
tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key}/${$.nest.key}/tail"
|
306
|
+
t = event_time('2016-04-11 20:30:00 +0900')
|
307
|
+
v = {:key => "value1", :"$.nest.key" => "value2"}
|
308
|
+
c = if api == :chunk
|
309
|
+
create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
|
310
|
+
else
|
311
|
+
create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
|
312
|
+
end
|
313
|
+
assert_equal "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/value1/value2/tail", @i.extract_placeholders(tmpl, c)
|
314
|
+
end
|
315
|
+
|
316
|
+
data(:new_api => :chunk,
|
317
|
+
:old_api => :metadata)
|
318
|
+
test '#extract_placeholders can extract all chunk keys if configured' do |api|
|
319
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
|
320
|
+
assert @i.chunk_key_time
|
321
|
+
assert @i.chunk_key_tag
|
322
|
+
assert_equal ['key1','key2'], @i.chunk_keys
|
323
|
+
tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
|
324
|
+
t = event_time('2016-04-11 20:30:00 +0900')
|
325
|
+
v = {key1: "value1", key2: "value2"}
|
326
|
+
c = if api == :chunk
|
327
|
+
create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
|
328
|
+
else
|
329
|
+
create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
|
330
|
+
end
|
331
|
+
assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/test/output/value1/value2/tail", @i.extract_placeholders(tmpl, c)
|
332
|
+
end
|
333
|
+
|
334
|
+
data(:new_api => :chunk,
|
335
|
+
:old_api => :metadata)
|
336
|
+
test '#extract_placeholders can extract negative index with tag' do |api|
|
337
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
|
338
|
+
assert @i.chunk_key_time
|
339
|
+
assert @i.chunk_key_tag
|
340
|
+
assert_equal ['key1','key2'], @i.chunk_keys
|
341
|
+
tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[-1]}/${tag[-2]}/${key1}/${key2}/tail"
|
342
|
+
t = event_time('2016-04-11 20:30:00 +0900')
|
343
|
+
v = {key1: "value1", key2: "value2"}
|
344
|
+
c = if api == :chunk
|
345
|
+
create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
|
346
|
+
else
|
347
|
+
create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
|
348
|
+
end
|
349
|
+
assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/output/test/value1/value2/tail", @i.extract_placeholders(tmpl, c)
|
350
|
+
end
|
351
|
+
|
352
|
+
data(:new_api => :chunk,
|
353
|
+
:old_api => :metadata)
|
354
|
+
test '#extract_placeholders removes out-of-range tag part and unknown variable placeholders' do |api|
|
355
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
|
356
|
+
assert @i.chunk_key_time
|
357
|
+
assert @i.chunk_key_tag
|
358
|
+
assert_equal ['key1','key2'], @i.chunk_keys
|
359
|
+
tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[3]}/${tag[-4]}/${key3}/${key4}/tail"
|
360
|
+
t = event_time('2016-04-11 20:30:00 +0900')
|
361
|
+
v = {key1: "value1", key2: "value2"}
|
362
|
+
c = if api == :chunk
|
363
|
+
create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v)
|
364
|
+
else
|
365
|
+
create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
|
366
|
+
end
|
367
|
+
assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/////tail", @i.extract_placeholders(tmpl, c)
|
368
|
+
end
|
369
|
+
|
370
|
+
test '#extract_placeholders logs warn message if metadata is passed for ${chunk_id} placeholder' do
|
371
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
372
|
+
tmpl = "/mypath/${chunk_id}/tail"
|
373
|
+
t = event_time('2016-04-11 20:30:00 +0900')
|
374
|
+
v = {key1: "value1", key2: "value2"}
|
375
|
+
m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
|
376
|
+
@i.extract_placeholders(tmpl, m)
|
377
|
+
logs = @i.log.out.logs
|
378
|
+
assert { logs.any? { |log| log.include?("${chunk_id} is not allowed in this plugin") } }
|
379
|
+
end
|
380
|
+
|
381
|
+
sub_test_case '#placeholder_validators' do
|
382
|
+
test 'returns validators for time, tag and keys when a template has placeholders even if plugin is not configured with these keys' do
|
383
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
384
|
+
validators = @i.placeholder_validators(:path, "/my/path/${tag}/${username}/file.%Y%m%d_%H%M.log")
|
385
|
+
assert_equal 3, validators.size
|
386
|
+
assert_equal 1, validators.select(&:time?).size
|
387
|
+
assert_equal 1, validators.select(&:tag?).size
|
388
|
+
assert_equal 1, validators.select(&:keys?).size
|
389
|
+
end
|
390
|
+
|
391
|
+
test 'returns validators for time, tag and keys when a plugin is configured with these keys even if a template does not have placeholders' do
|
392
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,username', {'timekey' => 60})]))
|
393
|
+
validators = @i.placeholder_validators(:path, "/my/path/file.log")
|
394
|
+
assert_equal 3, validators.size
|
395
|
+
assert_equal 1, validators.select(&:time?).size
|
396
|
+
assert_equal 1, validators.select(&:tag?).size
|
397
|
+
assert_equal 1, validators.select(&:keys?).size
|
398
|
+
end
|
399
|
+
|
400
|
+
test 'returns a validator for time if a template has timestamp placeholders' do
|
401
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
402
|
+
validators = @i.placeholder_validators(:path, "/my/path/file.%Y-%m-%d.log")
|
403
|
+
assert_equal 1, validators.size
|
404
|
+
assert_equal 1, validators.select(&:time?).size
|
405
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.%Y-%m-%d.log' has timestamp placeholders, but chunk key 'time' is not configured") do
|
406
|
+
validators.first.validate!
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
test 'returns a validator for time if a plugin is configured with time key' do
|
411
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {'timekey' => '30'})]))
|
412
|
+
validators = @i.placeholder_validators(:path, "/my/path/to/file.log")
|
413
|
+
assert_equal 1, validators.size
|
414
|
+
assert_equal 1, validators.select(&:time?).size
|
415
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/to/file.log' doesn't have timestamp placeholders for timekey 30") do
|
416
|
+
validators.first.validate!
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
test 'returns a validator for tag if a template has tag placeholders' do
|
421
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
422
|
+
validators = @i.placeholder_validators(:path, "/my/path/${tag}/file.log")
|
423
|
+
assert_equal 1, validators.size
|
424
|
+
assert_equal 1, validators.select(&:tag?).size
|
425
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${tag}/file.log' has tag placeholders, but chunk key 'tag' is not configured") do
|
426
|
+
validators.first.validate!
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
test 'returns a validator for tag if a plugin is configured with tag key' do
|
431
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag')]))
|
432
|
+
validators = @i.placeholder_validators(:path, "/my/path/file.log")
|
433
|
+
assert_equal 1, validators.size
|
434
|
+
assert_equal 1, validators.select(&:tag?).size
|
435
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have tag placeholder") do
|
436
|
+
validators.first.validate!
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
test 'returns a validator for variable keys if a template has variable placeholders' do
|
441
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
442
|
+
validators = @i.placeholder_validators(:path, "/my/path/${username}/file.${group}.log")
|
443
|
+
assert_equal 1, validators.size
|
444
|
+
assert_equal 1, validators.select(&:keys?).size
|
445
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${username}/file.${group}.log' has placeholders, but chunk keys doesn't have keys group,username") do
|
446
|
+
validators.first.validate!
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
test 'returns a validator for variable keys if a plugin is configured with variable keys' do
|
451
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,group')]))
|
452
|
+
validators = @i.placeholder_validators(:path, "/my/path/file.log")
|
453
|
+
assert_equal 1, validators.size
|
454
|
+
assert_equal 1, validators.select(&:keys?).size
|
455
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have enough placeholders for keys group,username") do
|
456
|
+
validators.first.validate!
|
457
|
+
end
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
sub_test_case '#placeholder_validate!' do
|
462
|
+
test 'raises configuration error for a template when timestamp placeholders exist but time key is missing' do
|
463
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
464
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /path/without/timestamp/file.%Y%m%d-%H%M.log' has timestamp placeholders, but chunk key 'time' is not configured") do
|
465
|
+
@i.placeholder_validate!(:path, "/path/without/timestamp/file.%Y%m%d-%H%M.log")
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
test 'raises configuration error for a template without timestamp placeholders when timekey is configured' do
|
470
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {"timekey" => 180})]))
|
471
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have timestamp placeholders for timekey 180") do
|
472
|
+
@i.placeholder_validate!(:path, "/my/path/file.log")
|
473
|
+
end
|
474
|
+
assert_nothing_raised do
|
475
|
+
@i.placeholder_validate!(:path, "/my/path/%Y%m%d/file.%H%M.log")
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
test 'raises configuration error for a template with timestamp placeholders when plugin is configured more fine timekey' do
|
480
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {"timekey" => 180})]))
|
481
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.%Y%m%d_%H.log' doesn't have timestamp placeholder for hour('%H') for timekey 180") do
|
482
|
+
@i.placeholder_validate!(:path, "/my/path/file.%Y%m%d_%H.log")
|
483
|
+
end
|
484
|
+
assert_nothing_raised do
|
485
|
+
@i.placeholder_validate!(:path, "/my/path/file.%Y%m%d_%H%M.log")
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
test 'raises configuration error for a template when tag placeholders exist but tag key is missing' do
|
490
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
491
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${tag}/file.${tag[2]}.log' has tag placeholders, but chunk key 'tag' is not configured") do
|
492
|
+
@i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[2]}.log")
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
test 'raises configuration error for a template without tag placeholders when tagkey is configured' do
|
497
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag')]))
|
498
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have tag placeholder") do
|
499
|
+
@i.placeholder_validate!(:path, "/my/path/file.log")
|
500
|
+
end
|
501
|
+
assert_nothing_raised do
|
502
|
+
@i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[2]}.log")
|
503
|
+
end
|
504
|
+
assert_nothing_raised do
|
505
|
+
@i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[-1]}.log")
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
test 'raises configuration error for a template when variable key placeholders exist but chunk keys are missing' do
|
510
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
|
511
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${service}/file.${username}.log' has placeholders, but chunk keys doesn't have keys service,username") do
|
512
|
+
@i.placeholder_validate!(:path, "/my/path/${service}/file.${username}.log")
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
test 'raises configuration error for a template without variable key placeholders when chunk keys are configured' do
|
517
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,service')]))
|
518
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.log' doesn't have enough placeholders for keys service,username") do
|
519
|
+
@i.placeholder_validate!(:path, "/my/path/file.log")
|
520
|
+
end
|
521
|
+
assert_nothing_raised do
|
522
|
+
@i.placeholder_validate!(:path, "/my/path/${service}/file.${username}.log")
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
test 'raise configuration error for a template and configuration with keys mismatch' do
|
527
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'username,service')]))
|
528
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/file.${username}.log' doesn't have enough placeholders for keys service") do
|
529
|
+
@i.placeholder_validate!(:path, "/my/path/file.${username}.log")
|
530
|
+
end
|
531
|
+
assert_raise Fluent::ConfigError.new("Parameter 'path: /my/path/${service}/file.log' doesn't have enough placeholders for keys username") do
|
532
|
+
@i.placeholder_validate!(:path, "/my/path/${service}/file.log")
|
533
|
+
end
|
534
|
+
assert_nothing_raised do
|
535
|
+
@i.placeholder_validate!(:path, "/my/path/${service}/file.${username}.log")
|
536
|
+
end
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
test '#get_placeholders_time returns seconds,title and example placeholder for a template' do
|
541
|
+
s, t, e = @i.get_placeholders_time("/path/to/dir/yay")
|
542
|
+
assert_nil s
|
543
|
+
assert_nil t
|
544
|
+
assert_nil e
|
545
|
+
|
546
|
+
s, t, e = @i.get_placeholders_time("/path/to/%Y%m%d/yay")
|
547
|
+
assert_equal 86400, s
|
548
|
+
assert_equal :day, t
|
549
|
+
assert_equal '%d', e
|
550
|
+
s, t, e = @i.get_placeholders_time("my birthday! at %F")
|
551
|
+
assert_equal 86400, s
|
552
|
+
assert_equal :day, t
|
553
|
+
assert_equal '%d', e
|
554
|
+
|
555
|
+
s, t, e = @i.get_placeholders_time("myfile.%Y-%m-%d_%H.log")
|
556
|
+
assert_equal 3600, s
|
557
|
+
assert_equal :hour, t
|
558
|
+
assert_equal '%H', e
|
559
|
+
|
560
|
+
s, t, e = @i.get_placeholders_time("part-%Y%m%d-%H%M.ts")
|
561
|
+
assert_equal 60, s
|
562
|
+
assert_equal :minute, t
|
563
|
+
assert_equal '%M', e
|
564
|
+
|
565
|
+
s, t, e = @i.get_placeholders_time("my first data at %F %T %z")
|
566
|
+
assert_equal 1, s
|
567
|
+
assert_equal :second, t
|
568
|
+
assert_equal '%S', e
|
569
|
+
end
|
570
|
+
|
571
|
+
test '#get_placeholders_tag returns a list of tag part position for a template' do
|
572
|
+
assert_equal [], @i.get_placeholders_tag("db.table")
|
573
|
+
assert_equal [], @i.get_placeholders_tag("db.table_${non_tag}")
|
574
|
+
assert_equal [-1], @i.get_placeholders_tag("table_${tag}")
|
575
|
+
assert_equal [0, 1], @i.get_placeholders_tag("db_${tag[0]}.table_${tag[1]}")
|
576
|
+
assert_equal [-1, 0], @i.get_placeholders_tag("/treedir/${tag[0]}/${tag}")
|
577
|
+
end
|
578
|
+
|
579
|
+
test '#get_placeholders_keys returns a list of keys for a template' do
|
580
|
+
assert_equal [], @i.get_placeholders_keys("/path/to/my/data/file.log")
|
581
|
+
assert_equal [], @i.get_placeholders_keys("/path/to/my/${tag}/file.log")
|
582
|
+
assert_equal ['key1', 'key2'], @i.get_placeholders_keys("/path/to/${key2}/${tag}/file.${key1}.log")
|
583
|
+
assert_equal ['.hidden', '0001', '@timestamp', 'a_key', 'my-domain'], @i.get_placeholders_keys("http://${my-domain}/${.hidden}/${0001}/${a_key}?timestamp=${@timestamp}")
|
584
|
+
end
|
585
|
+
|
586
|
+
data('include space' => 'ke y',
|
587
|
+
'bracket notation' => "$['key']",
|
588
|
+
'invalid notation' => "$.ke y")
|
589
|
+
test 'configure checks invalid chunk keys' do |chunk_keys|
|
590
|
+
i = create_output(:buffered)
|
591
|
+
assert_raise Fluent::ConfigError do
|
592
|
+
i.configure(config_element('ROOT' , '', {}, [config_element('buffer', chunk_keys)]))
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
test '#metadata returns object which contains tag/timekey/variables from records as specified in configuration' do
|
597
|
+
tag = 'test.output'
|
598
|
+
time = event_time('2016-04-12 15:31:23 -0700')
|
599
|
+
timekey = event_time('2016-04-12 15:00:00 -0700')
|
600
|
+
record = {"key1" => "value1", "num1" => 1, "message" => "my message", "nest" => {"key" => "nested value"}}
|
601
|
+
|
602
|
+
i1 = create_output(:buffered)
|
603
|
+
i1.configure(config_element('ROOT','',{},[config_element('buffer', '')]))
|
604
|
+
assert_equal create_metadata(), i1.metadata(tag, time, record)
|
605
|
+
|
606
|
+
i2 = create_output(:buffered)
|
607
|
+
i2.configure(config_element('ROOT','',{},[config_element('buffer', 'tag')]))
|
608
|
+
assert_equal create_metadata(tag: tag), i2.metadata(tag, time, record)
|
609
|
+
|
610
|
+
i3 = create_output(:buffered)
|
611
|
+
i3.configure(config_element('ROOT','',{},[config_element('buffer', 'time', {"timekey" => 3600, "timekey_zone" => "-0700"})]))
|
612
|
+
assert_equal create_metadata(timekey: timekey), i3.metadata(tag, time, record)
|
613
|
+
|
614
|
+
i4 = create_output(:buffered)
|
615
|
+
i4.configure(config_element('ROOT','',{},[config_element('buffer', 'key1', {})]))
|
616
|
+
assert_equal create_metadata(variables: {key1: "value1"}), i4.metadata(tag, time, record)
|
617
|
+
|
618
|
+
i5 = create_output(:buffered)
|
619
|
+
i5.configure(config_element('ROOT','',{},[config_element('buffer', 'key1,num1', {})]))
|
620
|
+
assert_equal create_metadata(variables: {key1: "value1", num1: 1}), i5.metadata(tag, time, record)
|
621
|
+
|
622
|
+
i6 = create_output(:buffered)
|
623
|
+
i6.configure(config_element('ROOT','',{},[config_element('buffer', 'tag,time', {"timekey" => 3600, "timekey_zone" => "-0700"})]))
|
624
|
+
assert_equal create_metadata(timekey: timekey, tag: tag), i6.metadata(tag, time, record)
|
625
|
+
|
626
|
+
i7 = create_output(:buffered)
|
627
|
+
i7.configure(config_element('ROOT','',{},[config_element('buffer', 'tag,num1', {"timekey" => 3600, "timekey_zone" => "-0700"})]))
|
628
|
+
assert_equal create_metadata(tag: tag, variables: {num1: 1}), i7.metadata(tag, time, record)
|
629
|
+
|
630
|
+
i8 = create_output(:buffered)
|
631
|
+
i8.configure(config_element('ROOT','',{},[config_element('buffer', 'time,tag,key1', {"timekey" => 3600, "timekey_zone" => "-0700"})]))
|
632
|
+
assert_equal create_metadata(timekey: timekey, tag: tag, variables: {key1: "value1"}), i8.metadata(tag, time, record)
|
633
|
+
|
634
|
+
i9 = create_output(:buffered)
|
635
|
+
i9.configure(config_element('ROOT','',{},[config_element('buffer', 'key1,$.nest.key', {})]))
|
636
|
+
assert_equal create_metadata(variables: {:key1 => "value1", :"$.nest.key" => 'nested value'}), i9.metadata(tag, time, record)
|
637
|
+
end
|
638
|
+
|
639
|
+
test '#emit calls #process via #emit_sync for non-buffered output' do
|
640
|
+
i = create_output(:sync)
|
641
|
+
process_called = false
|
642
|
+
i.register(:process){|tag, es| process_called = true }
|
643
|
+
i.configure(config_element())
|
644
|
+
i.start
|
645
|
+
i.after_start
|
646
|
+
|
647
|
+
t = event_time()
|
648
|
+
i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
|
649
|
+
|
650
|
+
assert process_called
|
651
|
+
|
652
|
+
i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
|
653
|
+
end
|
654
|
+
|
655
|
+
test '#emit calls #format for buffered output' do
|
656
|
+
i = create_output(:buffered)
|
657
|
+
format_called_times = 0
|
658
|
+
i.register(:format){|tag, time, record| format_called_times += 1; '' }
|
659
|
+
i.configure(config_element())
|
660
|
+
i.start
|
661
|
+
i.after_start
|
662
|
+
|
663
|
+
t = event_time()
|
664
|
+
i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
|
665
|
+
|
666
|
+
assert_equal 2, format_called_times
|
667
|
+
|
668
|
+
i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
|
669
|
+
end
|
670
|
+
|
671
|
+
test '#prefer_buffered_processing (returns false) decides non-buffered without <buffer> section' do
|
672
|
+
i = create_output(:full)
|
673
|
+
|
674
|
+
process_called = false
|
675
|
+
format_called_times = 0
|
676
|
+
i.register(:process){|tag, es| process_called = true }
|
677
|
+
i.register(:format){|tag, time, record| format_called_times += 1; '' }
|
678
|
+
|
679
|
+
i.configure(config_element())
|
680
|
+
i.register(:prefer_buffered_processing){ false } # delayed decision is possible to change after (output's) configure
|
681
|
+
i.start
|
682
|
+
i.after_start
|
683
|
+
|
684
|
+
assert !i.prefer_buffered_processing
|
685
|
+
|
686
|
+
t = event_time()
|
687
|
+
i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
|
688
|
+
|
689
|
+
waiting(4){ Thread.pass until process_called }
|
690
|
+
|
691
|
+
assert process_called
|
692
|
+
assert_equal 0, format_called_times
|
693
|
+
|
694
|
+
i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
|
695
|
+
end
|
696
|
+
|
697
|
+
test '#prefer_buffered_processing (returns true) decides buffered without <buffer> section' do
|
698
|
+
i = create_output(:full)
|
699
|
+
|
700
|
+
process_called = false
|
701
|
+
format_called_times = 0
|
702
|
+
i.register(:process){|tag, es| process_called = true }
|
703
|
+
i.register(:format){|tag, time, record| format_called_times += 1; '' }
|
704
|
+
|
705
|
+
i.configure(config_element())
|
706
|
+
i.register(:prefer_buffered_processing){ true } # delayed decision is possible to change after (output's) configure
|
707
|
+
i.start
|
708
|
+
i.after_start
|
709
|
+
|
710
|
+
assert i.prefer_buffered_processing
|
711
|
+
|
712
|
+
t = event_time()
|
713
|
+
i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
|
714
|
+
|
715
|
+
assert !process_called
|
716
|
+
assert_equal 2, format_called_times
|
717
|
+
|
718
|
+
i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
|
719
|
+
end
|
720
|
+
|
721
|
+
test 'output plugin will call #write for normal buffered plugin to flush buffer chunks' do
|
722
|
+
i = create_output(:buffered)
|
723
|
+
write_called = false
|
724
|
+
i.register(:write){ |chunk| write_called = true }
|
725
|
+
|
726
|
+
i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
|
727
|
+
i.start
|
728
|
+
i.after_start
|
729
|
+
|
730
|
+
t = event_time()
|
731
|
+
i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
|
732
|
+
i.force_flush
|
733
|
+
|
734
|
+
waiting(4){ Thread.pass until write_called }
|
735
|
+
|
736
|
+
assert write_called
|
737
|
+
|
738
|
+
i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
|
739
|
+
end
|
740
|
+
|
741
|
+
test 'output plugin will call #try_write for plugin supports delayed commit only to flush buffer chunks' do
|
742
|
+
i = create_output(:delayed)
|
743
|
+
try_write_called = false
|
744
|
+
i.register(:try_write){|chunk| try_write_called = true; commit_write(chunk.unique_id) }
|
745
|
+
|
746
|
+
i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
|
747
|
+
i.start
|
748
|
+
i.after_start
|
749
|
+
|
750
|
+
t = event_time()
|
751
|
+
i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
|
752
|
+
i.force_flush
|
753
|
+
|
754
|
+
waiting(4){ Thread.pass until try_write_called }
|
755
|
+
|
756
|
+
assert try_write_called
|
757
|
+
|
758
|
+
i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
|
759
|
+
end
|
760
|
+
|
761
|
+
test '#prefer_delayed_commit (returns false) decides delayed commit is disabled if both are implemented' do
|
762
|
+
i = create_output(:full)
|
763
|
+
write_called = false
|
764
|
+
try_write_called = false
|
765
|
+
i.register(:write){ |chunk| write_called = true }
|
766
|
+
i.register(:try_write){|chunk| try_write_called = true; commit_write(chunk.unique_id) }
|
767
|
+
|
768
|
+
i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
|
769
|
+
i.register(:prefer_delayed_commit){ false } # delayed decision is possible to change after (output's) configure
|
770
|
+
i.start
|
771
|
+
i.after_start
|
772
|
+
|
773
|
+
assert !i.prefer_delayed_commit
|
774
|
+
|
775
|
+
t = event_time()
|
776
|
+
i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
|
777
|
+
i.force_flush
|
778
|
+
|
779
|
+
waiting(4){ Thread.pass until write_called || try_write_called }
|
780
|
+
|
781
|
+
assert write_called
|
782
|
+
assert !try_write_called
|
783
|
+
|
784
|
+
i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
|
785
|
+
end
|
786
|
+
|
787
|
+
test '#prefer_delayed_commit (returns true) decides delayed commit is enabled if both are implemented' do
|
788
|
+
i = create_output(:full)
|
789
|
+
write_called = false
|
790
|
+
try_write_called = false
|
791
|
+
i.register(:write){ |chunk| write_called = true }
|
792
|
+
i.register(:try_write){|chunk| try_write_called = true; commit_write(chunk.unique_id) }
|
793
|
+
|
794
|
+
i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
|
795
|
+
i.register(:prefer_delayed_commit){ true } # delayed decision is possible to change after (output's) configure
|
796
|
+
i.start
|
797
|
+
i.after_start
|
798
|
+
|
799
|
+
assert i.prefer_delayed_commit
|
800
|
+
|
801
|
+
t = event_time()
|
802
|
+
i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
|
803
|
+
i.force_flush
|
804
|
+
|
805
|
+
waiting(4){ Thread.pass until write_called || try_write_called }
|
806
|
+
|
807
|
+
assert !write_called
|
808
|
+
assert try_write_called
|
809
|
+
|
810
|
+
i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
|
811
|
+
end
|
812
|
+
|
813
|
+
test 'flush_interval is ignored when flush_mode is not interval' do
|
814
|
+
mock(@i.log).warn("'flush_interval' is ignored because default 'flush_mode' is not 'interval': 'lazy'")
|
815
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {'timekey' => 60*30, 'flush_interval' => 10})]))
|
816
|
+
end
|
817
|
+
|
818
|
+
data(:lazy => 'lazy', :immediate => 'immediate')
|
819
|
+
test 'flush_interval and non-interval flush_mode is exclusive ' do |mode|
|
820
|
+
assert_raise Fluent::ConfigError.new("'flush_interval' can't be specified when 'flush_mode' is not 'interval' explicitly: '#{mode}'") do
|
821
|
+
@i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {'flush_mode' => mode, 'flush_interval' => 10})]))
|
822
|
+
end
|
823
|
+
end
|
824
|
+
|
825
|
+
test 'flush_mode is set to interval when flush_interval with v0.12 configuration is given' do
|
826
|
+
mock(@i.log).info("'flush_interval' is configured at out side of <buffer>. 'flush_mode' is set to 'interval' to keep existing behaviour")
|
827
|
+
@i.configure(config_element('ROOT', '', {'flush_interval' => 60}, []))
|
828
|
+
assert_equal :interval, @i.instance_variable_get(:@flush_mode)
|
829
|
+
end
|
830
|
+
|
831
|
+
sub_test_case 'configure secondary' do
|
832
|
+
test "Warn if primary type is different from secondary type and either primary or secondary has custom_format" do
|
833
|
+
o = create_output(:buffered)
|
834
|
+
mock(o.log).warn("secondary type should be same with primary one",
|
835
|
+
{ primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" })
|
836
|
+
|
837
|
+
o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
|
838
|
+
assert_not_nil o.instance_variable_get(:@secondary)
|
839
|
+
end
|
840
|
+
|
841
|
+
test "don't warn if primary type is the same as secondary type" do
|
842
|
+
o = Fluent::Plugin::TestOutput.new
|
843
|
+
mock(o.log).warn("secondary type should be same with primary one",
|
844
|
+
{ primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
|
845
|
+
|
846
|
+
o.configure(config_element('ROOT','',{'name' => "cool2"},
|
847
|
+
[config_element('secondary','',{'@type'=>'test', 'name' => "cool"}),
|
848
|
+
config_element('buffer','',{'@type'=>'memory'})]
|
849
|
+
))
|
850
|
+
assert_not_nil o.instance_variable_get(:@secondary)
|
851
|
+
end
|
852
|
+
|
853
|
+
test "don't warn if primary type is different from secondary type and both don't have custom_format" do
|
854
|
+
o = create_output(:standard)
|
855
|
+
mock(o.log).warn("secondary type should be same with primary one",
|
856
|
+
{ primary: o.class.to_s, secondary: "Fluent::Plugin::TestOutput" }).never
|
857
|
+
|
858
|
+
o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'test', 'name' => "cool"})]))
|
859
|
+
assert_not_nil o.instance_variable_get(:@secondary)
|
860
|
+
end
|
861
|
+
|
862
|
+
test "raise configuration error if secondary type specifies non buffered output" do
|
863
|
+
o = create_output(:standard)
|
864
|
+
assert_raise Fluent::ConfigError do
|
865
|
+
o.configure(config_element('ROOT','',{},[config_element('secondary','',{'@type'=>'copy'})]))
|
866
|
+
end
|
867
|
+
end
|
868
|
+
end
|
869
|
+
end
|
870
|
+
|
871
|
+
sub_test_case 'sync output feature' do
|
872
|
+
setup do
|
873
|
+
@i = create_output(:sync)
|
874
|
+
end
|
875
|
+
|
876
|
+
test 'raises configuration error if <buffer> section is specified' do
|
877
|
+
assert_raise Fluent::ConfigError do
|
878
|
+
@i.configure(config_element('ROOT','',{},[config_element('buffer', '')]))
|
879
|
+
end
|
880
|
+
end
|
881
|
+
|
882
|
+
test 'raises configuration error if <secondary> section is specified' do
|
883
|
+
assert_raise Fluent::ConfigError do
|
884
|
+
@i.configure(config_element('ROOT','',{},[config_element('secondary','')]))
|
885
|
+
end
|
886
|
+
end
|
887
|
+
|
888
|
+
test '#process is called for each event streams' do
|
889
|
+
ary = []
|
890
|
+
@i.register(:process){|tag, es| ary << [tag, es] }
|
891
|
+
@i.configure(config_element())
|
892
|
+
@i.start
|
893
|
+
@i.after_start
|
894
|
+
|
895
|
+
t = event_time()
|
896
|
+
es = Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ])
|
897
|
+
5.times do
|
898
|
+
@i.emit_events('tag', es)
|
899
|
+
end
|
900
|
+
assert_equal 5, ary.size
|
901
|
+
|
902
|
+
@i.stop; @i.before_shutdown; @i.shutdown; @i.after_shutdown; @i.close; @i.terminate
|
903
|
+
end
|
904
|
+
end
|
905
|
+
|
906
|
+
sub_test_case '#generate_format_proc' do
|
907
|
+
test "when output doesn't have <buffer>" do
|
908
|
+
i = create_output(:sync)
|
909
|
+
i.configure(config_element('ROOT', '', {}, []))
|
910
|
+
assert_equal Fluent::Plugin::Output::FORMAT_MSGPACK_STREAM, i.generate_format_proc
|
911
|
+
end
|
912
|
+
|
913
|
+
test "when output doesn't have <buffer> and time_as_integer is true" do
|
914
|
+
i = create_output(:sync)
|
915
|
+
i.configure(config_element('ROOT', '', {'time_as_integer' => true}))
|
916
|
+
assert_equal Fluent::Plugin::Output::FORMAT_MSGPACK_STREAM_TIME_INT, i.generate_format_proc
|
917
|
+
end
|
918
|
+
|
919
|
+
test 'when output has <buffer> and compress is gzip' do
|
920
|
+
i = create_output(:buffered)
|
921
|
+
i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {'compress' => 'gzip'})]))
|
922
|
+
assert_equal Fluent::Plugin::Output::FORMAT_COMPRESSED_MSGPACK_STREAM, i.generate_format_proc
|
923
|
+
end
|
924
|
+
|
925
|
+
test 'when output has <buffer> and compress is gzip and time_as_integer is true' do
|
926
|
+
i = create_output(:buffered)
|
927
|
+
i.configure(config_element('ROOT', '', {'time_as_integer' => true}, [config_element('buffer', '', {'compress' => 'gzip'})]))
|
928
|
+
assert_equal Fluent::Plugin::Output::FORMAT_COMPRESSED_MSGPACK_STREAM_TIME_INT, i.generate_format_proc
|
929
|
+
end
|
930
|
+
|
931
|
+
test 'when output has <buffer> and compress is text' do
|
932
|
+
i = create_output(:buffered)
|
933
|
+
i.configure(config_element('ROOT', '', {}, [config_element('buffer', '', {'compress' => 'text'})]))
|
934
|
+
assert_equal Fluent::Plugin::Output::FORMAT_MSGPACK_STREAM, i.generate_format_proc
|
935
|
+
end
|
936
|
+
end
|
937
|
+
|
938
|
+
sub_test_case 'slow_flush_log_threshold' do
|
939
|
+
def invoke_slow_flush_log_threshold_test(i)
|
940
|
+
i.configure(config_element('ROOT', '', {'slow_flush_log_threshold' => 0.5},
|
941
|
+
[config_element('buffer', '', {"flush_mode" => "immediate", "flush_thread_interval" => 30})]))
|
942
|
+
i.start
|
943
|
+
i.after_start
|
944
|
+
|
945
|
+
t = event_time()
|
946
|
+
i.emit_events('tag', Fluent::ArrayEventStream.new([ [t, {"key" => "value1"}], [t, {"key" => "value2"}] ]))
|
947
|
+
i.force_flush
|
948
|
+
|
949
|
+
waiting(4) { Thread.pass until i.test_finished? }
|
950
|
+
|
951
|
+
yield
|
952
|
+
ensure
|
953
|
+
i.stop; i.before_shutdown; i.shutdown; i.after_shutdown; i.close; i.terminate
|
954
|
+
end
|
955
|
+
|
956
|
+
test '#write flush took longer time than slow_flush_log_threshold' do
|
957
|
+
i = create_output(:buffered)
|
958
|
+
write_called = false
|
959
|
+
i.register(:write) { |chunk| sleep 3 }
|
960
|
+
i.define_singleton_method(:test_finished?) { write_called }
|
961
|
+
i.define_singleton_method(:try_flush) { super(); write_called = true }
|
962
|
+
|
963
|
+
invoke_slow_flush_log_threshold_test(i) {
|
964
|
+
assert write_called
|
965
|
+
logs = i.log.out.logs
|
966
|
+
assert{ logs.any?{|log| log.include?("buffer flush took longer time than slow_flush_log_threshold: elapsed_time") } }
|
967
|
+
}
|
968
|
+
end
|
969
|
+
|
970
|
+
test '#try_write flush took longer time than slow_flush_log_threshold' do
|
971
|
+
i = create_output(:delayed)
|
972
|
+
try_write_called = false
|
973
|
+
i.register(:try_write){ |chunk| sleep 3 }
|
974
|
+
i.define_singleton_method(:test_finished?) { try_write_called }
|
975
|
+
i.define_singleton_method(:try_flush) { super(); try_write_called = true }
|
976
|
+
|
977
|
+
invoke_slow_flush_log_threshold_test(i) {
|
978
|
+
assert try_write_called
|
979
|
+
logs = i.log.out.logs
|
980
|
+
assert{ logs.any?{|log| log.include?("buffer flush took longer time than slow_flush_log_threshold: elapsed_time") } }
|
981
|
+
}
|
982
|
+
end
|
983
|
+
end
|
984
|
+
end
|