fluent-plugin-kinesis 0.4.1 → 1.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/.gitignore +13 -18
  3. data/.travis.yml +9 -9
  4. data/CHANGELOG.md +9 -0
  5. data/CONTRIBUTORS.txt +1 -1
  6. data/Gemfile +12 -9
  7. data/LICENSE.txt +39 -201
  8. data/Makefile +40 -0
  9. data/NOTICE.txt +1 -1
  10. data/README-v0.4.md +348 -0
  11. data/README.md +398 -183
  12. data/Rakefile +20 -14
  13. data/benchmark/dummer.conf +13 -0
  14. data/benchmark/firehose.conf +24 -0
  15. data/benchmark/producer.conf +28 -0
  16. data/benchmark/streams.conf +24 -0
  17. data/fluent-plugin-kinesis.gemspec +34 -23
  18. data/gemfiles/Gemfile.fluentd-0.10.58 +20 -0
  19. data/lib/fluent/plugin/kinesis_helper.rb +30 -0
  20. data/lib/fluent/plugin/kinesis_helper/api.rb +164 -0
  21. data/lib/fluent/plugin/kinesis_helper/class_methods.rb +120 -0
  22. data/lib/fluent/plugin/kinesis_helper/client.rb +36 -0
  23. data/lib/fluent/plugin/kinesis_helper/credentials.rb +51 -0
  24. data/lib/fluent/plugin/kinesis_helper/error.rb +38 -0
  25. data/lib/fluent/plugin/kinesis_helper/format.rb +85 -0
  26. data/lib/fluent/plugin/kinesis_helper/initialize.rb +58 -0
  27. data/lib/fluent/plugin/kinesis_helper/kpl.rb +81 -0
  28. data/lib/fluent/plugin/out_kinesis.rb +13 -11
  29. data/lib/fluent/plugin/out_kinesis_firehose.rb +44 -0
  30. data/lib/fluent/plugin/out_kinesis_producer.rb +38 -0
  31. data/lib/fluent/plugin/out_kinesis_streams.rb +47 -0
  32. data/lib/fluent/plugin/patched_detach_process_impl.rb +103 -0
  33. data/lib/fluent_plugin_kinesis/version.rb +17 -0
  34. data/lib/kinesis_producer.rb +24 -0
  35. data/lib/kinesis_producer/binary.rb +10 -0
  36. data/lib/kinesis_producer/daemon.rb +238 -0
  37. data/lib/kinesis_producer/library.rb +122 -0
  38. data/lib/kinesis_producer/protobuf/config.pb.rb +66 -0
  39. data/lib/kinesis_producer/protobuf/messages.pb.rb +151 -0
  40. data/lib/kinesis_producer/tasks/binary.rake +73 -0
  41. metadata +196 -36
  42. data/lib/fluent/plugin/version.rb +0 -16
  43. data/test/helper.rb +0 -32
  44. data/test/plugin/test_out_kinesis.rb +0 -641
data/Rakefile CHANGED
@@ -1,23 +1,29 @@
1
- # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
1
  #
3
- # Licensed under the Apache License, Version 2.0 (the "License"). You
4
- # may not use this file except in compliance with the License. A copy of
5
- # the License is located at
2
+ # Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
6
3
  #
7
- # http://www.apache.org/licenses/LICENSE-2.0
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
8
7
  #
9
- # or in the "license" file accompanying this file. This file is
10
- # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
- # ANY KIND, either express or implied. See the License for the specific
12
- # language governing permissions and limitations under the License.
8
+ # http://aws.amazon.com/asl/
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.
13
14
 
14
15
  require "bundler/gem_tasks"
15
16
 
16
17
  require 'rake/testtask'
17
- Rake::TestTask.new(:test) do |test|
18
- test.libs << 'lib' << 'test'
19
- test.pattern = 'test/**/test_*.rb'
20
- test.verbose = true
18
+
19
+ task default: [:test]
20
+ Rake::TestTask.new do |test|
21
+ test.libs << 'lib' << 'test'
22
+ test.test_files = FileList['test/**/test_*.rb']
23
+ test.options = '-v'
21
24
  end
22
25
 
23
- task :default => :test
26
+ load 'kinesis_producer/tasks/binary.rake'
27
+
28
+ Rake::Task[:build].enhance [:binaries]
29
+ Rake::Task[:test].enhance [:binaries]
@@ -0,0 +1,13 @@
1
+ configure 'sample' do
2
+ output "/tmp/dummy.log"
3
+ rate 5000
4
+ delimiter "\t"
5
+ labeled true
6
+ field :id, type: :integer, countup: true, format: "%04d"
7
+ field :time, type: :datetime, format: "[%Y-%m-%d %H:%M:%S]", random: false
8
+ field :level, type: :string, any: %w[DEBUG INFO WARN ERROR]
9
+ field :method, type: :string, any: %w[GET POST PUT]
10
+ field :uri, type: :string, any: %w[/api/v1/people /api/v1/textdata /api/v1/messages]
11
+ field :reqtime, type: :float, range: 0.1..5.0
12
+ field :foobar, type: :string, length: 8
13
+ end
@@ -0,0 +1,24 @@
1
+ <source>
2
+ @type tail
3
+ path /tmp/dummy.log
4
+ format none
5
+ tag dummy
6
+ </source>
7
+
8
+ <source>
9
+ @type forward
10
+ </source>
11
+
12
+ <match dummy>
13
+ @type kinesis_firehose
14
+ flush_interval 1
15
+ buffer_chunk_limit 1m
16
+ try_flush_interval 0.1
17
+ queued_chunk_flush_interval 0.01
18
+ num_threads 15
19
+ detach_process 5
20
+ log_level debug
21
+
22
+ region us-west-2
23
+ delivery_stream_name fluent-plugin-test
24
+ </match>
@@ -0,0 +1,28 @@
1
+ <source>
2
+ @type tail
3
+ path /tmp/dummy.log
4
+ format none
5
+ tag dummy
6
+ </source>
7
+
8
+ <source>
9
+ @type forward
10
+ </source>
11
+
12
+ <match dummy>
13
+ @type kinesis_producer
14
+ flush_interval 1
15
+ buffer_chunk_limit 1m
16
+ try_flush_interval 0.1
17
+ queued_chunk_flush_interval 0.01
18
+ num_threads 15
19
+ detach_process 5
20
+ log_level debug
21
+
22
+ region ap-northeast-1
23
+ stream_name fluent-plugin-test
24
+ debug true
25
+ <kinesis_producer>
26
+ record_max_buffered_time 1000
27
+ </kinesis_producer>
28
+ </match>
@@ -0,0 +1,24 @@
1
+ <source>
2
+ @type tail
3
+ path /tmp/dummy.log
4
+ format none
5
+ tag dummy
6
+ </source>
7
+
8
+ <source>
9
+ @type forward
10
+ </source>
11
+
12
+ <match dummy>
13
+ @type kinesis_streams
14
+ flush_interval 1
15
+ buffer_chunk_limit 1m
16
+ try_flush_interval 0.1
17
+ queued_chunk_flush_interval 0.01
18
+ num_threads 15
19
+ detach_process 5
20
+ log_level debug
21
+
22
+ region ap-northeast-1
23
+ stream_name fluent-plugin-test
24
+ </match>
@@ -1,21 +1,22 @@
1
- # Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
1
+ # coding: utf-8
2
+ #
3
+ # Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
4
  #
3
- # Licensed under the Apache License, Version 2.0 (the "License"). You
4
- # may not use this file except in compliance with the License. A copy of
5
- # the License is located at
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
6
8
  #
7
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://aws.amazon.com/asl/
8
10
  #
9
- # or in the "license" file accompanying this file. This file is
10
- # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
- # ANY KIND, either express or implied. See the License for the specific
12
- # language governing permissions and limitations under the License.
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.
13
15
 
14
- # coding: utf-8
15
16
  lib = File.expand_path('../lib', __FILE__)
16
17
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
17
-
18
- require "fluent/plugin/version"
18
+ require 'fluent_plugin_kinesis/version'
19
+ require 'kinesis_producer/binary'
19
20
 
20
21
  Gem::Specification.new do |spec|
21
22
  spec.name = "fluent-plugin-kinesis"
@@ -23,19 +24,29 @@ Gem::Specification.new do |spec|
23
24
  spec.author = 'Amazon Web Services'
24
25
  spec.summary = %q{Fluentd output plugin that sends events to Amazon Kinesis.}
25
26
  spec.homepage = "https://github.com/awslabs/aws-fluent-plugin-kinesis"
26
- spec.license = "Apache License, Version 2.0"
27
+ spec.license = "Amazon Software License"
27
28
 
28
- spec.files = `git ls-files`.split($/)
29
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
30
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
29
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
30
+ spec.files += KinesisProducer::Binary::Files.values
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
32
  spec.require_paths = ["lib"]
32
- spec.required_ruby_version = '>= 1.9.3'
33
+ spec.required_ruby_version = '>= 2.0.0'
33
34
 
34
- spec.add_development_dependency "bundler", "~> 1.3"
35
- spec.add_development_dependency "rake", "~> 10.0"
36
- spec.add_development_dependency "test-unit-rr", "~> 1.0"
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"
37
40
 
38
- spec.add_dependency "fluentd", ">= 0.10.53", "< 2"
39
- spec.add_dependency "aws-sdk-core", ">= 2.0.12", "< 3.0"
40
- spec.add_dependency "msgpack", ">= 0.5.8"
41
+ spec.add_development_dependency "bundler", "~> 1.10"
42
+ spec.add_development_dependency "rake", "~> 10.0"
43
+ spec.add_development_dependency "test-unit", ">= 3.0.8"
44
+ spec.add_development_dependency "test-unit-rr", ">= 1.0.3"
45
+ spec.add_development_dependency "pry", ">= 0.10.1"
46
+ spec.add_development_dependency "pry-byebug", ">= 3.3.0"
47
+ spec.add_development_dependency "pry-stack_explorer", ">= 0.4.9.2"
48
+ spec.add_development_dependency "net-empty_port", ">= 0.0.2"
49
+ spec.add_development_dependency "dummer", ">= 0.4.0"
50
+ spec.add_development_dependency "rubyzip", ">= 1.0.0"
51
+ spec.add_development_dependency "mocha", ">= 1.1.0"
41
52
  end
@@ -0,0 +1,20 @@
1
+ #
2
+ # Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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
7
+ #
8
+ # http://aws.amazon.com/asl/
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.
14
+
15
+ source 'https://rubygems.org'
16
+
17
+ # Specify your gem's dependencies in fluent-plugin-kinesis.gemspec
18
+ gemspec path: ".."
19
+
20
+ gem "fluentd", "0.10.58"
@@ -0,0 +1,30 @@
1
+ #
2
+ # Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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
7
+ #
8
+ # http://aws.amazon.com/asl/
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.
14
+
15
+ require 'fluent/plugin/kinesis_helper/class_methods'
16
+ require 'fluent/plugin/kinesis_helper/initialize'
17
+ require 'fluent/plugin/kinesis_helper/error'
18
+
19
+ module Fluent
20
+ module KinesisHelper
21
+ include Fluent::SetTimeKeyMixin
22
+ include Fluent::SetTagKeyMixin
23
+ include Fluent::DetachMultiProcessMixin
24
+
25
+ def self.included(klass)
26
+ klass.extend ClassMethods
27
+ end
28
+ include Initialize
29
+ end
30
+ end
@@ -0,0 +1,164 @@
1
+ #
2
+ # Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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
7
+ #
8
+ # http://aws.amazon.com/asl/
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.
14
+
15
+ require 'fluent_plugin_kinesis/version'
16
+
17
+ module Fluent
18
+ module KinesisHelper
19
+ module API
20
+ def configure(conf)
21
+ super
22
+ if @batch_request_max_count > self.class::BatchRequestLimitCount
23
+ raise ConfigError, "batch_request_max_count can't be grater than #{self.class::BatchRequestLimitCount}."
24
+ end
25
+ if @batch_request_max_size > self.class::BatchRequestLimitSize
26
+ raise ConfigError, "batch_request_max_size can't be grater than #{self.class::BatchRequestLimitSize}."
27
+ end
28
+ @region = client.config.region if @region.nil?
29
+ end
30
+
31
+ def start
32
+ detach_multi_process do
33
+ super
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def client_options
40
+ options = {
41
+ user_agent_suffix: "fluent-plugin-kinesis/#{request_type}/#{FluentPluginKinesis::VERSION}",
42
+ credentials: credentials,
43
+ }
44
+ options.update(region: @region) unless @region.nil?
45
+ options.update(http_proxy: @http_proxy) unless @http_proxy.nil?
46
+ options.update(endpoint: @endpoint) unless @endpoint.nil?
47
+ options.update(ssl_verify_peer: @ssl_verify_peer) unless @ssl_verify_peer.nil?
48
+ if @debug
49
+ options.update(logger: Logger.new(log.out))
50
+ options.update(log_level: :debug)
51
+ end
52
+ options
53
+ end
54
+
55
+ def split_to_batches(records)
56
+ batch_by_limit(records, @batch_request_max_count, @batch_request_max_size)
57
+ end
58
+
59
+ def batch_by_limit(records, max_count, max_size)
60
+ result, buf, size = records.inject([[],[],0]){|(result, buf, size), record|
61
+ if buf.size >= max_count or size >= max_size
62
+ result << buf
63
+ buf = []
64
+ size = 0
65
+ end
66
+ buf << record
67
+ size += size_of_values(record)
68
+ [result, buf, size]
69
+ }
70
+ result << buf
71
+ end
72
+
73
+ def size_of_values(record)
74
+ record.values_at(:data, :partition_key).compact.map(&:size).inject(:+) || 0
75
+ end
76
+
77
+ def batch_request_with_retry(batch, retry_count=0, backoff: nil)
78
+ backoff ||= Backoff.new
79
+ res = batch_request(batch)
80
+ if failed_count(res) > 0
81
+ failed_records = collect_failed_records(batch, res)
82
+ if retry_count < @retries_on_batch_request
83
+ backoff.reset if @reset_backoff_if_success and any_records_shipped?(res)
84
+ sleep(backoff.next)
85
+ log.warn(truncate 'Retrying to request batch. Retry count: %d, Retry records: %d' % [retry_count, failed_records.size])
86
+ retry_batch = failed_records.map{|r| r[:original] }
87
+ batch_request_with_retry(retry_batch, retry_count + 1, backoff: backoff)
88
+ else
89
+ give_up_retries(failed_records)
90
+ end
91
+ end
92
+ end
93
+
94
+ def any_records_shipped?(res)
95
+ results(res).size > failed_count(res)
96
+ end
97
+
98
+ def collect_failed_records(records, res)
99
+ failed_records = []
100
+ results(res).each_with_index do |record, index|
101
+ next unless record[:error_code]
102
+ failed_records.push(
103
+ original: records[index],
104
+ error_code: record[:error_code],
105
+ error_message: record[:error_message]
106
+ )
107
+ end
108
+ failed_records
109
+ end
110
+
111
+ def failed_count(res)
112
+ failed_field = case request_type
113
+ when :streams; :failed_record_count
114
+ when :firehose; :failed_put_count
115
+ end
116
+ res[failed_field]
117
+ end
118
+
119
+ def results(res)
120
+ result_field = case request_type
121
+ when :streams; :records
122
+ when :firehose; :request_responses
123
+ end
124
+ res[result_field]
125
+ end
126
+
127
+ def give_up_retries(failed_records)
128
+ failed_records.each {|record|
129
+ log.error(truncate 'Could not put record, Error: %s/%s, Record: %s' % [
130
+ record[:error_code],
131
+ record[:error_message],
132
+ record[:original]
133
+ ])
134
+ }
135
+ end
136
+
137
+ class Backoff
138
+ def initialize
139
+ @count = 0
140
+ end
141
+
142
+ def next
143
+ value = calc(@count)
144
+ @count += 1
145
+ value
146
+ end
147
+
148
+ def reset
149
+ @count = 0
150
+ end
151
+
152
+ private
153
+
154
+ def calc(count)
155
+ (2 ** count) * scaling_factor
156
+ end
157
+
158
+ def scaling_factor
159
+ 0.3 + (0.5-rand) * 0.1
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,120 @@
1
+ #
2
+ # Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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
7
+ #
8
+ # http://aws.amazon.com/asl/
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.
14
+
15
+ module Fluent
16
+ module KinesisHelper
17
+ module ClassMethods
18
+ def config_param_for_streams
19
+ const_set(:RequestType, :streams)
20
+ const_set(:BatchRequestLimitCount, 500)
21
+ const_set(:BatchRequestLimitSize, 5 * 1024 * 1024)
22
+ config_param :stream_name, :string
23
+ config_param :region, :string, default: nil
24
+ config_param :partition_key, :string, default: nil
25
+ config_param_for_sdk
26
+ config_param_for_credentials
27
+ config_param_for_format
28
+ config_param_for_batch_request
29
+ config_param_for_debug
30
+ end
31
+
32
+ def config_param_for_firehose
33
+ const_set(:RequestType, :firehose)
34
+ const_set(:BatchRequestLimitCount, 500)
35
+ const_set(:BatchRequestLimitSize, 4 * 1024 * 1024)
36
+ config_param :delivery_stream_name, :string
37
+ config_param :region, :string, default: nil
38
+ config_param :append_new_line, :bool, default: true
39
+ config_param_for_sdk
40
+ config_param_for_credentials
41
+ config_param_for_format
42
+ config_param_for_batch_request
43
+ config_param_for_debug
44
+ end
45
+
46
+ def config_param_for_producer
47
+ const_set(:RequestType, :producer)
48
+ config_param :stream_name, :string
49
+ config_param :region, :string, default: nil
50
+ config_param :partition_key, :string, default: nil
51
+ config_param_for_credentials
52
+ config_param_for_format
53
+ config_param_for_debug
54
+
55
+ config_section :kinesis_producer, multi: false do
56
+ require 'kinesis_producer'
57
+ type_map = {
58
+ Protobuf::Field::BoolField => :bool,
59
+ Protobuf::Field::Uint64Field => :integer,
60
+ Protobuf::Field::StringField => :string,
61
+ }
62
+ KinesisProducer::ConfigurationFields.each do |field|
63
+ next if field.name == 'region'
64
+ type = type_map[field.type_class]
65
+ config_param field.name, type, default: field.default_value
66
+ end
67
+ config_param :credentials_refresh_delay, :integer, default: 5000
68
+ end
69
+ end
70
+
71
+ def config_param_for_sdk
72
+ config_param :http_proxy, :string, default: nil
73
+ config_param :endpoint, :string, default: nil
74
+ config_param :ssl_verify_peer, :bool, default: true
75
+ end
76
+
77
+ def config_param_for_credentials
78
+ config_param :aws_key_id, :string, default: nil, secret: true
79
+ config_param :aws_sec_key, :string, default: nil, secret: true
80
+ config_section :shared_credentials, multi: false do
81
+ config_param :profile_name, :string, default: nil
82
+ config_param :path, :string, default: nil
83
+ end
84
+ config_section :assume_role_credentials, multi: false do
85
+ config_param :role_arn, :string, secret: true
86
+ config_param :external_id, :string, default: nil, secret: true
87
+ end
88
+ end
89
+
90
+ def config_param_for_format
91
+ config_param :formatter, :string, default: 'json'
92
+ config_param :data_key, :string, default: nil
93
+ config_param :log_truncate_max_size, :integer, default: 0
94
+ end
95
+
96
+ def config_param_for_batch_request
97
+ config_param :retries_on_batch_request, :integer, default: 3
98
+ config_param :reset_backoff_if_success, :bool, default: true
99
+ config_param :batch_request_max_count, :integer, default: const_get(:BatchRequestLimitCount)
100
+ config_param :batch_request_max_size, :integer, default: const_get(:BatchRequestLimitSize)
101
+ end
102
+
103
+ def config_param_for_debug
104
+ config_param :debug, :bool, default: false
105
+ end
106
+
107
+ def request_type
108
+ const_get(:RequestType)
109
+ end
110
+
111
+ def api?
112
+ [:streams, :firehose].include?(request_type)
113
+ end
114
+
115
+ def kpl?
116
+ [:producer].include?(request_type)
117
+ end
118
+ end
119
+ end
120
+ end