fluentd 0.14.21 → 0.14.22.rc1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0c04447f174a283ac32276dd0dbde42bfabac9b
4
- data.tar.gz: dc5da1036653db4373345239dc4486918423e479
3
+ metadata.gz: cabaaf075c80b44f6b8f77efb057ad809212f871
4
+ data.tar.gz: 7092d208bb92fe4992764dbe418b117976a7ba66
5
5
  SHA512:
6
- metadata.gz: 7015711b0401b911a3242e96bf90f5bd56693e1ccc62565d2cee241403354599a3c29bf487f10989297bfcf41a7d0c90c274396f0a07dc9c338fc26a66769323
7
- data.tar.gz: 9cd584791a19c95166e34e325f104cb38918769c836f1779008e77e7d36367ccb786d3fa9b16381d8d9ce680ec22b903b60e9a8e0244f635954d188c6a5e2a6c
6
+ metadata.gz: 235273ae1d58e4e3c3be98642805cb9d62ac3df2c75cc94622ee78bf62b65e5927aec1ad9ba2043f4c06b65abed6a490340243fb1b82d42e6e0e8e9bd8d4a500
7
+ data.tar.gz: dcab5670899cb22e7914cffcb2a31f590d054f31ec44b500720cbbc02e59c4f22a9da02b2078035dc5dbf7eea625c34f60f8002eb9c83271c60f0b02883a0a9c
@@ -0,0 +1,5 @@
1
+ # Fluentd Adopters
2
+
3
+ Fluentd is widely used by hundred of companies, please refer to the testimonial section of our project website to learn more about it:
4
+
5
+ https://www.fluentd.org/testimonials
File without changes
@@ -4,7 +4,7 @@ We'd love your contribution. Here are the guidelines!
4
4
 
5
5
  ## Got a question or problem?
6
6
 
7
- RESOURCES of [Official site](http://www.fluentd.org/) and [Fluentd documentation](http://docs.fluentd.org/) may help you.
7
+ RESOURCES of [Official site](https://www.fluentd.org/) and [Fluentd documentation](https://docs.fluentd.org/) may help you.
8
8
 
9
9
  If you have further questions about Fluentd and plugins, please direct these to [Mailing List](https://groups.google.com/forum/#!forum/fluentd).
10
10
  Don't use Github issue for asking questions. Here are examples:
@@ -1,6 +1,6 @@
1
1
  # Fluentd Enterprise Providers
2
2
 
3
- [Fluentd](http://www.fluentd.org) is widely adopted in the enterprise and in most of scenarios, production environments requires special support and services. The following document describe the certified service providers and further guidelines to apply to become one.
3
+ [Fluentd](https://www.fluentd.org) is widely adopted in the enterprise and in most of scenarios, production environments requires special support and services. The following document describe the certified service providers and further guidelines to apply to become one.
4
4
 
5
5
  ## Fluentd Providers
6
6
 
@@ -10,7 +10,7 @@ The following section lists the companies that provides Support, Consulting Serv
10
10
 
11
11
  ### Treasure Data
12
12
 
13
- [Treasure Data](https://www.treasuredata.com) is one of the principal sponsors of Fluentd, it provides technical support, consulting services and [Fluentd Enterprise](https://fluentd.treasuredata.com/), a Fluentd-on steroids with enhanced security and connectors for enterprise backends such as [Apache Kafka](http://kafka.apache.org) and [Splunk](http://www.splunk.com) within others.
13
+ [Treasure Data](https://www.treasuredata.com) is one of the principal sponsors of Fluentd, it provides technical support, consulting services and [Fluentd Enterprise](https://fluentd.treasuredata.com/), a Fluentd-on steroids with enhanced security and connectors for enterprise backends such as [Apache Kafka](https://kafka.apache.org) and [Splunk](https://www.splunk.com) within others.
14
14
 
15
15
  For more details about Fluentd Enterprise provided by Treasure Data, click [here](https://fluentd.treasuredata.com/).
16
16
 
@@ -35,7 +35,7 @@ In order to be listed as a service provider, please send an email using your cor
35
35
  - What kind of services around Fluentd do you provide ?
36
36
  - Community
37
37
  - List of activities of your company within the Fluentd community in the last 12 months
38
- - Are you a member of the [Cloud Native Computing Foundation](http://cncf.io) ?
38
+ - Are you a member of the [Cloud Native Computing Foundation](https://cncf.io) ?
39
39
 
40
40
  ### Maintainers / Recipients
41
41
 
data/README.md CHANGED
@@ -5,10 +5,10 @@ Fluentd: Open-Source Log Collector
5
5
  [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1189/badge)](https://bestpractices.coreinfrastructure.org/projects/1189)
6
6
  [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Ffluent%2Ffluentd.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Ffluent%2Ffluentd?ref=badge_shield)
7
7
 
8
- [Fluentd](http://fluentd.org/) collects events from various data sources and writes them to files, RDBMS, NoSQL, IaaS, SaaS, Hadoop and so on. Fluentd helps you unify your logging infrastructure (Learn more about the [Unified Logging Layer](http://www.fluentd.org/blog/unified-logging-layer)).
8
+ [Fluentd](https://fluentd.org/) collects events from various data sources and writes them to files, RDBMS, NoSQL, IaaS, SaaS, Hadoop and so on. Fluentd helps you unify your logging infrastructure (Learn more about the [Unified Logging Layer](https://www.fluentd.org/blog/unified-logging-layer)).
9
9
 
10
10
  <p align="center">
11
- <img src="http://docs.fluentd.org/images/fluentd-architecture.png" width="500px"/>
11
+ <img src="https://docs.fluentd.org/images/fluentd-architecture.png" width="500px"/>
12
12
  </p>
13
13
 
14
14
  An event consists of *tag*, *time* and *record*. Tag is a string separated with '.' (e.g. myapp.access). It is used to categorize events. Time is a UNIX time recorded at occurrence of an event. Record is a JSON object.
@@ -62,16 +62,16 @@ Many enterprises run Fluentd in production to handle all of their logging needs.
62
62
 
63
63
  [Fluentd UI](https://github.com/fluent/fluentd-ui) is a graphical user interface to start/stop/configure Fluentd.
64
64
 
65
- <p align="center"><img width="500" src="http://www.fluentd.org/images/blog/fluentd-ui.gif"/></p>
65
+ <p align="center"><img width="500" src="https://www.fluentd.org/images/blog/fluentd-ui.gif"/></p>
66
66
 
67
67
  ## More Information
68
68
 
69
69
  - Website: https://www.fluentd.org/
70
- - Documentation: http://docs.fluentd.org/
71
- - Project repository: http://github.com/fluent
72
- - Discussion: http://groups.google.com/group/fluentd
73
- - Slack / Community: http://slack.fluentd.org
74
- - Newsletters: http://get.treasuredata.com/Fluentd_education
70
+ - Documentation: https://docs.fluentd.org/
71
+ - Project repository: https://github.com/fluent
72
+ - Discussion: https://groups.google.com/group/fluentd
73
+ - Slack / Community: https://slack.fluentd.org
74
+ - Newsletters: https://www.fluentd.org/newsletter_signup
75
75
  - Author: Sadayuki Furuhashi
76
76
  - Copyright: (c) 2011 FURUHASHI Sadayuki
77
77
  - License: Apache License, Version 2.0
@@ -8,7 +8,7 @@ Gem::Specification.new do |gem|
8
8
  gem.email = ["frsyuki@gmail.com"]
9
9
  gem.description = %q{Fluentd is an open source data collector designed to scale and simplify log management. It can collect, process and ship many kinds of data in near real-time.}
10
10
  gem.summary = %q{Fluentd event collector}
11
- gem.homepage = "http://fluentd.org/"
11
+ gem.homepage = "https://fluentd.org/"
12
12
 
13
13
  gem.files = `git ls-files`.split($\)
14
14
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -25,9 +25,13 @@ module Fluent
25
25
  config_param :keys, :array, value_type: :string
26
26
  desc 'The delimiter character (or string) of TSV values'
27
27
  config_param :delimiter, :string, default: "\t"
28
+ desc 'The parameter to enable writing to new lines'
29
+ config_param :add_newline, :bool, default: true
28
30
 
29
31
  def format(tag, time, record)
30
- @keys.map{|k| record[k].to_s }.join(@delimiter)
32
+ formatted = @keys.map{|k| record[k].to_s }.join(@delimiter)
33
+ formatted << "\n".freeze if @add_newline
34
+ formatted
31
35
  end
32
36
  end
33
37
  end
@@ -141,8 +141,8 @@ module Fluent::Plugin
141
141
  dummy_record_keys = get_placeholders_keys(@path_template) || ['message']
142
142
  dummy_record = Hash[dummy_record_keys.zip(['data'] * dummy_record_keys.size)]
143
143
 
144
- test_meta1 = metadata_for_test(dummy_tag, Fluent::Engine.now, dummy_record)
145
- test_path = extract_placeholders(@path_template, test_meta1)
144
+ test_chunk1 = chunk_for_test(dummy_tag, Fluent::Engine.now, dummy_record)
145
+ test_path = extract_placeholders(@path_template, test_chunk1)
146
146
  unless ::Fluent::FileUtil.writable_p?(test_path)
147
147
  raise Fluent::ConfigError, "out_file: `#{test_path}` is not writable"
148
148
  end
@@ -178,7 +178,7 @@ module Fluent::Plugin
178
178
  end
179
179
 
180
180
  def write(chunk)
181
- path = extract_placeholders(@path_template, chunk.metadata)
181
+ path = extract_placeholders(@path_template, chunk)
182
182
  FileUtils.mkdir_p File.dirname(path), mode: @dir_perm
183
183
 
184
184
  writer = case
@@ -582,7 +582,7 @@ module Fluent::Plugin
582
582
  rescue IO::WaitReadable
583
583
  # If the exception is Errno::EWOULDBLOCK or Errno::EAGAIN, it is extended by IO::WaitReadable.
584
584
  # So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.
585
- # http://docs.ruby-lang.org/en/2.3.0/IO.html#method-i-read_nonblock
585
+ # https//docs.ruby-lang.org/en/2.3.0/IO.html#method-i-read_nonblock
586
586
  sleep @sender.read_interval unless @state == :established
587
587
  rescue SystemCallError => e
588
588
  @log.warn "disconnected by error", host: @host, port: @port, error: e
@@ -71,7 +71,7 @@ module Fluent::Plugin
71
71
  end
72
72
 
73
73
  def write(chunk)
74
- path_without_suffix = extract_placeholders(@path_without_suffix, chunk.metadata)
74
+ path_without_suffix = extract_placeholders(@path_without_suffix, chunk)
75
75
  path = generate_path(path_without_suffix)
76
76
  FileUtils.mkdir_p File.dirname(path), mode: @dir_perm
77
77
 
@@ -106,7 +106,7 @@ module Fluent::Plugin
106
106
  raise Fluent::ConfigError, "out_secondary_file: basename or directory has an incompatible placeholder #{ph}, remove tag placeholder, like `${tag}`, from basename or directory"
107
107
  end
108
108
 
109
- vars = placeholders.reject { |placeholder| placeholder.match(/tag(\[\d+\])?/) }
109
+ vars = placeholders.reject { |placeholder| placeholder.match(/tag(\[\d+\])?/) || (placeholder == 'chunk_id') }
110
110
 
111
111
  if ph = vars.find { |v| !@chunk_keys.include?(v) }
112
112
  raise Fluent::ConfigError, "out_secondary_file: basename or directory has an incompatible placeholder #{ph}, remove variable placeholder, like `${varname}`, from basename or directory"
@@ -93,7 +93,7 @@ module Fluent
93
93
  def initialize
94
94
  super
95
95
  $log.warn "'tcp' output is obsoleted and will be removed. Use 'forward' instead."
96
- $log.warn "see 'forward' section in http://docs.fluentd.org/ for the high-availability configuration."
96
+ $log.warn "see 'forward' section in https://docs.fluentd.org/ for the high-availability configuration."
97
97
  end
98
98
 
99
99
  config_param :port, :integer, default: LISTEN_PORT
@@ -39,6 +39,7 @@ module Fluent
39
39
  CHUNK_KEY_PATTERN = /^[-_.@a-zA-Z0-9]+$/
40
40
  CHUNK_KEY_PLACEHOLDER_PATTERN = /\$\{[-_.@$a-zA-Z0-9]+\}/
41
41
  CHUNK_TAG_PLACEHOLDER_PATTERN = /\$\{(tag(?:\[\d+\])?)\}/
42
+ CHUNK_ID_PLACEHOLDER_PATTERN = /\$\{chunk_id\}/
42
43
 
43
44
  CHUNKING_FIELD_WARN_NUM = 4
44
45
 
@@ -679,13 +680,27 @@ module Fluent
679
680
  end
680
681
 
681
682
  def get_placeholders_keys(str)
682
- str.scan(CHUNK_KEY_PLACEHOLDER_PATTERN).map{|ph| ph[2..-2]}.reject{|s| s == "tag"}.sort
683
+ str.scan(CHUNK_KEY_PLACEHOLDER_PATTERN).map{|ph| ph[2..-2]}.reject{|s| (s == "tag") || (s == 'chunk_id') }.sort
683
684
  end
684
685
 
685
686
  # TODO: optimize this code
686
- def extract_placeholders(str, metadata)
687
+ def extract_placeholders(str, chunk)
688
+ metadata = if chunk.is_a?(Fluent::Plugin::Buffer::Chunk)
689
+ chunk_passed = true
690
+ chunk.metadata
691
+ else
692
+ chunk_passed = false
693
+ # For existing plugins. Old plugin passes Chunk.metadata instead of Chunk
694
+ chunk
695
+ end
687
696
  if metadata.empty?
688
- str
697
+ str.sub(CHUNK_ID_PLACEHOLDER_PATTERN) {
698
+ if chunk_passed
699
+ dump_unique_id_hex(chunk.unique_id)
700
+ else
701
+ log.warn "${chunk_id} is not allowed in this plugin. Pass Chunk instead of metadata in extract_placeholders's 2nd argument"
702
+ end
703
+ }
689
704
  else
690
705
  rvalue = str.dup
691
706
  # strftime formatting
@@ -720,7 +735,13 @@ module Fluent
720
735
  if rvalue =~ CHUNK_KEY_PLACEHOLDER_PATTERN
721
736
  log.warn "chunk key placeholder '#{$1}' not replaced. template:#{str}"
722
737
  end
723
- rvalue
738
+ rvalue.sub(CHUNK_ID_PLACEHOLDER_PATTERN) {
739
+ if chunk_passed
740
+ dump_unique_id_hex(chunk.unique_id)
741
+ else
742
+ log.warn "${chunk_id} is not allowed in this plugin. Pass Chunk instead of metadata in extract_placeholders's 2nd argument"
743
+ end
744
+ }
724
745
  end
725
746
  end
726
747
 
@@ -801,6 +822,13 @@ module Fluent
801
822
  end
802
823
  end
803
824
 
825
+ def chunk_for_test(tag, time, record)
826
+ require 'fluent/plugin/buffer/memory_chunk'
827
+
828
+ m = metadata_for_test(tag, time, record)
829
+ Fluent::Plugin::Buffer::MemoryChunk.new(m)
830
+ end
831
+
804
832
  def metadata_for_test(tag, time, record)
805
833
  raise "BUG: #metadata_for_test is available only when no actual metadata exists" unless @buffer.metadata_list.empty?
806
834
  m = metadata(tag, time, record)
@@ -26,10 +26,14 @@ module Fluent
26
26
 
27
27
  def initialize
28
28
  super
29
- @time_parser = time_parser_create(format: TIME_FORMAT)
30
29
  @mutex = Mutex.new
31
30
  end
32
31
 
32
+ def configure(conf)
33
+ super
34
+ @time_parser = time_parser_create(format: TIME_FORMAT)
35
+ end
36
+
33
37
  def patterns
34
38
  {'format' => REGEXP, 'time_format' => TIME_FORMAT}
35
39
  end
@@ -104,18 +104,28 @@ module Fluent
104
104
  cert.not_before = Time.at(0)
105
105
  cert.not_after = Time.now + opts[:expiration]
106
106
  cert.public_key = key
107
- cert.serial = 1
107
+ cert.version = 2
108
+ cert.serial = rand(2**(8*10))
108
109
  cert.issuer = issuer
109
110
  cert.subject = subject
110
111
 
111
112
  return cert, key
112
113
  end
113
114
 
115
+ def cert_option_add_extensions(cert, extensions)
116
+ ef = OpenSSL::X509::ExtensionFactory.new
117
+ extensions.each do |ext|
118
+ oid, value = ext
119
+ cert.add_extension ef.create_extension(oid, value)
120
+ end
121
+ end
122
+
114
123
  def cert_option_generate_ca_pair_self_signed(generate_opts)
115
124
  cert, key = cert_option_generate_pair(generate_opts)
116
125
 
117
- # basicConstraints: this cert is for CA or not
118
- cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(true)]))
126
+ cert_option_add_extensions(cert, [
127
+ ['basicConstraints', 'CA:TRUE']
128
+ ])
119
129
 
120
130
  cert.sign(key, generate_opts[:digest].to_s)
121
131
  return cert, key
@@ -127,9 +137,12 @@ module Fluent
127
137
  cert, key = cert_option_generate_pair(generate_opts, ca_cert.subject)
128
138
  raise "BUG: certificate digest algorithm not set" unless generate_opts[:digest]
129
139
 
130
- # basicConstraints: this cert is for CA or not
131
- cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(false)]))
132
- cert.add_extension OpenSSL::X509::Extension.new('nsCertType', 'server')
140
+ cert_option_add_extensions(cert, [
141
+ ['basicConstraints', 'CA:FALSE'],
142
+ ['nsCertType', 'server'],
143
+ ['keyUsage', 'digitalSignature,keyEncipherment'],
144
+ ['extendedKeyUsage', 'serverAuth']
145
+ ])
133
146
 
134
147
  cert.sign(ca_key, generate_opts[:digest].to_s)
135
148
  return cert, key, nil
@@ -139,9 +152,10 @@ module Fluent
139
152
  cert, key = cert_option_generate_pair(generate_opts)
140
153
  raise "BUG: certificate digest algorithm not set" unless generate_opts[:digest]
141
154
 
142
- # basicConstraints: this cert is for CA or not
143
- cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(false)]))
144
- cert.add_extension OpenSSL::X509::Extension.new('nsCertType', 'server')
155
+ cert_option_add_extensions(cert, [
156
+ ['basicConstraints', 'CA:FALSE'],
157
+ ['nsCertType', 'server']
158
+ ])
145
159
 
146
160
  cert.sign(key, generate_opts[:digest].to_s)
147
161
  return cert, key, nil
@@ -133,8 +133,9 @@ module Fluent
133
133
 
134
134
  until param.empty?
135
135
  if in_bracket
136
- if param[0] == "'"
137
- if i = param.index("']")
136
+ if param[0] == "'" || param[0] == '"'
137
+ if i = param.index("']") || param.index('"]')
138
+ raise Fluent::ConfigError, "Mismatched quotes. Invalid syntax: #{orig_param}" unless param[0] == param[i]
138
139
  result << param[1..i - 1]
139
140
  param = param[i + 2..-1]
140
141
  in_bracket = false
@@ -21,7 +21,7 @@ require 'fluent/time'
21
21
  module Fluent
22
22
  module Test
23
23
  module Helpers
24
- # See "Example Custom Assertion: http://test-unit.github.io/test-unit/en/Test/Unit/Assertions.html
24
+ # See "Example Custom Assertion: https://test-unit.github.io/test-unit/en/Test/Unit/Assertions.html
25
25
  def assert_equal_event_time(expected, actual, message = nil)
26
26
  expected_s = "#{Time.at(expected.sec)} (nsec #{expected.nsec})"
27
27
  actual_s = "#{Time.at(actual.sec) } (nsec #{actual.nsec})"
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Fluent
18
18
 
19
- VERSION = '0.14.21'
19
+ VERSION = '0.14.22.rc1'
20
20
 
21
21
  end
@@ -1,6 +1,6 @@
1
1
  # <%= gem_name %>
2
2
 
3
- [Fluentd](http://fluentd.org/) <%= type %> plugin to do something.
3
+ [Fluentd](https://fluentd.org/) <%= type %> plugin to do something.
4
4
 
5
5
  TODO: write description for you plugin.
6
6
 
@@ -23,14 +23,17 @@ class LabeledTSVFormatterTest < ::Test::Unit::TestCase
23
23
  d = create_driver
24
24
  assert_equal "\t", d.instance.delimiter
25
25
  assert_equal ":", d.instance.label_delimiter
26
+ assert_equal true, d.instance.add_newline
26
27
 
27
28
  d = create_driver(
28
29
  'delimiter' => ',',
29
30
  'label_delimiter' => '=',
31
+ 'add_newline' => false,
30
32
  )
31
33
 
32
34
  assert_equal ",", d.instance.delimiter
33
35
  assert_equal "=", d.instance.label_delimiter
36
+ assert_equal false, d.instance.add_newline
34
37
  end
35
38
 
36
39
  def test_format
@@ -0,0 +1,68 @@
1
+ require_relative '../helper'
2
+ require 'fluent/test/driver/formatter'
3
+ require 'fluent/plugin/formatter_tsv'
4
+
5
+ class TSVFormatterTest < ::Test::Unit::TestCase
6
+ def setup
7
+ @time = event_time
8
+ end
9
+
10
+ def create_driver(conf = "")
11
+ Fluent::Test::Driver::Formatter.new(Fluent::Plugin::TSVFormatter).configure(conf)
12
+ end
13
+
14
+ def tag
15
+ "tag"
16
+ end
17
+
18
+ def record
19
+ {'message' => 'awesome', 'greeting' => 'hello'}
20
+ end
21
+
22
+ def test_config_params
23
+ d = create_driver(
24
+ 'keys' => 'message,greeting',
25
+ )
26
+ assert_equal ["message", "greeting"], d.instance.keys
27
+ assert_equal "\t", d.instance.delimiter
28
+ assert_equal true, d.instance.add_newline
29
+
30
+ d = create_driver(
31
+ 'keys' => 'message,greeting',
32
+ 'delimiter' => ',',
33
+ 'add_newline' => false,
34
+ )
35
+ assert_equal ["message", "greeting"], d.instance.keys
36
+ assert_equal ",", d.instance.delimiter
37
+ assert_equal false, d.instance.add_newline
38
+ end
39
+
40
+ def test_format
41
+ d = create_driver(
42
+ 'keys' => 'message,greeting',
43
+ )
44
+ formatted = d.instance.format(tag, @time, record)
45
+
46
+ assert_equal("awesome\thello\n", formatted)
47
+ end
48
+
49
+ def test_format_without_newline
50
+ d = create_driver(
51
+ 'keys' => 'message,greeting',
52
+ 'add_newline' => false,
53
+ )
54
+ formatted = d.instance.format(tag, @time, record)
55
+
56
+ assert_equal("awesome\thello", formatted)
57
+ end
58
+
59
+ def test_format_with_customized_delimiters
60
+ d = create_driver(
61
+ 'keys' => 'message,greeting',
62
+ 'delimiter' => ',',
63
+ )
64
+ formatted = d.instance.format(tag, @time, record)
65
+
66
+ assert_equal("awesome,hello\n", formatted)
67
+ end
68
+ end
@@ -557,6 +557,35 @@ class FileOutputTest < Test::Unit::TestCase
557
557
  check_gzipped_result(path, formatted_lines * 3)
558
558
  end
559
559
 
560
+ test '${chunk_id}' do
561
+ time = event_time("2011-01-02 13:14:15 UTC")
562
+ formatted_lines = %[2011-01-02T13:14:15Z\ttest\t{"a":1}\n] + %[2011-01-02T13:14:15Z\ttest\t{"a":2}\n]
563
+
564
+ write_once = ->(){
565
+ d = create_driver %[
566
+ path #{TMP_DIR}/out_file_chunk_id_${chunk_id}
567
+ utc
568
+ append true
569
+ <buffer>
570
+ timekey_use_utc true
571
+ </buffer>
572
+ ]
573
+ d.run(default_tag: 'test'){
574
+ d.feed(time, {"a"=>1})
575
+ d.feed(time, {"a"=>2})
576
+ }
577
+ d.instance.last_written_path
578
+ }
579
+
580
+ path = write_once.call
581
+ if File.basename(path) =~ /out_file_chunk_id_([-_.@a-zA-Z0-9].*).20110102.log/
582
+ unique_id = Fluent::UniqueId.hex(Fluent::UniqueId.generate)
583
+ assert_equal unique_id.size, $1.size, "chunk_id size is mismatched"
584
+ else
585
+ flunk "chunk_id is not included in the path"
586
+ end
587
+ end
588
+
560
589
  test 'symlink' do
561
590
  omit "Windows doesn't support symlink" if Fluent.windows?
562
591
  conf = CONFIG + %[
@@ -260,6 +260,20 @@ class FileOutputSecondaryTest < Test::Unit::TestCase
260
260
  assert_equal "#{TMP_DIR}/dump.bin", path
261
261
  end
262
262
 
263
+ test 'path with ${chunk_id}' do
264
+ d = create_driver %[
265
+ directory #{TMP_DIR}
266
+ basename out_file_chunk_id_${chunk_id}
267
+ ]
268
+ path = d.instance.write(@c)
269
+ if File.basename(path) =~ /out_file_chunk_id_([-_.@a-zA-Z0-9].*).0/
270
+ unique_id = Fluent::UniqueId.hex(Fluent::UniqueId.generate)
271
+ assert_equal unique_id.size, $1.size, "chunk_id size is mismatched"
272
+ else
273
+ flunk "chunk_id is not included in the path"
274
+ end
275
+ end
276
+
263
277
  data(
264
278
  invalid_tag: [/tag/, '${tag}'],
265
279
  invalid_tag0: [/tag\[0\]/, '${tag[0]}'],
@@ -125,6 +125,10 @@ class OutputTest < Test::Unit::TestCase
125
125
  def create_metadata(timekey: nil, tag: nil, variables: nil)
126
126
  Fluent::Plugin::Buffer::Metadata.new(timekey, tag, variables)
127
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
128
132
  def waiting(seconds)
129
133
  begin
130
134
  Timeout.timeout(seconds) do
@@ -219,7 +223,9 @@ class OutputTest < Test::Unit::TestCase
219
223
  assert @i.terminated?
220
224
  end
221
225
 
222
- test '#extract_placeholders does nothing if chunk key is not specified' do
226
+ data(:new_api => :chunk,
227
+ :old_api => :metadata)
228
+ test '#extract_placeholders does nothing if chunk key is not specified' do |api|
223
229
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
224
230
  assert !@i.chunk_key_time
225
231
  assert !@i.chunk_key_tag
@@ -227,11 +233,17 @@ class OutputTest < Test::Unit::TestCase
227
233
  tmpl = "/mypath/%Y/%m/%d/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
228
234
  t = event_time('2016-04-11 20:30:00 +0900')
229
235
  v = {key1: "value1", key2: "value2"}
230
- m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
231
- assert_equal tmpl, @i.extract_placeholders(tmpl, m)
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)
232
242
  end
233
243
 
234
- test '#extract_placeholders can extract time if time key and range are configured' do
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|
235
247
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
236
248
  assert @i.chunk_key_time
237
249
  assert !@i.chunk_key_tag
@@ -239,11 +251,17 @@ class OutputTest < Test::Unit::TestCase
239
251
  tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
240
252
  t = event_time('2016-04-11 20:30:00 +0900')
241
253
  v = {key1: "value1", key2: "value2"}
242
- m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
243
- assert_equal "/mypath/2016/04/11/20-30/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail", @i.extract_placeholders(tmpl, m)
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)
244
260
  end
245
261
 
246
- test '#extract_placeholders can extract tag and parts of tag if tag is configured' do
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|
247
265
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'tag', {})]))
248
266
  assert !@i.chunk_key_time
249
267
  assert @i.chunk_key_tag
@@ -251,11 +269,17 @@ class OutputTest < Test::Unit::TestCase
251
269
  tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
252
270
  t = event_time('2016-04-11 20:30:00 +0900')
253
271
  v = {key1: "value1", key2: "value2"}
254
- m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
255
- assert_equal "/mypath/%Y/%m/%d/%H-%M/fluentd.test.output/test/output/${key1}/${key2}/tail", @i.extract_placeholders(tmpl, m)
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)
256
278
  end
257
279
 
258
- test '#extract_placeholders can extract variables if variables are configured' do
280
+ data(:new_api => :chunk,
281
+ :old_api => :metadata)
282
+ test '#extract_placeholders can extract variables if variables are configured' do |api|
259
283
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'key1,key2', {})]))
260
284
  assert !@i.chunk_key_time
261
285
  assert !@i.chunk_key_tag
@@ -263,11 +287,17 @@ class OutputTest < Test::Unit::TestCase
263
287
  tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
264
288
  t = event_time('2016-04-11 20:30:00 +0900')
265
289
  v = {key1: "value1", key2: "value2"}
266
- m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
267
- assert_equal "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/value1/value2/tail", @i.extract_placeholders(tmpl, m)
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)
268
296
  end
269
297
 
270
- test '#extract_placeholders can extract nested variables if variables are configured with dot notation' do
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|
271
301
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'key,$.nest.key', {})]))
272
302
  assert !@i.chunk_key_time
273
303
  assert !@i.chunk_key_tag
@@ -275,11 +305,17 @@ class OutputTest < Test::Unit::TestCase
275
305
  tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key}/${$.nest.key}/tail"
276
306
  t = event_time('2016-04-11 20:30:00 +0900')
277
307
  v = {:key => "value1", :"$.nest.key" => "value2"}
278
- m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
279
- assert_equal "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/value1/value2/tail", @i.extract_placeholders(tmpl, m)
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)
280
314
  end
281
315
 
282
- test '#extract_placeholders can extract all chunk keys if configured' do
316
+ data(:new_api => :chunk,
317
+ :old_api => :metadata)
318
+ test '#extract_placeholders can extract all chunk keys if configured' do |api|
283
319
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
284
320
  assert @i.chunk_key_time
285
321
  assert @i.chunk_key_tag
@@ -287,11 +323,17 @@ class OutputTest < Test::Unit::TestCase
287
323
  tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[1]}/${tag[2]}/${key1}/${key2}/tail"
288
324
  t = event_time('2016-04-11 20:30:00 +0900')
289
325
  v = {key1: "value1", key2: "value2"}
290
- m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
291
- assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/test/output/value1/value2/tail", @i.extract_placeholders(tmpl, m)
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)
292
332
  end
293
333
 
294
- test '#extract_placeholders removes out-of-range tag part and unknown variable placeholders' do
334
+ data(:new_api => :chunk,
335
+ :old_api => :metadata)
336
+ test '#extract_placeholders removes out-of-range tag part and unknown variable placeholders' do |api|
295
337
  @i.configure(config_element('ROOT', '', {}, [config_element('buffer', 'time,tag,key1,key2', {'timekey' => 60*30, 'timekey_zone' => "+0900"})]))
296
338
  assert @i.chunk_key_time
297
339
  assert @i.chunk_key_tag
@@ -299,8 +341,23 @@ class OutputTest < Test::Unit::TestCase
299
341
  tmpl = "/mypath/%Y/%m/%d/%H-%M/${tag}/${tag[3]}/${tag[4]}/${key3}/${key4}/tail"
300
342
  t = event_time('2016-04-11 20:30:00 +0900')
301
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/////tail", @i.extract_placeholders(tmpl, c)
350
+ end
351
+
352
+ test '#extract_placeholders logs warn message if metadata is passed for ${chunk_id} placeholder' do
353
+ @i.configure(config_element('ROOT', '', {}, [config_element('buffer', '')]))
354
+ tmpl = "/mypath/${chunk_id}/tail"
355
+ t = event_time('2016-04-11 20:30:00 +0900')
356
+ v = {key1: "value1", key2: "value2"}
302
357
  m = create_metadata(timekey: t, tag: 'fluentd.test.output', variables: v)
303
- assert_equal "/mypath/2016/04/11/20-30/fluentd.test.output/////tail", @i.extract_placeholders(tmpl, m)
358
+ @i.extract_placeholders(tmpl, m)
359
+ logs = @i.log.out.logs
360
+ assert { logs.any? { |log| log.include?("${chunk_id} is not allowed in this plugin") } }
304
361
  end
305
362
 
306
363
  sub_test_case '#placeholder_validators' do
@@ -16,6 +16,7 @@ class Apache2ParserTest < ::Test::Unit::TestCase
16
16
  'referer' => nil,
17
17
  'agent' => 'Opera/12.0'
18
18
  }
19
+ @parser.configure({})
19
20
  end
20
21
 
21
22
  def test_parse
@@ -24,20 +24,23 @@ class RecordAccessorHelperTest < Test::Unit::TestCase
24
24
  end
25
25
 
26
26
  data('dot' => '$.key1.key2[0]',
27
- 'bracket' => "$['key1']['key2'][0]")
27
+ 'bracket' => "$['key1']['key2'][0]",
28
+ 'bracket w/ double quotes' => '$["key1"]["key2"][0]')
28
29
  test "nested keys ['key1', 'key2', 0]" do |param|
29
30
  result = Fluent::PluginHelper::RecordAccessor::Accessor.parse_parameter(param)
30
31
  assert_equal ['key1', 'key2', 0], result
31
32
  end
32
33
 
33
- data('bracket' => "$['key1'][0]['ke y2']")
34
+ data('bracket' => "$['key1'][0]['ke y2']",
35
+ 'bracket w/ double quotes' => '$["key1"][0]["ke y2"]')
34
36
  test "nested keys ['key1', 0, 'ke y2']" do |param|
35
37
  result = Fluent::PluginHelper::RecordAccessor::Accessor.parse_parameter(param)
36
38
  assert_equal ['key1', 0, 'ke y2'], result
37
39
  end
38
40
 
39
41
  data('dot' => '$.[0].key1.[1].key2',
40
- 'bracket' => "$[0]['key1'][1]['key2']")
42
+ 'bracket' => "$[0]['key1'][1]['key2']",
43
+ 'bracket w/ double quotes' => '$[0]["key1"][1]["key2"]')
41
44
  test "nested keys [0, 'key1', 1, 'key2']" do |param|
42
45
  result = Fluent::PluginHelper::RecordAccessor::Accessor.parse_parameter(param)
43
46
  assert_equal [0, 'key1', 1, 'key2'], result
@@ -49,7 +52,9 @@ class RecordAccessorHelperTest < Test::Unit::TestCase
49
52
  "more chars" => "$.key1[0]foo",
50
53
  "whitespace char included key in dot notation" => "$.key[0].ke y",
51
54
  "empty keys with dot" => "$.",
52
- "empty keys with bracket" => "$[")
55
+ "empty keys with bracket" => "$[",
56
+ "mismatched quotes1" => "$['key1']['key2\"]",
57
+ "mismatched quotes2" => '$["key1"]["key2\']')
53
58
  test 'invalid syntax' do |param|
54
59
  assert_raise Fluent::ConfigError do
55
60
  Fluent::PluginHelper::RecordAccessor::Accessor.parse_parameter(param)
@@ -78,14 +83,16 @@ class RecordAccessorHelperTest < Test::Unit::TestCase
78
83
  end
79
84
 
80
85
  data('dot' => '$.key1.key2[0]',
81
- 'bracket' => "$['key1']['key2'][0]")
86
+ 'bracket' => "$['key1']['key2'][0]",
87
+ 'bracket w/ double quotes' => '$["key1"]["key2"][0]')
82
88
  test "nested keys ['key1', 'key2', 0]" do |param|
83
89
  r = {'key1' => {'key2' => [1, 2, 3]}}
84
90
  accessor = @d.record_accessor_create(param)
85
91
  assert_equal 1, accessor.call(r)
86
92
  end
87
93
 
88
- data('bracket' => "$['key1'][0]['ke y2']")
94
+ data('bracket' => "$['key1'][0]['ke y2']",
95
+ 'bracket w/ double quotes' => '$["key1"][0]["ke y2"]')
89
96
  test "nested keys ['key1', 0, 'ke y2']" do |param|
90
97
  r = {'key1' => [{'ke y2' => "value"}]}
91
98
  accessor = @d.record_accessor_create(param)
@@ -98,7 +105,9 @@ class RecordAccessorHelperTest < Test::Unit::TestCase
98
105
  "whitespace char included key in dot notation" => "$.key[0].ke y",
99
106
  "more chars" => "$.key1[0]foo",
100
107
  "empty keys with dot" => "$.",
101
- "empty keys with bracket" => "$[")
108
+ "empty keys with bracket" => "$[",
109
+ "mismatched quotes1" => "$['key1']['key2\"]",
110
+ "mismatched quotes2" => '$["key1"]["key2\']')
102
111
  test 'invalid syntax' do |param|
103
112
  assert_raise Fluent::ConfigError do
104
113
  @d.record_accessor_create(param)
@@ -776,6 +776,7 @@ class ServerPluginHelperTest < Test::Unit::TestCase
776
776
  def create_server_pair_signed_by_self(cert_path, private_key_path, passphrase)
777
777
  cert, key, _ = CertUtil.cert_option_generate_server_pair_self_signed(create_server_options)
778
778
  write_cert_and_key(cert_path, cert, private_key_path, key, passphrase)
779
+ return cert
779
780
  end
780
781
 
781
782
  def create_ca_pair_signed_by_self(cert_path, private_key_path, passphrase)
@@ -786,6 +787,7 @@ class ServerPluginHelperTest < Test::Unit::TestCase
786
787
  def create_server_pair_signed_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, passphrase)
787
788
  cert, key, _ = CertUtil.cert_option_generate_server_pair_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, create_server_options)
788
789
  write_cert_and_key(cert_path, cert, private_key_path, key, passphrase)
790
+ return cert
789
791
  end
790
792
 
791
793
  def create_server_pair_chained_with_root_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, passphrase)
@@ -842,6 +844,20 @@ class ServerPluginHelperTest < Test::Unit::TestCase
842
844
  sock.close rescue nil
843
845
  end
844
846
 
847
+ def assert_certificate(cert, expected_extensions)
848
+ get_extension = lambda do |oid|
849
+ cert.extensions.detect { |e| e.oid == oid }
850
+ end
851
+
852
+ assert_true cert.serial > 1
853
+ assert_equal 2, cert.version
854
+
855
+ expected_extensions.each do |ext|
856
+ expected_oid, expected_value = ext
857
+ assert_equal expected_value, get_extension.call(expected_oid).value
858
+ end
859
+ end
860
+
845
861
  sub_test_case '#server_create_tls with various certificate options' do
846
862
  setup do
847
863
  @d = Dummy.new # to get plugin not configured/started yet
@@ -896,7 +912,12 @@ class ServerPluginHelperTest < Test::Unit::TestCase
896
912
  test 'load self-signed cert/key pair (files), verified from clients using cert files' do |private_key_passphrase|
897
913
  cert_path = File.join(@server_cert_dir, "cert.pem")
898
914
  private_key_path = File.join(@certs_dir, "server.key.pem")
899
- create_server_pair_signed_by_self(cert_path, private_key_path, private_key_passphrase)
915
+ cert = create_server_pair_signed_by_self(cert_path, private_key_path, private_key_passphrase)
916
+
917
+ assert_certificate(cert,[
918
+ ['basicConstraints', 'CA:FALSE'],
919
+ ['nsCertType', 'SSL Server']
920
+ ])
900
921
 
901
922
  tls_options = {
902
923
  protocol: :tls,
@@ -963,7 +984,14 @@ class ServerPluginHelperTest < Test::Unit::TestCase
963
984
 
964
985
  cert_path = File.join(@server_cert_dir, "cert.pem")
965
986
  private_key_path = File.join(@certs_dir, "server.key.pem")
966
- create_server_pair_signed_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, private_key_passphrase)
987
+ cert = create_server_pair_signed_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, private_key_passphrase)
988
+
989
+ assert_certificate(cert,[
990
+ ['basicConstraints', 'CA:FALSE'],
991
+ ['nsCertType', 'SSL Server'],
992
+ ['keyUsage', 'Digital Signature, Key Encipherment'],
993
+ ['extendedKeyUsage', 'TLS Web Server Authentication']
994
+ ])
967
995
 
968
996
  tls_options = {
969
997
  protocol: :tls,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluentd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.21
4
+ version: 0.14.22.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-07 00:00:00.000000000 Z
11
+ date: 2017-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -318,10 +318,11 @@ files:
318
318
  - ".github/ISSUE_TEMPLATE.md"
319
319
  - ".gitignore"
320
320
  - ".travis.yml"
321
+ - ADOPTERS.md
321
322
  - AUTHORS
323
+ - CHANGELOG.md
322
324
  - CONTRIBUTING.md
323
325
  - COPYING
324
- - ChangeLog
325
326
  - ENTERPRISE_PROVIDERS.md
326
327
  - Gemfile
327
328
  - MAINTAINERS.md
@@ -623,6 +624,7 @@ files:
623
624
  - test/plugin/test_formatter_msgpack.rb
624
625
  - test/plugin/test_formatter_out_file.rb
625
626
  - test/plugin/test_formatter_single_value.rb
627
+ - test/plugin/test_formatter_tsv.rb
626
628
  - test/plugin/test_in_debug_agent.rb
627
629
  - test/plugin/test_in_dummy.rb
628
630
  - test/plugin/test_in_exec.rb
@@ -718,7 +720,7 @@ files:
718
720
  - test/test_time_formatter.rb
719
721
  - test/test_time_parser.rb
720
722
  - test/test_unique_id.rb
721
- homepage: http://fluentd.org/
723
+ homepage: https://fluentd.org/
722
724
  licenses:
723
725
  - Apache-2.0
724
726
  metadata: {}
@@ -733,12 +735,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
733
735
  version: '2.1'
734
736
  required_rubygems_version: !ruby/object:Gem::Requirement
735
737
  requirements:
736
- - - ">="
738
+ - - ">"
737
739
  - !ruby/object:Gem::Version
738
- version: '0'
740
+ version: 1.3.1
739
741
  requirements: []
740
742
  rubyforge_project:
741
- rubygems_version: 2.6.11
743
+ rubygems_version: 2.6.12
742
744
  signing_key:
743
745
  specification_version: 4
744
746
  summary: Fluentd event collector
@@ -789,6 +791,7 @@ test_files:
789
791
  - test/plugin/test_formatter_msgpack.rb
790
792
  - test/plugin/test_formatter_out_file.rb
791
793
  - test/plugin/test_formatter_single_value.rb
794
+ - test/plugin/test_formatter_tsv.rb
792
795
  - test/plugin/test_in_debug_agent.rb
793
796
  - test/plugin/test_in_dummy.rb
794
797
  - test/plugin/test_in_exec.rb