fluentd 1.1.1 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '08745174bdefc09fdc359003c6acb65f63d58bac'
4
- data.tar.gz: 45e36b62fe808b05273d98eab2ca69c0e46b8c93
3
+ metadata.gz: e20dab78cc15d81c32ba9cd70fd5a806c6234a73
4
+ data.tar.gz: 2c133e7665781dcc0d97da8459489ce3edf46f8f
5
5
  SHA512:
6
- metadata.gz: b855e7e95bd3d6b29b50a6b4ba3321a4fd4166c4e0ef8bd4ab104252bd1b6b738a16eb8a93eae35cbf4b1daf7a8ad209d7ef1cb3be508633071d9490ccb15ffb
7
- data.tar.gz: 90754b2ba1765da45e47906866dbb3cfd77bd5373134e9f160b58f3bab3832e1db144124a2665cec19a7e731c70620edf7f14a9d453cd452646263dcc4b14b74
6
+ metadata.gz: 3d3775f9459c4c5ee8747c39596d2750e51ae6e0bab04958c6162d1faad4a6afd7deb2bcce27ed14b2f1eb925666554d444506cc30408a5db898f29aab3c6258
7
+ data.tar.gz: c67fcc90f8f3717b73f4d3d78d5899881c688d52d3a39d4b0e112412092973a65d86ca7e9930326f894f3e896013afa42971532db895d67ecbc6e48c5b12180b
@@ -1,5 +1,28 @@
1
1
  # v1.1
2
2
 
3
+ ## Release v1.1.2 - 2018/03/18
4
+
5
+ ### Enhancements
6
+
7
+ * filter_grep: Support pattern starts with character classes with //
8
+ https://github.com/fluent/fluentd/pull/1887
9
+
10
+ ### Bug fixes
11
+
12
+ * in_tail: Handle records in the correct order on file rotation
13
+ https://github.com/fluent/fluentd/pull/1880
14
+ * out_forward: Fix race condition with <security> on multi thread environment
15
+ https://github.com/fluent/fluentd/pull/1893
16
+ * output: Prevent flushing threads consume too much CPU when retry happens
17
+ https://github.com/fluent/fluentd/pull/1901
18
+ * config: Fix boolean param handling for comment without value
19
+ https://github.com/fluent/fluentd/pull/1883
20
+ * test: Fix random test failures in test/plugin/test_out_forward.rb
21
+ https://github.com/fluent/fluentd/pull/1881
22
+ https://github.com/fluent/fluentd/pull/1890
23
+ * command: Fix typo in binlog_reader
24
+ https://github.com/fluent/fluentd/pull/1898
25
+
3
26
  ## Release v1.1.1 - 2018/03/05
4
27
 
5
28
  ### Enhancements
@@ -926,4 +949,4 @@ This list includes changes of 0.14.0.pre.1 and release candidates.
926
949
  https://github.com/fluent/fluentd/pull/955
927
950
  https://github.com/fluent/fluentd/pull/966
928
951
 
929
- See https://github.com/fluent/fluentd/blob/v0.12/ChangeLog for v0.12 changelog
952
+ See https://github.com/fluent/fluentd/blob/v0.12/CHANGELOG.md for v0.12 changelog
@@ -32,7 +32,7 @@ Usage: fluent-binlog-reader <command> [<args>]
32
32
  Commands of fluent-binlog-reader:
33
33
  cat : Read files sequentially, writing them to standard output.
34
34
  head : Display the beginning of a text file.
35
- format : Display plugins that you can use.
35
+ formats : Display plugins that you can use.
36
36
 
37
37
  See 'fluent-binlog-reader <command> --help' for more information on a specific command.
38
38
  HELP
@@ -60,7 +60,13 @@ module Fluent
60
60
  when ''
61
61
  true
62
62
  else
63
- nil
63
+ # Current parser passes comment without actual values, e.g. "param #foo".
64
+ # parser should pass empty string in this case but changing behaviour may break existing environment so keep parser behaviour. Just ignore comment value in boolean handling for now.
65
+ if str.respond_to?('start_with?') && str.start_with?('#')
66
+ true
67
+ else
68
+ nil
69
+ end
64
70
  end
65
71
  end
66
72
 
@@ -41,7 +41,11 @@ module Fluent::Plugin
41
41
  config_param :key, :string
42
42
  desc "The regular expression."
43
43
  config_param :pattern do |value|
44
- Regexp.compile(value)
44
+ if value.start_with?("/") and value.end_with?("/")
45
+ Regexp.compile(value[1..-2])
46
+ else
47
+ Regexp.compile(value)
48
+ end
45
49
  end
46
50
  end
47
51
 
@@ -50,7 +54,11 @@ module Fluent::Plugin
50
54
  config_param :key, :string
51
55
  desc "The regular expression."
52
56
  config_param :pattern do |value|
53
- Regexp.compile(value)
57
+ if value.start_with?("/") and value.end_with?("/")
58
+ Regexp.compile(value[1..-2])
59
+ else
60
+ Regexp.compile(value)
61
+ end
54
62
  end
55
63
  end
56
64
 
@@ -580,6 +580,8 @@ module Fluent::Plugin
580
580
  @pe.update(inode, 0)
581
581
  else # file is rotated and new file found
582
582
  watcher_needs_update = true
583
+ # Handle the old log file before renewing TailWatcher [fluentd#1055]
584
+ @io_handler.on_notify
583
585
  end
584
586
  else # file is rotated and new file not found
585
587
  # Clear RotateHandler to avoid duplicated file watch in same path.
@@ -521,7 +521,6 @@ module Fluent::Plugin
521
521
  @standby = server.standby
522
522
  @failure = failure
523
523
  @available = true
524
- @state = nil
525
524
 
526
525
  # @hostname is used for certificate verification & TLS SNI
527
526
  host_is_hostname = !(IPAddr.new(@host) rescue false)
@@ -537,7 +536,6 @@ module Fluent::Plugin
537
536
  @password = server.password
538
537
  @shared_key = server.shared_key || (sender.security && sender.security.shared_key) || ""
539
538
  @shared_key_salt = generate_salt
540
- @shared_key_nonce = ""
541
539
 
542
540
  @unpacker = Fluent::Engine.msgpack_unpacker
543
541
 
@@ -552,6 +550,8 @@ module Fluent::Plugin
552
550
  attr_reader :sockaddr # used by on_heartbeat
553
551
  attr_reader :failure, :available # for test
554
552
 
553
+ RequestInfo = Struct.new(:state, :shared_key_nonce, :auth)
554
+
555
555
  def validate_host_resolution!
556
556
  resolved_host
557
557
  end
@@ -568,8 +568,8 @@ module Fluent::Plugin
568
568
  @standby
569
569
  end
570
570
 
571
- def establish_connection(sock)
572
- while available? && @state != :established
571
+ def establish_connection(sock, ri)
572
+ while available? && ri.state != :established
573
573
  begin
574
574
  # TODO: On Ruby 2.2 or earlier, read_nonblock doesn't work expectedly.
575
575
  # We need rewrite around here using new socket/server plugin helper.
@@ -579,13 +579,13 @@ module Fluent::Plugin
579
579
  next
580
580
  end
581
581
  @unpacker.feed_each(buf) do |data|
582
- on_read(sock, data)
582
+ on_read(sock, ri, data)
583
583
  end
584
584
  rescue IO::WaitReadable
585
585
  # If the exception is Errno::EWOULDBLOCK or Errno::EAGAIN, it is extended by IO::WaitReadable.
586
586
  # So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.
587
587
  # https//docs.ruby-lang.org/en/2.3.0/IO.html#method-i-read_nonblock
588
- sleep @sender.read_interval unless @state == :established
588
+ sleep @sender.read_interval unless ri.state == :established
589
589
  rescue SystemCallError => e
590
590
  @log.warn "disconnected by error", host: @host, port: @port, error: e
591
591
  disable!
@@ -599,9 +599,9 @@ module Fluent::Plugin
599
599
  end
600
600
 
601
601
  def send_data_actual(sock, tag, chunk)
602
- @state = @sender.security ? :helo : :established
603
- if @state != :established
604
- establish_connection(sock)
602
+ ri = RequestInfo.new(@sender.security ? :helo : :established)
603
+ if ri.state != :established
604
+ establish_connection(sock, ri)
605
605
  end
606
606
 
607
607
  unless available?
@@ -756,7 +756,7 @@ module Fluent::Plugin
756
756
  SecureRandom.hex(16)
757
757
  end
758
758
 
759
- def check_helo(message)
759
+ def check_helo(ri, message)
760
760
  @log.debug "checking helo"
761
761
  # ['HELO', options(hash)]
762
762
  unless message.size == 2 && message[0] == 'HELO'
@@ -764,23 +764,23 @@ module Fluent::Plugin
764
764
  end
765
765
  opts = message[1] || {}
766
766
  # make shared_key_check failed (instead of error) if protocol version mismatch exist
767
- @shared_key_nonce = opts['nonce'] || ''
768
- @authentication = opts['auth'] || ''
767
+ ri.shared_key_nonce = opts['nonce'] || ''
768
+ ri.auth = opts['auth'] || ''
769
769
  true
770
770
  end
771
771
 
772
- def generate_ping
772
+ def generate_ping(ri)
773
773
  @log.debug "generating ping"
774
774
  # ['PING', self_hostname, sharedkey\_salt, sha512\_hex(sharedkey\_salt + self_hostname + nonce + shared_key),
775
775
  # username || '', sha512\_hex(auth\_salt + username + password) || '']
776
776
  shared_key_hexdigest = Digest::SHA512.new.update(@shared_key_salt)
777
777
  .update(@sender.security.self_hostname)
778
- .update(@shared_key_nonce)
778
+ .update(ri.shared_key_nonce)
779
779
  .update(@shared_key)
780
780
  .hexdigest
781
781
  ping = ['PING', @sender.security.self_hostname, @shared_key_salt, shared_key_hexdigest]
782
- if !@authentication.empty?
783
- password_hexdigest = Digest::SHA512.new.update(@authentication).update(@username).update(@password).hexdigest
782
+ if !ri.auth.empty?
783
+ password_hexdigest = Digest::SHA512.new.update(ri.auth).update(@username).update(@password).hexdigest
784
784
  ping.push(@username, password_hexdigest)
785
785
  else
786
786
  ping.push('','')
@@ -788,7 +788,7 @@ module Fluent::Plugin
788
788
  ping
789
789
  end
790
790
 
791
- def check_pong(message)
791
+ def check_pong(ri, message)
792
792
  @log.debug "checking pong"
793
793
  # ['PONG', bool(authentication result), 'reason if authentication failed',
794
794
  # self_hostname, sha512\_hex(salt + self_hostname + nonce + sharedkey)]
@@ -805,7 +805,7 @@ module Fluent::Plugin
805
805
  return false, 'same hostname between input and output: invalid configuration'
806
806
  end
807
807
 
808
- clientside = Digest::SHA512.new.update(@shared_key_salt).update(hostname).update(@shared_key_nonce).update(@shared_key).hexdigest
808
+ clientside = Digest::SHA512.new.update(@shared_key_salt).update(hostname).update(ri.shared_key_nonce).update(@shared_key).hexdigest
809
809
  unless shared_key_hexdigest == clientside
810
810
  return false, 'shared key mismatch'
811
811
  end
@@ -813,29 +813,29 @@ module Fluent::Plugin
813
813
  return true, nil
814
814
  end
815
815
 
816
- def on_read(sock, data)
816
+ def on_read(sock, ri, data)
817
817
  @log.trace __callee__
818
818
 
819
- case @state
819
+ case ri.state
820
820
  when :helo
821
- unless check_helo(data)
821
+ unless check_helo(ri, data)
822
822
  @log.warn "received invalid helo message from #{@name}"
823
823
  disable! # shutdown
824
824
  return
825
825
  end
826
- sock.write(generate_ping.to_msgpack)
827
- @state = :pingpong
826
+ sock.write(generate_ping(ri).to_msgpack)
827
+ ri.state = :pingpong
828
828
  when :pingpong
829
- succeeded, reason = check_pong(data)
829
+ succeeded, reason = check_pong(ri, data)
830
830
  unless succeeded
831
831
  @log.warn "connection refused to #{@name}: #{reason}"
832
832
  disable! # shutdown
833
833
  return
834
834
  end
835
- @state = :established
835
+ ri.state = :established
836
836
  @log.debug "connection established", host: @host, port: @port
837
837
  else
838
- raise "BUG: unknown session state: #{@state}"
838
+ raise "BUG: unknown session state: #{ri.state}"
839
839
  end
840
840
  end
841
841
  end
@@ -1313,9 +1313,17 @@ module Fluent
1313
1313
  # This thread don't use `thread_current_running?` because this thread should run in `before_shutdown` phase
1314
1314
  while @output_flush_threads_running
1315
1315
  current_clock = Fluent::Clock.now
1316
- interval = state.next_clock - current_clock
1316
+ next_retry_time = nil
1317
1317
 
1318
- if state.next_clock <= current_clock && @retry_mutex.synchronize { @retry ? @retry.next_time <= Time.now : true }
1318
+ @retry_mutex.synchronize do
1319
+ next_retry_time = @retry ? @retry.next_time : nil
1320
+ end
1321
+
1322
+ if state.next_clock > current_clock
1323
+ interval = state.next_clock - current_clock
1324
+ elsif next_retry_time && next_retry_time > Time.now
1325
+ interval = next_retry_time.to_f - Time.now.to_f
1326
+ else
1319
1327
  try_flush
1320
1328
 
1321
1329
  # next_flush_time uses flush_thread_interval or flush_thread_burst_interval (or retrying)
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Fluent
18
18
 
19
- VERSION = '1.1.1'
19
+ VERSION = '1.1.2'
20
20
 
21
21
  end
@@ -0,0 +1,56 @@
1
+ require_relative '../helper'
2
+ require 'fluent/plugin/input'
3
+ require 'fluent/test/driver/input'
4
+
5
+ module ConfigurationForPlugins
6
+ class AllBooleanParams < Fluent::Plugin::Input
7
+ config_param :flag1, :bool, default: true
8
+ config_param :flag2, :bool, default: true
9
+ config_param :flag3, :bool, default: false
10
+ config_param :flag4, :bool, default: false
11
+
12
+ config_section :child, param_name: :children, multi: true, required: true do
13
+ config_param :flag1, :bool, default: true
14
+ config_param :flag2, :bool, default: true
15
+ config_param :flag3, :bool, default: false
16
+ config_param :flag4, :bool, default: false
17
+ end
18
+ end
19
+
20
+ class BooleanParamsWithoutValue < ::Test::Unit::TestCase
21
+ CONFIG = <<CONFIG
22
+ flag1
23
+ flag2 # yaaaaaaaaaay
24
+ flag3
25
+ flag4 # yaaaaaaaaaay
26
+ <child>
27
+ flag1
28
+ flag2 # yaaaaaaaaaay
29
+ flag3
30
+ flag4 # yaaaaaaaaaay
31
+ </child>
32
+ <child>
33
+ flag1 # yaaaaaaaaaay
34
+ flag2
35
+ flag3 # yaaaaaaaaaay
36
+ flag4
37
+ </child>
38
+ # with following whitespace
39
+ <child>
40
+ flag1
41
+ flag2
42
+ flag3
43
+ flag4
44
+ </child>
45
+ CONFIG
46
+
47
+ test 'create plugin via driver' do
48
+ d = Fluent::Test::Driver::Input.new(AllBooleanParams)
49
+ d.configure(CONFIG)
50
+ assert_equal([true] * 4, [d.instance.flag1, d.instance.flag2, d.instance.flag3, d.instance.flag4])
51
+ num_of_sections = 3
52
+ assert_equal num_of_sections, d.instance.children.size
53
+ assert_equal([true] * (num_of_sections * 4), d.instance.children.map{|c| [c.flag1, c.flag2, c.flag3, c.flag4]}.flatten)
54
+ end
55
+ end
56
+ end
@@ -73,6 +73,24 @@ class GrepFilterTest < Test::Unit::TestCase
73
73
  end
74
74
  end
75
75
  end
76
+
77
+ sub_test_case "pattern with slashes" do
78
+ test "start with character classes" do
79
+ conf = %[
80
+ <regexp>
81
+ key message
82
+ pattern /[a-z]test/
83
+ </regexp>
84
+ <exclude>
85
+ key message
86
+ pattern /[A-Z]test/
87
+ </exclude>
88
+ ]
89
+ d = create_driver(conf)
90
+ assert_equal(/[a-z]test/, d.instance.regexps.first.pattern)
91
+ assert_equal(/[A-Z]test/, d.instance.excludes.first.pattern)
92
+ end
93
+ end
76
94
  end
77
95
 
78
96
  sub_test_case 'filter_stream' do
@@ -486,6 +486,7 @@ EOL
486
486
  retry_type periodic
487
487
  retry_wait 30s
488
488
  flush_at_shutdown false # suppress errors in d.instance_shutdown
489
+ flush_thread_interval 30s
489
490
  </buffer>
490
491
  ])
491
492
 
@@ -501,7 +502,7 @@ EOL
501
502
  target_input_driver.end_if{ d.instance.rollback_count > 0 }
502
503
  target_input_driver.end_if{ !node.available }
503
504
  target_input_driver.run(expect_records: 2, timeout: 25) do
504
- d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false) do
505
+ d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false, flush: false) do
505
506
  delayed_commit_timeout_value = d.instance.delayed_commit_timeout
506
507
  d.feed([[time, records[0]], [time,records[1]]])
507
508
  end
@@ -530,6 +531,7 @@ EOL
530
531
  retry_type periodic
531
532
  retry_wait 30s
532
533
  flush_at_shutdown false # suppress errors in d.instance_shutdown
534
+ flush_thread_interval 30s
533
535
  </buffer>
534
536
  ])
535
537
 
@@ -545,7 +547,7 @@ EOL
545
547
  target_input_driver.end_if{ d.instance.rollback_count > 0 }
546
548
  target_input_driver.end_if{ !node.available }
547
549
  target_input_driver.run(expect_records: 2, timeout: 25) do
548
- d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false) do
550
+ d.run(default_tag: 'test', timeout: 20, wait_flush_completion: false, shutdown: false, flush: false) do
549
551
  delayed_commit_timeout_value = d.instance.delayed_commit_timeout
550
552
  d.feed([[time, records[0]], [time,records[1]]])
551
553
  end
@@ -664,6 +666,51 @@ EOL
664
666
  assert_equal(['test', time, records[1]], events[1])
665
667
  end
666
668
 
669
+ # This test is not 100% but test failed with previous Node implementation which has race condition
670
+ test 'Node with security is thread-safe on multi threads' do
671
+ input_conf = TARGET_CONFIG + %[
672
+ <security>
673
+ self_hostname in.localhost
674
+ shared_key fluentd-sharedkey
675
+ <client>
676
+ host 127.0.0.1
677
+ </client>
678
+ </security>
679
+ ]
680
+ target_input_driver = create_target_input_driver(conf: input_conf)
681
+ output_conf = %[
682
+ send_timeout 51
683
+ <security>
684
+ self_hostname localhost
685
+ shared_key fluentd-sharedkey
686
+ </security>
687
+ <server>
688
+ name test
689
+ host #{TARGET_HOST}
690
+ port #{TARGET_PORT}
691
+ shared_key fluentd-sharedkey
692
+ </server>
693
+ ]
694
+ @d = d = create_driver(output_conf)
695
+
696
+ chunk = Fluent::Plugin::Buffer::MemoryChunk.new(Fluent::Plugin::Buffer::Metadata.new(nil, nil, nil))
697
+ target_input_driver.run(timeout: 15) do
698
+ d.run(shutdown: false) do
699
+ node = d.instance.nodes.first
700
+ arr = []
701
+ 4.times {
702
+ arr << Thread.new {
703
+ node.send_data('test', chunk) rescue nil
704
+ }
705
+ }
706
+ arr.each { |a| a.join }
707
+ end
708
+ end
709
+
710
+ logs = d.logs
711
+ assert_false(logs.any? { |log| log.include?("invalid format for PONG message") || log.include?("shared key mismatch") }, "'#{logs.last.strip}' happens")
712
+ end
713
+
667
714
  def create_target_input_driver(response_stub: nil, disconnect: false, conf: TARGET_CONFIG)
668
715
  require 'fluent/plugin/in_forward'
669
716
 
@@ -907,7 +907,8 @@ class OutputTest < Test::Unit::TestCase
907
907
 
908
908
  sub_test_case 'slow_flush_log_threshold' do
909
909
  def invoke_slow_flush_log_threshold_test(i)
910
- i.configure(config_element('ROOT', '', {'slow_flush_log_threshold' => 0.5}, [config_element('buffer', '', {"flush_mode" => "immediate"})]))
910
+ i.configure(config_element('ROOT', '', {'slow_flush_log_threshold' => 0.5},
911
+ [config_element('buffer', '', {"flush_mode" => "immediate", "flush_thread_interval" => 30})]))
911
912
  i.start
912
913
  i.after_start
913
914
 
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: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-05 00:00:00.000000000 Z
11
+ date: 2018-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -330,7 +330,6 @@ files:
330
330
  - CHANGELOG.md
331
331
  - CONTRIBUTING.md
332
332
  - COPYING
333
- - ENTERPRISE_PROVIDERS.md
334
333
  - GOVERNANCE.md
335
334
  - Gemfile
336
335
  - LICENSE
@@ -603,6 +602,7 @@ files:
603
602
  - test/config/test_dsl.rb
604
603
  - test/config/test_element.rb
605
604
  - test/config/test_literal_parser.rb
605
+ - test/config/test_plugin_configuration.rb
606
606
  - test/config/test_section.rb
607
607
  - test/config/test_system_config.rb
608
608
  - test/config/test_types.rb
@@ -772,6 +772,7 @@ test_files:
772
772
  - test/config/test_dsl.rb
773
773
  - test/config/test_element.rb
774
774
  - test/config/test_literal_parser.rb
775
+ - test/config/test_plugin_configuration.rb
775
776
  - test/config/test_section.rb
776
777
  - test/config/test_system_config.rb
777
778
  - test/config/test_types.rb
@@ -1,43 +0,0 @@
1
- # Fluentd Enterprise Providers
2
-
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
-
5
- ## Fluentd Providers
6
-
7
- The following section lists the companies that provides Support, Consulting Services and Products around Fluentd for the Enterprise needs.
8
-
9
- - [Treasure Data](https://fluentd.treasuredata.com)
10
-
11
- ### Treasure Data
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](https://kafka.apache.org) and [Splunk](https://www.splunk.com) within others.
14
-
15
- For more details about Fluentd Enterprise provided by Treasure Data, click [here](https://fluentd.treasuredata.com/).
16
-
17
- ## Apply to become a Fluentd Service Provider
18
-
19
- In order to keep a transparent involvement of companies in Fluentd growth, to be listed as a service provider your company must fulfil the following criteria:
20
-
21
- - The company offering the services or products must be fully incorporated.
22
- - At least two former employees must be contributors of Fluentd ecosystem (core, plugins, documentation, etc).
23
- - Company participate from Fluentd community activities: meetups, conferences (or webinars) or online communication channels (Slack)
24
-
25
- In order to be listed as a service provider, please send an email using your corporate account to the maintainers (listed at bottom) with the following information:
26
-
27
- - Company Information
28
- - Company Name
29
- - Company URL
30
- - Country / Location
31
- - Employees
32
- - Name, email and github handle of employees who contribute to Fluentd ecosystem
33
- - List of projects or contributions where the company is involved
34
- - Services
35
- - What kind of services around Fluentd do you provide ?
36
- - Community
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](https://cncf.io) ?
39
-
40
- ### Maintainers / Recipients
41
-
42
- - Kiyoto Tamura <kiyoto@treasure-data.com>
43
- - Eduardo Silva <eduardo@treasure-data.com>