From 891ce71120198fa168232a796d4267a3cdb2c91f Mon Sep 17 00:00:00 2001 From: Daijiro Fukuda Date: Wed, 12 Jun 2024 11:56:43 +0900 Subject: [PATCH] parser_json: fix wrong LoadError warning If Oj is not installed, LoadError with the empty message is raised. So, the current condition `/\boj\z/.match?(ex.message)` does not work and the following meaningless warning is displayed. {datetime} [warn]: #x {id} LoadError After this fix, the log message will be: {datetime} [info]: #x {id} Oj is not installed, and failing back to Yajl for json parser Refactor "rescue" logic because this falling back feature is currently only for "oj" (LoadError can not occur for "json" and "yajl"). Signed-off-by: Daijiro Fukuda Co-authored-by: Takuro Ashie --- lib/fluent/plugin/parser_json.rb | 16 ++++------------ test/plugin/test_parser_json.rb | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/fluent/plugin/parser_json.rb b/lib/fluent/plugin/parser_json.rb index 52dd6f5e8f..57d637ded4 100644 --- a/lib/fluent/plugin/parser_json.rb +++ b/lib/fluent/plugin/parser_json.rb @@ -50,23 +50,15 @@ def configure(conf) def configure_json_parser(name) case name when :oj - raise LoadError unless Fluent::OjOptions.available? - [Oj.method(:load), Oj::ParseError] + return [Oj.method(:load), Oj::ParseError] if Fluent::OjOptions.available? + + log&.info "Oj is not installed, and failing back to Yajl for json parser" + configure_json_parser(:yajl) when :json then [JSON.method(:load), JSON::ParserError] when :yajl then [Yajl.method(:load), Yajl::ParseError] else raise "BUG: unknown json parser specified: #{name}" end - rescue LoadError => ex - name = :yajl - if log - if /\boj\z/.match?(ex.message) - log.info "Oj is not installed, and failing back to Yajl for json parser" - else - log.warn ex.message - end - end - retry end def parse(text) diff --git a/test/plugin/test_parser_json.rb b/test/plugin/test_parser_json.rb index 875611eb32..7958f7a282 100644 --- a/test/plugin/test_parser_json.rb +++ b/test/plugin/test_parser_json.rb @@ -8,6 +8,37 @@ def setup @parser = Fluent::Test::Driver::Parser.new(Fluent::Plugin::JSONParser) end + sub_test_case "configure_json_parser" do + data("oj", [:oj, [Oj.method(:load), Oj::ParseError]]) + data("json", [:json, [JSON.method(:load), JSON::ParserError]]) + data("yajl", [:yajl, [Yajl.method(:load), Yajl::ParseError]]) + def test_return_each_loader((input, expected_return)) + result = @parser.instance.configure_json_parser(input) + assert_equal expected_return, result + end + + def test_raise_exception_for_unknown_input + assert_raise RuntimeError do + @parser.instance.configure_json_parser(:unknown) + end + end + + def test_fall_back_oj_to_yajl_if_oj_not_available + stub(Fluent::OjOptions).available? { false } + + result = @parser.instance.configure_json_parser(:oj) + + assert_equal [Yajl.method(:load), Yajl::ParseError], result + logs = @parser.logs.collect do |log| + log.gsub(/\A\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]\d{4} /, "") + end + assert_equal( + ["[info]: Oj is not installed, and failing back to Yajl for json parser\n"], + logs + ) + end + end + data('oj' => 'oj', 'yajl' => 'yajl') def test_parse(data) @parser.configure('json_parser' => data)