fluent-plugin-cloudwatch-logs 0.2.3 → 0.2.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5082b725cf548ffea0fb7e779c6c24a4d7bb7909
4
- data.tar.gz: 6a8dbc8986550ec45e9fb3518316f19d7267ac8e
3
+ metadata.gz: 177bb1a6b7af9c6565f1cd5104f422c1fb48add7
4
+ data.tar.gz: 576f39a7a7cec61aa655aefbc60549f1787f9f77
5
5
  SHA512:
6
- metadata.gz: f8321eeaa7a481dae684a5908446782a5ba570b1bcc9bbeec86a63d4a365340923a4478536a471a4480aa32b6017a537c5023ee87dd5d0144d62cab252f0c6fd
7
- data.tar.gz: c57ab7ca6be0756ad4377b3b7cf12cc69b6f4e141b82c5c5cc664fe493fe22f705758c5e3c4be2d00fcec55d98c892c8c325c3f17b453acd899b7ccf266b01cb
6
+ metadata.gz: 998c9861c7db2ed024ef27c2011a70a52a8648797f2b5f5891381f6c5620b2d4074279b0e682b2123f0f6f9a90d197f388943fec9416271c6f045261d39b326e
7
+ data.tar.gz: 900de6d31aeb5e62f6695c9ae016e16470ce0c550cb2e9b0851d03a073095862808dab9093a22586709ff05310445c47c7134c89b8a4485c0032ef69e8998dbe
data/README.md CHANGED
@@ -79,6 +79,9 @@ Fetch sample log from CloudWatch Logs:
79
79
  #log_stream_name_key stream_name_key
80
80
  #remove_log_group_name_key true
81
81
  #remove_log_stream_name_key true
82
+ #put_log_events_retry_wait 1s
83
+ #put_log_events_retry_limit 17
84
+ #put_log_events_disable_retry_limit false
82
85
  </match>
83
86
  ```
84
87
 
@@ -96,6 +99,9 @@ Fetch sample log from CloudWatch Logs:
96
99
  * `log_stream_name_key`: use specified field of records as log stream name
97
100
  * `remove_log_group_name_key`: remove field specified by `log_group_name_key`
98
101
  * `remove_log_stream_name_key`: remove field specified by `log_stream_name_key`
102
+ * `put_log_events_retry_wait`: time before retrying PutLogEvents (retry interval increases exponentially like `put_log_events_retry_wait * (2 ^ retry_count)`)
103
+ * `put_log_events_retry_limit`: maximum count of retry (if exceeding this, the events will be discarded)
104
+ * `put_log_events_disable_retry_limit`: if true, `put_log_events_retry_limit` will be ignored
99
105
 
100
106
  ### in_cloudwatch_logs
101
107
 
@@ -24,4 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "bundler", "~> 1.6"
25
25
  spec.add_development_dependency "rake"
26
26
  spec.add_development_dependency "test-unit"
27
+ spec.add_development_dependency "mocha"
27
28
  end
@@ -2,7 +2,7 @@ module Fluent
2
2
  module Plugin
3
3
  module Cloudwatch
4
4
  module Logs
5
- VERSION = "0.2.3"
5
+ VERSION = "0.2.4"
6
6
  end
7
7
  end
8
8
  end
@@ -23,6 +23,9 @@ module Fluent
23
23
  config_param :remove_log_group_name_key, :bool, :default => false
24
24
  config_param :remove_log_stream_name_key, :bool, :default => false
25
25
  config_param :http_proxy, :string, default: nil
26
+ config_param :put_log_events_retry_wait, :time, default: 1.0
27
+ config_param :put_log_events_retry_limit, :integer, default: 17
28
+ config_param :put_log_events_disable_retry_limit, :bool, default: false
26
29
 
27
30
  MAX_EVENTS_SIZE = 1_048_576
28
31
  EVENT_HEADER_SIZE = 26
@@ -60,7 +63,7 @@ module Fluent
60
63
  options[:credentials] = Aws::Credentials.new(@aws_key_id, @aws_sec_key) if @aws_key_id && @aws_sec_key
61
64
  options[:region] = @region if @region
62
65
  options[:http_proxy] = @http_proxy if @http_proxy
63
- @logs = Aws::CloudWatchLogs::Client.new(options)
66
+ @logs ||= Aws::CloudWatchLogs::Client.new(options)
64
67
  @sequence_tokens = {}
65
68
  end
66
69
 
@@ -191,14 +194,42 @@ module Fluent
191
194
  token = next_sequence_token(group_name, stream_name)
192
195
  args[:sequence_token] = token if token
193
196
 
194
- log.debug "Calling PutLogEvents API", {
195
- "group" => group_name,
196
- "stream" => stream_name,
197
- "events_count" => events.size,
198
- "events_bytesize" => events_bytesize,
199
- }
197
+ response = nil
198
+ retry_count = 0
199
+ until response
200
+ log.debug "Calling PutLogEvents API", {
201
+ "group" => group_name,
202
+ "stream" => stream_name,
203
+ "events_count" => events.size,
204
+ "events_bytesize" => events_bytesize,
205
+ }
206
+ begin
207
+ response = @logs.put_log_events(args)
208
+ rescue Aws::CloudWatchLogs::Errors::ThrottlingException => err
209
+ if !@put_log_events_disable_retry_limit && @put_log_events_retry_limit < retry_count
210
+ log.error "failed to PutLogEvents and discard logs because retry count exceeded put_log_events_retry_limit", {
211
+ "error_class" => err.class.to_s,
212
+ "error" => err.message,
213
+ }
214
+ return
215
+ else
216
+ sleep_sec = @put_log_events_retry_wait * (2 ** retry_count)
217
+ sleep_sec += sleep_sec * (0.25 * (rand - 0.5))
218
+ log.warn "failed to PutLogEvents", {
219
+ "next_retry" => Time.now + sleep_sec,
220
+ "error_class" => err.class.to_s,
221
+ "error" => err.message,
222
+ }
223
+ sleep(sleep_sec)
224
+ retry_count += 1
225
+ end
226
+ end
227
+ end
228
+
229
+ if 0 < retry_count
230
+ log.warn "retry succeeded"
231
+ end
200
232
 
201
- response = @logs.put_log_events(args)
202
233
  store_next_sequence_token(group_name, stream_name, response.next_sequence_token)
203
234
  end
204
235
 
@@ -291,6 +291,49 @@ class CloudwatchLogsOutputTest < Test::Unit::TestCase
291
291
  assert_equal({'cloudwatch' => 'logs1', 'message' => 'message1'}, JSON.parse(events[0].message))
292
292
  end
293
293
 
294
+ def test_retrying_on_throttling_exception
295
+ resp = mock()
296
+ resp.expects(:next_sequence_token)
297
+ client = Aws::CloudWatchLogs::Client.new
298
+ client.stubs(:put_log_events).
299
+ raises(Aws::CloudWatchLogs::Errors::ThrottlingException.new(nil, "error")).then.returns(resp)
300
+
301
+ time = Time.now
302
+ d = create_driver
303
+ d.instance.instance_variable_set(:@logs, client)
304
+ d.emit({'message' => 'message1'}, time.to_i)
305
+ d.run
306
+
307
+ assert_match(/Calling PutLogEvents/, d.instance.log.logs[0])
308
+ assert_match(/failed to PutLogEvents/, d.instance.log.logs[1])
309
+ assert_match(/Calling PutLogEvents/, d.instance.log.logs[2])
310
+ assert_match(/retry succeeded/, d.instance.log.logs[3])
311
+ end
312
+
313
+ def test_retrying_on_throttling_exception_and_throw_away
314
+ client = Aws::CloudWatchLogs::Client.new
315
+ client.stubs(:put_log_events).
316
+ raises(Aws::CloudWatchLogs::Errors::ThrottlingException.new(nil, "error"))
317
+
318
+ time = Time.now
319
+ d = create_driver(<<-EOC)
320
+ #{default_config}
321
+ log_group_name #{log_group_name}
322
+ log_stream_name #{log_stream_name}
323
+ put_log_events_retry_limit 1
324
+ EOC
325
+ d.instance.instance_variable_set(:@logs, client)
326
+ d.emit({'message' => 'message1'}, time.to_i)
327
+ d.run
328
+
329
+ assert_match(/Calling PutLogEvents/, d.instance.log.logs[0])
330
+ assert_match(/failed to PutLogEvents/, d.instance.log.logs[1])
331
+ assert_match(/Calling PutLogEvents/, d.instance.log.logs[2])
332
+ assert_match(/failed to PutLogEvents/, d.instance.log.logs[3])
333
+ assert_match(/Calling PutLogEvents/, d.instance.log.logs[4])
334
+ assert_match(/failed to PutLogEvents and throwing away/, d.instance.log.logs[5])
335
+ end
336
+
294
337
  private
295
338
  def default_config
296
339
  <<-EOC
data/test/test_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'test/unit'
2
+ require 'mocha/test_unit'
2
3
  require 'fluent/test'
3
4
 
4
5
  require 'aws-sdk-core'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-cloudwatch-logs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryota Arai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-18 00:00:00.000000000 Z
11
+ date: 2016-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: mocha
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  description:
98
112
  email:
99
113
  - ryota.arai@gmail.com