fluent-plugin-kinesis 1.3.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -23
  3. data/CHANGELOG.md +13 -0
  4. data/Gemfile +9 -9
  5. data/LICENSE.txt +201 -40
  6. data/Makefile +24 -31
  7. data/README.md +179 -308
  8. data/Rakefile +9 -13
  9. data/benchmark/task.rake +96 -58
  10. data/fluent-plugin-kinesis.gemspec +15 -19
  11. data/gemfiles/Gemfile.fluentd-0.12 +10 -10
  12. data/lib/fluent/plugin/kinesis.rb +166 -0
  13. data/lib/fluent/plugin/kinesis_helper/aggregator.rb +99 -0
  14. data/lib/fluent/plugin/kinesis_helper/api.rb +152 -121
  15. data/lib/fluent/plugin/kinesis_helper/client.rb +125 -12
  16. data/lib/fluent/plugin/out_kinesis_firehose.rb +40 -27
  17. data/lib/fluent/plugin/out_kinesis_streams.rb +51 -30
  18. data/lib/fluent/plugin/out_kinesis_streams_aggregated.rb +76 -0
  19. data/lib/fluent_plugin_kinesis/version.rb +10 -10
  20. metadata +18 -70
  21. data/README-v0.4.md +0 -348
  22. data/benchmark/dummy.conf +0 -0
  23. data/gemfiles/Gemfile.aws-sdk-2.4 +0 -20
  24. data/gemfiles/Gemfile.fluentd-0.10.58 +0 -20
  25. data/gemfiles/Gemfile.fluentd-0.14.11 +0 -20
  26. data/gemfiles/Gemfile.ruby-2.0 +0 -21
  27. data/gemfiles/Gemfile.ruby-2.1 +0 -21
  28. data/lib/fluent/plugin/kinesis_helper.rb +0 -36
  29. data/lib/fluent/plugin/kinesis_helper/class_methods.rb +0 -123
  30. data/lib/fluent/plugin/kinesis_helper/credentials.rb +0 -51
  31. data/lib/fluent/plugin/kinesis_helper/error.rb +0 -43
  32. data/lib/fluent/plugin/kinesis_helper/format.rb +0 -85
  33. data/lib/fluent/plugin/kinesis_helper/initialize.rb +0 -59
  34. data/lib/fluent/plugin/kinesis_helper/kpl.rb +0 -82
  35. data/lib/fluent/plugin/out_kinesis.rb +0 -323
  36. data/lib/fluent/plugin/out_kinesis_producer.rb +0 -48
  37. data/lib/fluent/plugin/patched_detach_process_impl.rb +0 -103
  38. data/lib/kinesis_producer.rb +0 -24
  39. data/lib/kinesis_producer/binary.rb +0 -10
  40. data/lib/kinesis_producer/daemon.rb +0 -270
  41. data/lib/kinesis_producer/library.rb +0 -122
  42. data/lib/kinesis_producer/protobuf/config.pb.rb +0 -66
  43. data/lib/kinesis_producer/protobuf/messages.pb.rb +0 -151
  44. data/lib/kinesis_producer/tasks/binary.rake +0 -73
data/Rakefile CHANGED
@@ -1,16 +1,16 @@
1
1
  #
2
- # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  #
4
- # Licensed under the Amazon Software License (the "License").
5
- # You may not use this file except in compliance with the License.
6
- # A copy of the License is located at
4
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # may not use this file except in compliance with the License. A copy of
6
+ # the License is located at
7
7
  #
8
- # http://aws.amazon.com/asl/
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
9
  #
10
- # or in the "license" file accompanying this file. This file is distributed
11
- # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12
- # express or implied. See the License for the specific language governing
13
- # permissions and limitations under the License.
10
+ # or in the "license" file accompanying this file. This file is
11
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # ANY KIND, either express or implied. See the License for the specific
13
+ # language governing permissions and limitations under the License.
14
14
 
15
15
  require "bundler/gem_tasks"
16
16
 
@@ -23,8 +23,4 @@ Rake::TestTask.new do |test|
23
23
  test.options = '-v'
24
24
  end
25
25
 
26
- load 'kinesis_producer/tasks/binary.rake'
27
- Rake::Task[:build].enhance [:binaries]
28
- Rake::Task[:test].enhance [:binaries]
29
-
30
26
  load 'benchmark/task.rake'
data/benchmark/task.rake CHANGED
@@ -1,72 +1,110 @@
1
1
  #
2
- # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  #
4
- # Licensed under the Amazon Software License (the "License").
5
- # You may not use this file except in compliance with the License.
6
- # A copy of the License is located at
4
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # may not use this file except in compliance with the License. A copy of
6
+ # the License is located at
7
7
  #
8
- # http://aws.amazon.com/asl/
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
9
  #
10
- # or in the "license" file accompanying this file. This file is distributed
11
- # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12
- # express or implied. See the License for the specific language governing
13
- # permissions and limitations under the License.
10
+ # or in the "license" file accompanying this file. This file is
11
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # ANY KIND, either express or implied. See the License for the specific
13
+ # language governing permissions and limitations under the License.
14
14
 
15
- require_relative '../test/dummy_server'
15
+ require_relative '../test/helper'
16
+ require 'fluent/plugin/out_kinesis_streams'
17
+ require 'fluent/plugin/out_kinesis_streams_aggregated'
18
+ require 'fluent/plugin/out_kinesis_firehose'
19
+ require 'benchmark'
20
+ require 'net/empty_port'
16
21
 
17
- task :benchmark do
18
- server = DummyServer.start
19
- conf = profile_conf(ENV["TYPE"] || 'streams', ENV["RATE"] || 1000, server)
20
- pid = spawn("bundle exec fluentd -i '#{conf}' -c benchmark/dummy.conf")
21
- sleep 10
22
- Process.kill("TERM", pid)
23
- Process.wait
24
- puts "Results: requets: #{server.requests.size}, raw_records: #{server.raw_records.size}, records: #{server.records.size}"
25
- server.shutdown
22
+ namespace :benchmark do
23
+ task :local do
24
+ KinesisBenchmark.new.run
25
+ end
26
+ task :remote do
27
+ KinesisBenchmark.new(false).run
28
+ end
26
29
  end
27
30
 
28
- def profile_conf(type, rate, server)
29
- additional_conf = case type
30
- when 'streams', 'firehose'
31
- <<-EOS
32
- endpoint https://localhost:#{server.port}
33
- ssl_verify_peer false
34
- EOS
35
- when 'producer'
36
- <<-EOS
37
- debug true
38
- <kinesis_producer>
39
- custom_endpoint localhost
40
- port #{server.port}
41
- verify_certificate false
42
- record_max_buffered_time 1000
43
- log_level error
44
- </kinesis_producer>
45
- EOS
46
- end
31
+ class KinesisBenchmark
32
+ def initialize(local = true)
33
+ @local = local
34
+ Fluent::Test.setup
35
+ end
47
36
 
48
- conf = <<-EOS
49
- <source>
50
- @type dummy
51
- tag dummy
52
- rate #{rate}
53
- </source>
37
+ def run
38
+ setup
39
+ benchmark(ENV['SIZE'] || 100, ENV['COUNT'] || 10000)
40
+ teardown
41
+ end
54
42
 
55
- <match dummy>
56
- @type kinesis_#{type}
57
- flush_interval 1
58
- buffer_chunk_limit 1m
59
- try_flush_interval 0.1
60
- queued_chunk_flush_interval 0.01
61
- @log_level debug
43
+ def setup
44
+ return if not @local
45
+ @port = Net::EmptyPort.empty_port
46
+ @server_pid = fork do
47
+ Process.setsid
48
+ server = DummyServer.start(port: @port)
49
+ Signal.trap("TERM") do
50
+ server.shutdown
51
+ end
52
+ server.thread.join
53
+ end
54
+ Net::EmptyPort.wait(@port, 3)
55
+ end
62
56
 
63
- num_threads 100
57
+ def teardown
58
+ return if not @local
59
+ Process.kill "TERM", @server_pid
60
+ Process.waitpid @server_pid
61
+ end
64
62
 
65
- region ap-northeast-1
66
- stream_name fluent-plugin-test
63
+ def default_config
64
+ conf = %[
65
+ log_level error
66
+ region ap-northeast-1
67
+ data_key a
68
+ ]
69
+ if @local
70
+ conf += %[
71
+ endpoint https://localhost:#{@port}
72
+ ssl_verify_peer false
73
+ ]
74
+ end
75
+ conf
76
+ end
67
77
 
68
- #{additional_conf}
69
- </match>
70
- EOS
71
- conf
78
+ def create_driver(type, conf = default_config)
79
+ klass = case type
80
+ when :streams
81
+ Fluent::KinesisStreamsOutput
82
+ when :streams_aggregated
83
+ Fluent::KinesisStreamsAggregatedOutput
84
+ when :firehose
85
+ Fluent::KinesisFirehoseOutput
86
+ end
87
+ conf += case type
88
+ when :streams, :streams_aggregated
89
+ "stream_name fluent-plugin-test"
90
+ when :firehose
91
+ "delivery_stream_name fluent-plugin-test"
92
+ end
93
+ if fluentd_v0_12?
94
+ Fluent::Test::BufferedOutputTestDriver.new(klass) do
95
+ end.configure(conf)
96
+ else
97
+ Fluent::Test::Driver::Output.new(klass) do
98
+ end.configure(conf)
99
+ end
100
+ end
101
+
102
+ def benchmark(size, count)
103
+ record = {"a"=>"a"*size}
104
+ Benchmark.bmbm(20) do |x|
105
+ [:streams_aggregated, :streams, :firehose].each do |type|
106
+ x.report(type) { driver_run(create_driver(type), count.times.map{|i|record}) }
107
+ end
108
+ end
109
+ end
72
110
  end
@@ -1,22 +1,21 @@
1
1
  # coding: utf-8
2
2
  #
3
- # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
4
  #
5
- # Licensed under the Amazon Software License (the "License").
6
- # You may not use this file except in compliance with the License.
7
- # A copy of the License is located at
5
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
6
+ # may not use this file except in compliance with the License. A copy of
7
+ # the License is located at
8
8
  #
9
- # http://aws.amazon.com/asl/
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
- # or in the "license" file accompanying this file. This file is distributed
12
- # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13
- # express or implied. See the License for the specific language governing
14
- # permissions and limitations under the License.
11
+ # or in the "license" file accompanying this file. This file is
12
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
13
+ # ANY KIND, either express or implied. See the License for the specific
14
+ # language governing permissions and limitations under the License.
15
15
 
16
16
  lib = File.expand_path('../lib', __FILE__)
17
17
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
18
18
  require 'fluent_plugin_kinesis/version'
19
- require 'kinesis_producer/binary'
20
19
 
21
20
  Gem::Specification.new do |spec|
22
21
  spec.name = "fluent-plugin-kinesis"
@@ -24,19 +23,17 @@ Gem::Specification.new do |spec|
24
23
  spec.author = 'Amazon Web Services'
25
24
  spec.summary = %q{Fluentd output plugin that sends events to Amazon Kinesis.}
26
25
  spec.homepage = "https://github.com/awslabs/aws-fluent-plugin-kinesis"
27
- spec.license = "Amazon Software License"
26
+ spec.license = "Apache-2.0"
28
27
 
29
28
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
30
- spec.files += KinesisProducer::Binary::Files.values
31
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
30
  spec.require_paths = ["lib"]
33
- spec.required_ruby_version = '>= 2.0.0'
31
+ spec.required_ruby_version = '>= 2.1'
34
32
 
35
- spec.add_dependency "fluentd", ">= 0.10.58", "< 2"
36
- spec.add_dependency "protobuf", ">= 3.5.5"
37
- spec.add_dependency "aws-sdk", "~> 2"
38
- spec.add_dependency "concurrent-ruby", "~> 1"
39
- spec.add_dependency "os", ">= 0.9.6"
33
+ spec.add_dependency "fluentd", ">= 0.12.35", "< 2"
34
+ spec.add_dependency "aws-sdk-kinesis", "~> 1"
35
+ spec.add_dependency "aws-sdk-firehose", "~> 1"
36
+ spec.add_dependency "google-protobuf", "~> 3"
40
37
 
41
38
  spec.add_development_dependency "bundler", "~> 1.10"
42
39
  spec.add_development_dependency "rake", "~> 10.0"
@@ -46,7 +43,6 @@ Gem::Specification.new do |spec|
46
43
  spec.add_development_dependency "pry-byebug", ">= 3.3.0"
47
44
  spec.add_development_dependency "pry-stack_explorer", ">= 0.4.9.2"
48
45
  spec.add_development_dependency "net-empty_port", ">= 0.0.2"
49
- spec.add_development_dependency "rubyzip", ">= 1.0.0"
50
46
  spec.add_development_dependency "mocha", ">= 1.1.0"
51
47
  spec.add_development_dependency "webmock", ">= 1.24.2"
52
48
  spec.add_development_dependency "fakefs", ">= 0.8.1"
@@ -1,20 +1,20 @@
1
1
  #
2
- # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  #
4
- # Licensed under the Amazon Software License (the "License").
5
- # You may not use this file except in compliance with the License.
6
- # A copy of the License is located at
4
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # may not use this file except in compliance with the License. A copy of
6
+ # the License is located at
7
7
  #
8
- # http://aws.amazon.com/asl/
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
9
  #
10
- # or in the "license" file accompanying this file. This file is distributed
11
- # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12
- # express or implied. See the License for the specific language governing
13
- # permissions and limitations under the License.
10
+ # or in the "license" file accompanying this file. This file is
11
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # ANY KIND, either express or implied. See the License for the specific
13
+ # language governing permissions and limitations under the License.
14
14
 
15
15
  source 'https://rubygems.org'
16
16
 
17
17
  # Specify your gem's dependencies in fluent-plugin-kinesis.gemspec
18
18
  gemspec path: ".."
19
19
 
20
- gem "fluentd", "~> 0.12.26"
20
+ gem "fluentd", ">= 0.12.35", "< 0.14"
@@ -0,0 +1,166 @@
1
+ #
2
+ # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # may not use this file except in compliance with the License. A copy of
6
+ # the License is located at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # or in the "license" file accompanying this file. This file is
11
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # ANY KIND, either express or implied. See the License for the specific
13
+ # language governing permissions and limitations under the License.
14
+
15
+ require 'fluent/plugin/kinesis_helper/client'
16
+ require 'fluent/plugin/kinesis_helper/api'
17
+ require 'zlib'
18
+
19
+ module Fluent
20
+ class KinesisOutput < BufferedOutput
21
+ def self.fluentd_v0_12?
22
+ @fluentd_v0_12 ||= Gem.loaded_specs['fluentd'].version < Gem::Version.create('0.14')
23
+ end
24
+
25
+ include Fluent::SetTimeKeyMixin
26
+ include Fluent::SetTagKeyMixin
27
+
28
+ include KinesisHelper::Client
29
+ include KinesisHelper::API
30
+
31
+ class SkipRecordError < ::StandardError
32
+ def initialize(message, record)
33
+ super message
34
+ @record_message = if record.is_a? Array
35
+ record.reverse.map(&:to_s).join(', ')
36
+ else
37
+ record.to_s
38
+ end
39
+ end
40
+
41
+ def to_s
42
+ super + ": " + @record_message
43
+ end
44
+ end
45
+ class KeyNotFoundError < SkipRecordError
46
+ def initialize(key, record)
47
+ super "Key '#{key}' doesn't exist", record
48
+ end
49
+ end
50
+ class ExceedMaxRecordSizeError < SkipRecordError
51
+ def initialize(size, record)
52
+ super "Record size limit exceeded in #{size/1024} KB", record
53
+ end
54
+ end
55
+ class InvalidRecordError < SkipRecordError
56
+ def initialize(record)
57
+ super "Invalid type of record", record
58
+ end
59
+ end
60
+
61
+ config_param :data_key, :string, default: nil
62
+ config_param :log_truncate_max_size, :integer, default: 1024
63
+ config_param :compression, :string, default: nil
64
+ config_section :format do
65
+ config_set_default :@type, 'json'
66
+ end
67
+ config_section :inject do
68
+ config_set_default :time_type, 'string'
69
+ config_set_default :time_format, '%Y-%m-%dT%H:%M:%S.%N%z'
70
+ end
71
+
72
+ config_param :debug, :bool, default: false
73
+
74
+ if fluentd_v0_12?
75
+ config_param :format, :string, default: 'json'
76
+ else
77
+ helpers :formatter, :inject
78
+ end
79
+
80
+ def configure(conf)
81
+ super
82
+ @data_formatter = data_formatter_create(conf)
83
+ end
84
+
85
+ def multi_workers_ready?
86
+ true
87
+ end
88
+
89
+ private
90
+
91
+ def fluentd_v0_12?
92
+ self.class.fluentd_v0_12?
93
+ end
94
+
95
+ def data_formatter_create(conf)
96
+ if fluentd_v0_12?
97
+ formatter = Fluent::Plugin.new_formatter(@format)
98
+ formatter.configure(conf)
99
+ else
100
+ formatter = formatter_create
101
+ end
102
+ compressor = compressor_create
103
+ if @data_key.nil?
104
+ ->(tag, time, record) {
105
+ unless fluentd_v0_12?
106
+ record = inject_values_to_record(tag, time, record)
107
+ end
108
+ compressor.call(formatter.format(tag, time, record).chomp.b)
109
+ }
110
+ else
111
+ ->(tag, time, record) {
112
+ raise InvalidRecordError, record unless record.is_a? Hash
113
+ raise KeyNotFoundError.new(@data_key, record) if record[@data_key].nil?
114
+ compressor.call(record[@data_key].to_s.b)
115
+ }
116
+ end
117
+ end
118
+
119
+ def compressor_create
120
+ case @compression
121
+ when "zlib"
122
+ ->(data) { Zlib::Deflate.deflate(data) }
123
+ else
124
+ ->(data) { data }
125
+ end
126
+ end
127
+
128
+ def format_for_api(&block)
129
+ converted = block.call
130
+ size = size_of_values(converted)
131
+ if size > @max_record_size
132
+ raise ExceedMaxRecordSizeError.new(size, converted)
133
+ end
134
+ converted.to_msgpack
135
+ rescue SkipRecordError => e
136
+ log.error(truncate e)
137
+ ''
138
+ end
139
+
140
+ def write_records_batch(chunk, &block)
141
+ if fluentd_v0_12?
142
+ unique_id = chunk.unique_id.unpack('H*').first
143
+ else
144
+ unique_id = chunk.dump_unique_id_hex(chunk.unique_id)
145
+ end
146
+ records = chunk.to_enum(:msgpack_each)
147
+ split_to_batches(records) do |batch, size|
148
+ log.debug(sprintf "Write chunk %s / %3d records / %4d KB", unique_id, batch.size, size/1024)
149
+ batch_request_with_retry(batch, &block)
150
+ log.debug("Finish writing chunk")
151
+ end
152
+ end
153
+
154
+ def request_type
155
+ self.class::RequestType
156
+ end
157
+
158
+ def truncate(msg)
159
+ if @log_truncate_max_size == 0 or (msg.to_s.size <= @log_truncate_max_size)
160
+ msg.to_s
161
+ else
162
+ msg.to_s[0...@log_truncate_max_size]
163
+ end
164
+ end
165
+ end
166
+ end