fluent-plugin-google-cloud 0.2.0 → 0.2.1

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.
@@ -4,7 +4,7 @@ Gem::Specification.new do |gem|
4
4
  gem.summary = %q{Fluentd plugin to stream logs to the Google Cloud Platform's logging API}
5
5
  gem.homepage = 'https://github.com/GoogleCloudPlatform/fluent-plugin-google-cloud'
6
6
  gem.license = 'Apache 2.0'
7
- gem.version = '0.2.0'
7
+ gem.version = '0.2.1'
8
8
  gem.authors = ['Todd Derr', 'Alex Robinson']
9
9
  gem.email = ['salty@google.com']
10
10
 
@@ -192,24 +192,44 @@ module Fluent
192
192
  })
193
193
  client.execute!(request)
194
194
  # Allow most exceptions to propagate, which will cause fluentd to
195
- # retry (with backoff). However, most ClientErrors indicate a problem
196
- # with the request itself and should not be retried - the exception
197
- # is 'Invalid Credentials' which we can retry.
195
+ # retry (with backoff), but in some cases we catch the error and
196
+ # drop the request (we will emit a log message in those cases).
198
197
  rescue Google::APIClient::ClientError => error
199
- if (error.message == 'Invalid Credentials')
198
+ # Most ClientErrors indicate a problem with the request itself and
199
+ # should not be retried, unless it is an authentication issue, in
200
+ # which case we will retry the request via re-raising the exception.
201
+ if (is_retriable_client_error(error))
200
202
  raise error
201
203
  end
202
- # fall through to next rescue clause
204
+ log_write_failure(write_log_entries_request, error)
203
205
  rescue JSON::GeneratorError => error
206
+ # This happens if the request contains illegal characters;
207
+ # do not retry it because it will fail repeatedly.
204
208
  dropped = write_log_entries_request['entries'].length
205
- $log.warn "Dropping #{dropped} log message(s)",
206
- :error_class=>error.class.to_s, :error=>error.to_s
209
+ log_write_failure(write_log_entries_request, error)
207
210
  end
208
211
  end
209
212
  end
210
213
 
211
214
  private
212
215
 
216
+ RETRIABLE_CLIENT_ERRORS = Set.new [
217
+ 'Invalid Credentials',
218
+ 'Request had invalid credentials.',
219
+ 'The caller does not have permission',
220
+ 'Project has not enabled the API. Please use Google Developers Console to activate the API for your project.',
221
+ 'Unable to fetch access token (no scopes configured?)']
222
+
223
+ def is_retriable_client_error(error)
224
+ return RETRIABLE_CLIENT_ERRORS.include?(error.message)
225
+ end
226
+
227
+ def log_write_failure(request, error)
228
+ dropped = request['entries'].length
229
+ $log.warn "Dropping #{dropped} log message(s)",
230
+ :error_class=>error.class.to_s, :error=>error.to_s
231
+ end
232
+
213
233
  def fetch_metadata(metadata_path)
214
234
  open('http://metadata/computeMetadata/v1/' + metadata_path,
215
235
  {'Metadata-Flavor' => 'Google'}) do |f|
@@ -220,7 +240,7 @@ module Fluent
220
240
  def init_api_client
221
241
  @client = Google::APIClient.new(
222
242
  :application_name => 'Fluentd Google Cloud Logging plugin',
223
- :application_version => '0.2.0',
243
+ :application_version => '0.2.1',
224
244
  :retries => 1)
225
245
 
226
246
  if @auth_method == 'private_key'
@@ -238,7 +258,14 @@ module Fluent
238
258
 
239
259
  def api_client
240
260
  if !@client.authorization.expired?
241
- @client.authorization.fetch_access_token!
261
+ begin
262
+ @client.authorization.fetch_access_token!
263
+ rescue MultiJson::ParseError
264
+ # Workaround an issue in the API client; just re-raise a more
265
+ # descriptive error for the user (which will still cause a retry).
266
+ raise Google::APIClient::ClientError,
267
+ 'Unable to fetch access token (no scopes configured?)'
268
+ end
242
269
  end
243
270
  return @client
244
271
  end
@@ -223,23 +223,43 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
223
223
  assert_requested(:post, uri_for_log(COMPUTE_PARAMS), :times => 2)
224
224
  end
225
225
 
226
- def test_client_error_invalid_credentials
227
- # we expect this to retry once, then throw the error.
226
+ # helper for the ClientError retriable special cases below.
227
+ def client_error_helper(message)
228
228
  stub_request(:post, uri_for_log(COMPUTE_PARAMS)).to_return(
229
- :status => 401, :body => "Invalid Credentials")
229
+ :status => 401, :body => message)
230
230
  d = create_driver(PRIVATE_KEY_CONFIG)
231
231
  d.emit({'message' => log_entry(0)})
232
232
  exception_count = 0
233
233
  begin
234
234
  d.run
235
235
  rescue Google::APIClient::ClientError => error
236
- assert_equal 'Invalid Credentials', error.message
236
+ assert_equal message, error.message
237
237
  exception_count += 1
238
238
  end
239
239
  assert_requested(:post, uri_for_log(COMPUTE_PARAMS), :times => 2)
240
240
  assert_equal 1, exception_count
241
241
  end
242
242
 
243
+ def test_client_error_invalid_credentials
244
+ client_error_helper("Invalid Credentials")
245
+ end
246
+
247
+ def test_client_error_caller_does_not_have_permission
248
+ client_error_helper("The caller does not have permission")
249
+ end
250
+
251
+ def test_client_error_request_had_invalid_credentials
252
+ client_error_helper("Request had invalid credentials.")
253
+ end
254
+
255
+ def test_client_error_project_has_not_enabled_the_api
256
+ client_error_helper("Project has not enabled the API. Please use Google Developers Console to activate the API for your project.")
257
+ end
258
+
259
+ def test_client_error_unable_to_fetch_accesss_token
260
+ client_error_helper("Unable to fetch access token (no scopes configured?)")
261
+ end
262
+
243
263
  def test_server_error
244
264
  # The API client should retry this once, then throw an exception which
245
265
  # gets propagated through the plugin.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-google-cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-02-23 00:00:00.000000000 Z
13
+ date: 2015-03-25 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: fluentd