From 2f50453663a78b19692e369e43751343b7852231 Mon Sep 17 00:00:00 2001 From: Kenji Okimoto Date: Fri, 23 Mar 2018 16:26:32 +0900 Subject: [PATCH] Support negative index for tag when extract placeholders For example, tag is `fluentd.test.output` `${tag[-1]}` is extracted to `output` `${tag[-2]}` is extracted to `test` It is useful to extract last element of variable length tag. --- lib/fluent/plugin/output.rb | 10 ++++++---- test/plugin/test_output.rb | 23 ++++++++++++++++++++++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/fluent/plugin/output.rb b/lib/fluent/plugin/output.rb index 4a8b42d9b6..5979629f27 100644 --- a/lib/fluent/plugin/output.rb +++ b/lib/fluent/plugin/output.rb @@ -38,7 +38,7 @@ class Output < Base CHUNK_KEY_PATTERN = /^[-_.@a-zA-Z0-9]+$/ CHUNK_KEY_PLACEHOLDER_PATTERN = /\$\{[-_.@$a-zA-Z0-9]+\}/ - CHUNK_TAG_PLACEHOLDER_PATTERN = /\$\{(tag(?:\[\d+\])?)\}/ + CHUNK_TAG_PLACEHOLDER_PATTERN = /\$\{(tag(?:\[-?\d+\])?)\}/ CHUNK_ID_PLACEHOLDER_PATTERN = /\$\{chunk_id\}/ CHUNKING_FIELD_WARN_NUM = 4 @@ -672,7 +672,7 @@ def get_placeholders_tag(str) str.scan(CHUNK_TAG_PLACEHOLDER_PATTERN).map(&:first).each do |ph| if ph == "tag" parts << -1 - elsif ph =~ /^tag\[(\d+)\]$/ + elsif ph =~ /^tag\[(-?\d+)\]$/ parts << $1.to_i end end @@ -708,15 +708,17 @@ def extract_placeholders(str, chunk) @output_time_formatter_cache[str] ||= Fluent::Timezone.formatter(@timekey_zone, str) rvalue = @output_time_formatter_cache[str].call(metadata.timekey) end - # ${tag}, ${tag[0]}, ${tag[1]}, ... + # ${tag}, ${tag[0]}, ${tag[1]}, ... , ${tag[-2]}, ${tag[-1]} if @chunk_key_tag if str.include?('${tag}') rvalue = rvalue.gsub('${tag}', metadata.tag) end if str =~ CHUNK_TAG_PLACEHOLDER_PATTERN hash = {} - metadata.tag.split('.').each_with_index do |part, i| + tag_parts = metadata.tag.split('.') + tag_parts.each_with_index do |part, i| hash["${tag[#{i}]}"] = part + hash["${tag[#{i-tag_parts.size}]}"] = part end rvalue = rvalue.gsub(CHUNK_TAG_PLACEHOLDER_PATTERN, hash) end diff --git a/test/plugin/test_output.rb b/test/plugin/test_output.rb index c1a2dace1c..696f3c3398 100644 --- a/test/plugin/test_output.rb +++ b/test/plugin/test_output.rb @@ -331,6 +331,24 @@ def waiting(seconds) assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/test/output/value1/value2/tail", @i.extract_placeholders(tmpl, c) end + data(:new_api => :chunk, + :old_api => :metadata) + test '#extract_placeholders can extract negative index with tag' do |api| + @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})])) + assert @i.chunk_key_time + assert @i.chunk_key_tag + assert_equal ['key1','key2'], @i.chunk_keys + tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[-1]}/${tag[-2]}/${key1}/${key2}/tail" + t = event_time('2016-04-11 20:30:00 +0900') + v = {key1: "value1", key2: "value2"} + c = if api == :chunk + create_chunk(timekey: t, tag: 'fluentd.test.output', variables: v) + else + create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v) + end + assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/output/test/value1/value2/tail", @i.extract_placeholders(tmpl, c) + end + data(:new_api => :chunk, :old_api => :metadata) test '#extract_placeholders removes out-of-range tag part and unknown variable placeholders' do |api| @@ -338,7 +356,7 @@ def waiting(seconds) assert @i.chunk_key_time assert @i.chunk_key_tag assert_equal ['key1','key2'], @i.chunk_keys - tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[3]}/${tag[4]}/${key3}/${key4}/tail" + tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[3]}/${tag[-4]}/${key3}/${key4}/tail" t = event_time('2016-04-11 20:30:00 +0900') v = {key1: "value1", key2: "value2"} c = if api == :chunk @@ -483,6 +501,9 @@ def waiting(seconds) assert_nothing_raised do @i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[2]}.log") end + assert_nothing_raised do + @i.placeholder_validate!(:path, "/my/path/${tag}/file.${tag[-1]}.log") + end end test 'raises configuration error for a template when variable key placeholders exist but chunk keys are missing' do