fluent-plugin-kinesis 2.2.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,178 +16,180 @@ require 'fluent_plugin_kinesis/version'
16
16
  require 'fluent/configurable'
17
17
 
18
18
  module Fluent
19
- module KinesisHelper
20
- module API
21
- MaxRecordSize = 1024 * 1024 # 1 MB
19
+ module Plugin
20
+ module KinesisHelper
21
+ module API
22
+ MaxRecordSize = 1024 * 1024 # 1 MB
22
23
 
23
- module APIParams
24
- include Fluent::Configurable
25
- config_param :max_record_size, :integer, default: MaxRecordSize
26
- end
27
-
28
- def self.included(mod)
29
- mod.include APIParams
30
- end
31
-
32
- def configure(conf)
33
- super
34
- if @max_record_size > MaxRecordSize
35
- raise ConfigError, "max_record_size can't be grater than #{MaxRecordSize/1024} KB."
36
- end
37
- end
38
-
39
- module BatchRequest
40
- module BatchRequestParams
24
+ module APIParams
41
25
  include Fluent::Configurable
42
- config_param :retries_on_batch_request, :integer, default: 8
43
- config_param :reset_backoff_if_success, :bool, default: true
44
- config_param :batch_request_max_count, :integer, default: nil
45
- config_param :batch_request_max_size, :integer, default: nil
26
+ config_param :max_record_size, :integer, default: MaxRecordSize
46
27
  end
47
28
 
48
29
  def self.included(mod)
49
- mod.include BatchRequestParams
30
+ mod.include APIParams
50
31
  end
51
32
 
52
33
  def configure(conf)
53
34
  super
54
- if @batch_request_max_count.nil?
55
- @batch_request_max_count = self.class::BatchRequestLimitCount
56
- elsif @batch_request_max_count > self.class::BatchRequestLimitCount
57
- raise ConfigError, "batch_request_max_count can't be grater than #{self.class::BatchRequestLimitCount}."
58
- end
59
- if @batch_request_max_size.nil?
60
- @batch_request_max_size = self.class::BatchRequestLimitSize
61
- elsif @batch_request_max_size > self.class::BatchRequestLimitSize
62
- raise ConfigError, "batch_request_max_size can't be grater than #{self.class::BatchRequestLimitSize}."
35
+ if @max_record_size > MaxRecordSize
36
+ raise ConfigError, "max_record_size can't be grater than #{MaxRecordSize/1024} KB."
63
37
  end
64
38
  end
65
39
 
66
- def size_of_values(record)
67
- record.compact.map(&:size).inject(:+) || 0
68
- end
40
+ module BatchRequest
41
+ module BatchRequestParams
42
+ include Fluent::Configurable
43
+ config_param :retries_on_batch_request, :integer, default: 8
44
+ config_param :reset_backoff_if_success, :bool, default: true
45
+ config_param :batch_request_max_count, :integer, default: nil
46
+ config_param :batch_request_max_size, :integer, default: nil
47
+ end
69
48
 
70
- private
71
-
72
- def split_to_batches(records, &block)
73
- batch = []
74
- size = 0
75
- records.each do |record|
76
- record_size = size_of_values(record)
77
- if batch.size+1 > @batch_request_max_count or size+record_size > @batch_request_max_size
78
- yield(batch, size)
79
- batch = []
80
- size = 0
81
- end
82
- batch << record
83
- size += record_size
49
+ def self.included(mod)
50
+ mod.include BatchRequestParams
84
51
  end
85
- yield(batch, size) if batch.size > 0
86
- end
87
52
 
88
- def batch_request_with_retry(batch, retry_count=0, backoff: nil, &block)
89
- backoff ||= Backoff.new
90
- res = yield(batch)
91
- if failed_count(res) > 0
92
- failed_records = collect_failed_records(batch, res)
93
- if retry_count < @retries_on_batch_request
94
- backoff.reset if @reset_backoff_if_success and any_records_shipped?(res)
95
- wait_second = backoff.next
96
- msg = 'Retrying to request batch. Retry count: %3d, Retry records: %3d, Wait seconds %3.2f' % [retry_count+1, failed_records.size, wait_second]
97
- log.warn(truncate msg)
98
- # TODO: sleep() doesn't wait the given seconds sometime.
99
- # The root cause is unknown so far, so I'd like to add debug print only. It should be fixed in the future.
100
- log.debug("#{Thread.current.object_id} sleep start")
101
- sleep(wait_second)
102
- log.debug("#{Thread.current.object_id} sleep finish")
103
- batch_request_with_retry(retry_records(failed_records), retry_count+1, backoff: backoff, &block)
104
- else
105
- give_up_retries(failed_records)
53
+ def configure(conf)
54
+ super
55
+ if @batch_request_max_count.nil?
56
+ @batch_request_max_count = self.class::BatchRequestLimitCount
57
+ elsif @batch_request_max_count > self.class::BatchRequestLimitCount
58
+ raise ConfigError, "batch_request_max_count can't be grater than #{self.class::BatchRequestLimitCount}."
59
+ end
60
+ if @batch_request_max_size.nil?
61
+ @batch_request_max_size = self.class::BatchRequestLimitSize
62
+ elsif @batch_request_max_size > self.class::BatchRequestLimitSize
63
+ raise ConfigError, "batch_request_max_size can't be grater than #{self.class::BatchRequestLimitSize}."
106
64
  end
107
65
  end
108
- end
109
66
 
110
- def any_records_shipped?(res)
111
- results(res).size > failed_count(res)
112
- end
113
-
114
- def collect_failed_records(records, res)
115
- failed_records = []
116
- results(res).each_with_index do |record, index|
117
- next unless record[:error_code]
118
- original = case request_type
119
- when :streams, :firehose; records[index]
120
- when :streams_aggregated; records
121
- end
122
- failed_records.push(
123
- original: original,
124
- error_code: record[:error_code],
125
- error_message: record[:error_message]
126
- )
67
+ def size_of_values(record)
68
+ record.compact.map(&:size).inject(:+) || 0
127
69
  end
128
- failed_records
70
+
71
+ private
72
+
73
+ def split_to_batches(records, &block)
74
+ batch = []
75
+ size = 0
76
+ records.each do |record|
77
+ record_size = size_of_values(record)
78
+ if batch.size+1 > @batch_request_max_count or size+record_size > @batch_request_max_size
79
+ yield(batch, size)
80
+ batch = []
81
+ size = 0
129
82
  end
83
+ batch << record
84
+ size += record_size
85
+ end
86
+ yield(batch, size) if batch.size > 0
87
+ end
130
88
 
131
- def retry_records(failed_records)
132
- case request_type
133
- when :streams, :firehose
134
- failed_records.map{|r| r[:original] }
135
- when :streams_aggregated
136
- failed_records.first[:original]
89
+ def batch_request_with_retry(batch, retry_count=0, backoff: nil, &block)
90
+ backoff ||= Backoff.new
91
+ res = yield(batch)
92
+ if failed_count(res) > 0
93
+ failed_records = collect_failed_records(batch, res)
94
+ if retry_count < @retries_on_batch_request
95
+ backoff.reset if @reset_backoff_if_success and any_records_shipped?(res)
96
+ wait_second = backoff.next
97
+ msg = 'Retrying to request batch. Retry count: %3d, Retry records: %3d, Wait seconds %3.2f' % [retry_count+1, failed_records.size, wait_second]
98
+ log.warn(truncate msg)
99
+ # TODO: sleep() doesn't wait the given seconds sometime.
100
+ # The root cause is unknown so far, so I'd like to add debug print only. It should be fixed in the future.
101
+ log.debug("#{Thread.current.object_id} sleep start")
102
+ sleep(wait_second)
103
+ log.debug("#{Thread.current.object_id} sleep finish")
104
+ batch_request_with_retry(retry_records(failed_records), retry_count+1, backoff: backoff, &block)
105
+ else
106
+ give_up_retries(failed_records)
107
+ end
108
+ end
137
109
  end
138
- end
139
110
 
140
- def failed_count(res)
141
- failed_field = case request_type
142
- when :streams; :failed_record_count
143
- when :streams_aggregated; :failed_record_count
144
- when :firehose; :failed_put_count
145
- end
146
- res[failed_field]
147
- end
111
+ def any_records_shipped?(res)
112
+ results(res).size > failed_count(res)
113
+ end
148
114
 
149
- def results(res)
150
- result_field = case request_type
151
- when :streams; :records
152
- when :streams_aggregated; :records
153
- when :firehose; :request_responses
115
+ def collect_failed_records(records, res)
116
+ failed_records = []
117
+ results(res).each_with_index do |record, index|
118
+ next unless record[:error_code]
119
+ original = case request_type
120
+ when :streams, :firehose; records[index]
121
+ when :streams_aggregated; records
154
122
  end
155
- res[result_field]
156
- end
123
+ failed_records.push(
124
+ original: original,
125
+ error_code: record[:error_code],
126
+ error_message: record[:error_message]
127
+ )
128
+ end
129
+ failed_records
130
+ end
157
131
 
158
- def give_up_retries(failed_records)
159
- failed_records.each {|record|
160
- log.error(truncate 'Could not put record, Error: %s/%s, Record: %s' % [
161
- record[:error_code],
162
- record[:error_message],
163
- record[:original]
164
- ])
165
- }
166
- end
132
+ def retry_records(failed_records)
133
+ case request_type
134
+ when :streams, :firehose
135
+ failed_records.map{|r| r[:original] }
136
+ when :streams_aggregated
137
+ failed_records.first[:original]
138
+ end
139
+ end
167
140
 
168
- class Backoff
169
- def initialize
170
- @count = 0
141
+ def failed_count(res)
142
+ failed_field = case request_type
143
+ when :streams; :failed_record_count
144
+ when :streams_aggregated; :failed_record_count
145
+ when :firehose; :failed_put_count
146
+ end
147
+ res[failed_field]
171
148
  end
172
149
 
173
- def next
174
- value = calc(@count)
175
- @count += 1
176
- value
150
+ def results(res)
151
+ result_field = case request_type
152
+ when :streams; :records
153
+ when :streams_aggregated; :records
154
+ when :firehose; :request_responses
155
+ end
156
+ res[result_field]
177
157
  end
178
158
 
179
- def reset
180
- @count = 0
159
+ def give_up_retries(failed_records)
160
+ failed_records.each {|record|
161
+ log.error(truncate 'Could not put record, Error: %s/%s, Record: %s' % [
162
+ record[:error_code],
163
+ record[:error_message],
164
+ record[:original]
165
+ ])
166
+ }
181
167
  end
182
168
 
183
- private
169
+ class Backoff
170
+ def initialize
171
+ @count = 0
172
+ end
184
173
 
185
- def calc(count)
186
- (2 ** count) * scaling_factor
187
- end
174
+ def next
175
+ value = calc(@count)
176
+ @count += 1
177
+ value
178
+ end
179
+
180
+ def reset
181
+ @count = 0
182
+ end
183
+
184
+ private
188
185
 
189
- def scaling_factor
190
- 0.3 + (0.5-rand) * 0.1
186
+ def calc(count)
187
+ (2 ** count) * scaling_factor
188
+ end
189
+
190
+ def scaling_factor
191
+ 0.3 + (0.5-rand) * 0.1
192
+ end
191
193
  end
192
194
  end
193
195
  end
@@ -16,152 +16,142 @@ require 'fluent/configurable'
16
16
  require 'aws-sdk-core'
17
17
 
18
18
  module Fluent
19
- module KinesisHelper
20
- module Client
21
- module ClientParams
22
- include Fluent::Configurable
23
- config_param :region, :string, default: nil
19
+ module Plugin
20
+ module KinesisHelper
21
+ module Client
22
+ module ClientParams
23
+ include Fluent::Configurable
24
+ config_param :region, :string, default: nil
24
25
 
25
- config_param :http_proxy, :string, default: nil, secret: true
26
- config_param :endpoint, :string, default: nil
27
- config_param :ssl_verify_peer, :bool, default: true
26
+ config_param :http_proxy, :string, default: nil, secret: true
27
+ config_param :endpoint, :string, default: nil
28
+ config_param :ssl_verify_peer, :bool, default: true
28
29
 
29
- config_param :aws_key_id, :string, default: nil, secret: true
30
- config_param :aws_sec_key, :string, default: nil, secret: true
31
- config_section :assume_role_credentials, multi: false do
32
- desc "The Amazon Resource Name (ARN) of the role to assume"
33
- config_param :role_arn, :string, secret: true
34
- desc "An identifier for the assumed role session"
35
- config_param :role_session_name, :string
36
- desc "An IAM policy in JSON format"
37
- config_param :policy, :string, default: nil
38
- desc "The duration, in seconds, of the role session (900-3600)"
39
- config_param :duration_seconds, :integer, default: nil
40
- desc "A unique identifier that is used by third parties when assuming roles in their customers' accounts."
41
- config_param :external_id, :string, default: nil, secret: true
42
- desc "A http proxy url for requests to aws sts service"
43
- config_param :sts_http_proxy, :string, default: nil, secret: true
44
- end
45
- config_section :instance_profile_credentials, multi: false do
46
- desc "Number of times to retry when retrieving credentials"
47
- config_param :retries, :integer, default: nil
48
- desc "IP address (default:169.254.169.254)"
49
- config_param :ip_address, :string, default: nil
50
- desc "Port number (default:80)"
51
- config_param :port, :integer, default: nil
52
- desc "Number of seconds to wait for the connection to open"
53
- config_param :http_open_timeout, :float, default: nil
54
- desc "Number of seconds to wait for one block to be read"
55
- config_param :http_read_timeout, :float, default: nil
56
- # config_param :delay, :integer or :proc, :default => nil
57
- # config_param :http_degub_output, :io, :default => nil
58
- end
59
- config_section :shared_credentials, multi: false do
60
- desc "Path to the shared file. (default: $HOME/.aws/credentials)"
61
- config_param :path, :string, default: nil
62
- desc "Profile name. Default to 'default' or ENV['AWS_PROFILE']"
63
- config_param :profile_name, :string, default: nil
30
+ config_param :aws_key_id, :string, default: nil, secret: true
31
+ config_param :aws_sec_key, :string, default: nil, secret: true
32
+ config_section :assume_role_credentials, multi: false do
33
+ desc "The Amazon Resource Name (ARN) of the role to assume"
34
+ config_param :role_arn, :string, secret: true
35
+ desc "An identifier for the assumed role session"
36
+ config_param :role_session_name, :string
37
+ desc "An IAM policy in JSON format"
38
+ config_param :policy, :string, default: nil
39
+ desc "The duration, in seconds, of the role session (900-3600)"
40
+ config_param :duration_seconds, :integer, default: nil
41
+ desc "A unique identifier that is used by third parties when assuming roles in their customers' accounts."
42
+ config_param :external_id, :string, default: nil, secret: true
43
+ desc "A http proxy url for requests to aws sts service"
44
+ config_param :sts_http_proxy, :string, default: nil, secret: true
45
+ end
46
+ config_section :instance_profile_credentials, multi: false do
47
+ desc "Number of times to retry when retrieving credentials"
48
+ config_param :retries, :integer, default: nil
49
+ desc "IP address (default:169.254.169.254)"
50
+ config_param :ip_address, :string, default: nil
51
+ desc "Port number (default:80)"
52
+ config_param :port, :integer, default: nil
53
+ desc "Number of seconds to wait for the connection to open"
54
+ config_param :http_open_timeout, :float, default: nil
55
+ desc "Number of seconds to wait for one block to be read"
56
+ config_param :http_read_timeout, :float, default: nil
57
+ # config_param :delay, :integer or :proc, :default => nil
58
+ # config_param :http_degub_output, :io, :default => nil
59
+ end
60
+ config_section :shared_credentials, multi: false do
61
+ desc "Path to the shared file. (default: $HOME/.aws/credentials)"
62
+ config_param :path, :string, default: nil
63
+ desc "Profile name. Default to 'default' or ENV['AWS_PROFILE']"
64
+ config_param :profile_name, :string, default: nil
65
+ end
64
66
  end
65
- end
66
67
 
67
- def self.included(mod)
68
- mod.include ClientParams
69
- end
70
-
71
- def configure(conf)
72
- super
73
- @region = client.config.region if @region.nil?
74
- end
68
+ def self.included(mod)
69
+ mod.include ClientParams
70
+ end
75
71
 
76
- def client
77
- @client ||= client_class.new(client_options)
78
- end
72
+ def configure(conf)
73
+ super
74
+ @region = client.config.region if @region.nil?
75
+ end
79
76
 
80
- private
77
+ def client
78
+ @client ||= client_class.new(client_options)
79
+ end
81
80
 
82
- def aws_sdk_v2?
83
- @aws_sdk_v2 ||= Gem.loaded_specs['aws-sdk-core'].version < Gem::Version.create('3')
84
- end
81
+ private
85
82
 
86
- def client_class
87
- case request_type
88
- when :streams, :streams_aggregated
89
- if aws_sdk_v2?
90
- require 'aws-sdk'
91
- else
83
+ def client_class
84
+ case request_type
85
+ when :streams, :streams_aggregated
92
86
  require 'aws-sdk-kinesis'
93
- end
94
- Aws::Kinesis::Client
95
- when :firehose
96
- if aws_sdk_v2?
97
- require 'aws-sdk'
98
- else
87
+ Aws::Kinesis::Client
88
+ when :firehose
99
89
  require 'aws-sdk-firehose'
90
+ Aws::Firehose::Client
100
91
  end
101
- Aws::Firehose::Client
102
92
  end
103
- end
104
93
 
105
- def client_options
106
- options = setup_credentials
107
- options.update(
108
- user_agent_suffix: "fluent-plugin-kinesis/#{request_type}/#{FluentPluginKinesis::VERSION}"
109
- )
110
- options.update(region: @region) unless @region.nil?
111
- options.update(http_proxy: @http_proxy) unless @http_proxy.nil?
112
- options.update(endpoint: @endpoint) unless @endpoint.nil?
113
- options.update(ssl_verify_peer: @ssl_verify_peer) unless @ssl_verify_peer.nil?
114
- if @debug
115
- options.update(logger: Logger.new(log.out))
116
- options.update(log_level: :debug)
94
+ def client_options
95
+ options = setup_credentials
96
+ options.update(
97
+ user_agent_suffix: "fluent-plugin-kinesis/#{request_type}/#{FluentPluginKinesis::VERSION}"
98
+ )
99
+ options.update(region: @region) unless @region.nil?
100
+ options.update(http_proxy: @http_proxy) unless @http_proxy.nil?
101
+ options.update(endpoint: @endpoint) unless @endpoint.nil?
102
+ options.update(ssl_verify_peer: @ssl_verify_peer) unless @ssl_verify_peer.nil?
103
+ if @debug
104
+ options.update(logger: Logger.new(log.out))
105
+ options.update(log_level: :debug)
106
+ end
107
+ options
117
108
  end
118
- options
119
- end
120
109
 
121
- def setup_credentials
122
- options = {}
123
- credentials_options = {}
124
- case
125
- when @aws_key_id && @aws_sec_key
126
- options[:access_key_id] = @aws_key_id
127
- options[:secret_access_key] = @aws_sec_key
128
- when @assume_role_credentials
129
- c = @assume_role_credentials
130
- credentials_options[:role_arn] = c.role_arn
131
- credentials_options[:role_session_name] = c.role_session_name
132
- credentials_options[:policy] = c.policy if c.policy
133
- credentials_options[:duration_seconds] = c.duration_seconds if c.duration_seconds
134
- credentials_options[:external_id] = c.external_id if c.external_id
135
- if c.sts_http_proxy and @region
136
- credentials_options[:client] = Aws::STS::Client.new(region: @region, http_proxy: c.sts_http_proxy)
137
- elsif @region
138
- credentials_options[:client] = Aws::STS::Client.new(region: @region)
139
- elsif c.sts_http_proxy
140
- credentials_options[:client] = Aws::STS::Client.new(http_proxy: c.sts_http_proxy)
141
- end
142
- options[:credentials] = Aws::AssumeRoleCredentials.new(credentials_options)
143
- when @instance_profile_credentials
144
- c = @instance_profile_credentials
145
- credentials_options[:retries] = c.retries if c.retries
146
- credentials_options[:ip_address] = c.ip_address if c.ip_address
147
- credentials_options[:port] = c.port if c.port
148
- credentials_options[:http_open_timeout] = c.http_open_timeout if c.http_open_timeout
149
- credentials_options[:http_read_timeout] = c.http_read_timeout if c.http_read_timeout
150
- if ENV["AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"]
151
- options[:credentials] = Aws::ECSCredentials.new(credentials_options)
110
+ def setup_credentials
111
+ options = {}
112
+ credentials_options = {}
113
+ case
114
+ when @aws_key_id && @aws_sec_key
115
+ options[:access_key_id] = @aws_key_id
116
+ options[:secret_access_key] = @aws_sec_key
117
+ when @assume_role_credentials
118
+ c = @assume_role_credentials
119
+ credentials_options[:role_arn] = c.role_arn
120
+ credentials_options[:role_session_name] = c.role_session_name
121
+ credentials_options[:policy] = c.policy if c.policy
122
+ credentials_options[:duration_seconds] = c.duration_seconds if c.duration_seconds
123
+ credentials_options[:external_id] = c.external_id if c.external_id
124
+ if c.sts_http_proxy and @region
125
+ credentials_options[:client] = Aws::STS::Client.new(region: @region, http_proxy: c.sts_http_proxy)
126
+ elsif @region
127
+ credentials_options[:client] = Aws::STS::Client.new(region: @region)
128
+ elsif c.sts_http_proxy
129
+ credentials_options[:client] = Aws::STS::Client.new(http_proxy: c.sts_http_proxy)
130
+ end
131
+ options[:credentials] = Aws::AssumeRoleCredentials.new(credentials_options)
132
+ when @instance_profile_credentials
133
+ c = @instance_profile_credentials
134
+ credentials_options[:retries] = c.retries if c.retries
135
+ credentials_options[:ip_address] = c.ip_address if c.ip_address
136
+ credentials_options[:port] = c.port if c.port
137
+ credentials_options[:http_open_timeout] = c.http_open_timeout if c.http_open_timeout
138
+ credentials_options[:http_read_timeout] = c.http_read_timeout if c.http_read_timeout
139
+ if ENV["AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"]
140
+ options[:credentials] = Aws::ECSCredentials.new(credentials_options)
141
+ else
142
+ options[:credentials] = Aws::InstanceProfileCredentials.new(credentials_options)
143
+ end
144
+ when @shared_credentials
145
+ c = @shared_credentials
146
+ credentials_options[:path] = c.path if c.path
147
+ credentials_options[:profile_name] = c.profile_name if c.profile_name
148
+ options[:credentials] = Aws::SharedCredentials.new(credentials_options)
152
149
  else
153
- options[:credentials] = Aws::InstanceProfileCredentials.new(credentials_options)
150
+ # Use default credentials
151
+ # See http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Client.html
154
152
  end
155
- when @shared_credentials
156
- c = @shared_credentials
157
- credentials_options[:path] = c.path if c.path
158
- credentials_options[:profile_name] = c.profile_name if c.profile_name
159
- options[:credentials] = Aws::SharedCredentials.new(credentials_options)
160
- else
161
- # Use default credentials
162
- # See http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Client.html
153
+ options
163
154
  end
164
- options
165
155
  end
166
156
  end
167
157
  end