google-cloud-error_reporting 0.30.5 → 0.31.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df53fba39b31fef5256a2fb3e35160f868eaaea7e6332b71ea779c9edb55c11c
4
- data.tar.gz: 28bea2c9d8caa7eb94f69ad8ea64fb243c9920449cff4396bc5220726d834f07
3
+ metadata.gz: 2ca4dece3ad67bcf61fa206c1561305f21d2dea95e2505099818cdf5f99368e3
4
+ data.tar.gz: c91e752ce4555b646bcaa313177373b8310a6d944997560f9dc98ea7f87eb6a9
5
5
  SHA512:
6
- metadata.gz: ec08c92db16cdaf1a8fe8d6d0d4f00255d2c78c550f07ccb1dc024d9318704b5c1e57a6ded1c37228fa094fd87fc41869c98f4b9c3d7a1a773c611b74e9237d8
7
- data.tar.gz: 4099c791a52bab837c673cc8a88f02542a1f64fe9926e143af97758e72df970066898db77e8fcbb0d7a07a58fca0c5a115d132fc162670ed1b0ec8f3cda5997d
6
+ metadata.gz: 52bb1f172ce54cd572f7ff60d60c675b440f7196358d54ff9ce3f31ceb87a80c07245d1dd9f7fa4f8c9da38aa740cf8d40215a4d4fb229f2ae42ae78f8482fbe
7
+ data.tar.gz: b3d6ebf49e7e596045b86104d4cd0eb4702a493cd93581487c7456f1da0209523d0d80fa6fc0faf06e92f591d027a8b90e096b6ae3b1bb484a7f36551f9c53b0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Release History
2
2
 
3
+ ### 0.31.0 / 2019-02-01
4
+
5
+ * Add ErrorReporting on_error configuration.
6
+ * Update asynchronous error reporting implementation:
7
+ * Add dependency on concurrent-ruby.
8
+ * Fix for submitting error objects without backtrace.
9
+ * Make use of Credentials#project_id
10
+ * Use Credentials#project_id
11
+ If a project_id is not provided, use the value on the Credentials object.
12
+ This value was added in googleauth 0.7.0.
13
+ * Loosen googleauth dependency
14
+ Allow for new releases up to 0.10.
15
+ The googleauth devs have committed to maintanining the current API
16
+ and will not make backwards compatible changes before 0.10.
17
+
3
18
  ### 0.30.5 / 2018-09-20
4
19
 
5
20
  * Update documentation.
@@ -163,4 +163,5 @@ Google::Cloud.configure.add_config! :error_reporting do |config|
163
163
  config.add_field! :service_version, default_version,
164
164
  match: String, allow_nil: true
165
165
  config.add_field! :ignore_classes, nil, match: Array
166
+ config.add_field! :on_error, nil, match: Proc
166
167
  end
@@ -76,20 +76,24 @@ module Google
76
76
  #
77
77
  def self.new project_id: nil, credentials: nil, scope: nil, timeout: nil,
78
78
  client_config: nil, project: nil, keyfile: nil
79
- project_id ||= (project || ErrorReporting::Project.default_project_id)
80
- project_id = project_id.to_s
81
- raise ArgumentError, "project_id is missing" if project_id.empty?
82
-
83
- scope ||= configure.scope
84
- timeout ||= configure.timeout
79
+ project_id ||= project
80
+ project_id ||= ErrorReporting::Project.default_project_id
81
+ scope ||= configure.scope
82
+ timeout ||= configure.timeout
85
83
  client_config ||= configure.client_config
84
+ credentials ||= (keyfile || default_credentials(scope: scope))
86
85
 
87
- credentials ||= (keyfile || default_credentials(scope: scope))
88
86
  unless credentials.is_a? Google::Auth::Credentials
89
87
  credentials = ErrorReporting::Credentials.new credentials,
90
88
  scope: scope
91
89
  end
92
90
 
91
+ if credentials.respond_to? :project_id
92
+ project_id ||= credentials.project_id
93
+ end
94
+ project_id = project_id.to_s
95
+ raise ArgumentError, "project_id is missing" if project_id.empty?
96
+
93
97
  ErrorReporting::Project.new(
94
98
  ErrorReporting::Service.new(
95
99
  project_id, credentials, timeout: timeout,
@@ -123,6 +127,13 @@ module Google
123
127
  # * `service_version` - (String) Version identifier for the application.
124
128
  # * `ignore_classes` - (Array<Exception>) Array of exception types that
125
129
  # should not be reported.
130
+ # * `on_error` - (Proc) A Proc to be run when an error is encountered
131
+ # on a background thread, such as {ErrorReporting.report} or
132
+ # {Middleware}. The Proc must take the error object as the single
133
+ # argument. If ErrorReporting is being used to report errors using
134
+ # `Google::Cloud::cofigure.on_error`, then this `on_error` should be
135
+ # configured to report errors raised when reporting through
136
+ # ErrorReporting.
126
137
  #
127
138
  # See the [Configuration
128
139
  # Guide](https://googleapis.github.io/google-cloud-ruby/docs/stackdriver/latest/file.INSTRUMENTATION_CONFIGURATION)
@@ -206,6 +217,9 @@ module Google
206
217
  service_name ||= Project.default_service_name
207
218
  service_version ||= Project.default_service_version
208
219
 
220
+ # Ensure the reported exception has a backtrace
221
+ exception.set_backtrace caller if exception.backtrace.nil?
222
+
209
223
  error_event = ErrorEvent.from_exception(exception).tap do |event|
210
224
  event.service_name = service_name
211
225
  event.service_version = service_version
@@ -13,12 +13,51 @@
13
13
  # limitations under the License.
14
14
 
15
15
 
16
- require "stackdriver/core/async_actor"
17
-
16
+ require "concurrent"
17
+ require "google/cloud/errors"
18
18
 
19
19
  module Google
20
20
  module Cloud
21
21
  module ErrorReporting
22
+ ##
23
+ # # AsyncErrorReporterError
24
+ #
25
+ # @private Used to indicate a problem reporting errors asynchronously.
26
+ # This can occur when there are not enough resources allocated for the
27
+ # amount of usage.
28
+ #
29
+ class AsyncErrorReporterError < Google::Cloud::Error
30
+ # @!attribute [r] error_event
31
+ # @return [Array<Google::Cloud::ErrorReporting::ErrorEvent>] The
32
+ # individual error event that was not reported to Stackdriver Error
33
+ # Reporting service.
34
+ attr_reader :error_event
35
+
36
+ def initialize message, error_event = nil
37
+ super(message)
38
+ @error_event = error_event
39
+ end
40
+ end
41
+
42
+ ##
43
+ # # ErrorReporterError
44
+ #
45
+ # @private Used to indicate a problem reporting errors. This can occur
46
+ # when the calling the API returns an error.
47
+ #
48
+ class ErrorReporterError < Google::Cloud::Error
49
+ # @!attribute [r] error_event
50
+ # @return [Array<Google::Cloud::ErrorReporting::ErrorEvent>] The
51
+ # individual error event that was not reported to Stackdriver Error
52
+ # Reporting service.
53
+ attr_reader :error_event
54
+
55
+ def initialize message, error_event = nil
56
+ super(message)
57
+ @error_event = error_event
58
+ end
59
+ end
60
+
22
61
  ##
23
62
  # # AsyncErrorReporter
24
63
  #
@@ -27,98 +66,144 @@ module Google
27
66
  # error events to Stackdriver Error Reporting service when used in
28
67
  # Ruby applications.
29
68
  class AsyncErrorReporter
30
- include Stackdriver::Core::AsyncActor
31
-
32
69
  ##
33
- # @private Default maximum backlog size for the job queue
34
- DEFAULT_MAX_QUEUE_SIZE = 1000
70
+ # @private Implementation accessors
71
+ attr_reader :error_reporting, :max_queue, :threads, :thread_pool
35
72
 
36
73
  ##
37
- # The {Google::Cloud::ErrorReporting::Project} object to submit events
38
- # with.
39
- attr_accessor :error_reporting
74
+ # @private Creates a new AsyncErrorReporter instance.
75
+ def initialize error_reporting, max_queue: 1000, threads: 10
76
+ @error_reporting = error_reporting
40
77
 
41
- ##
42
- # The max number of items the queue holds
43
- attr_accessor :max_queue_size
78
+ @max_queue = max_queue
79
+ @threads = threads
44
80
 
45
- ##
46
- # @private Construct a new instance of AsyncErrorReporter
47
- def initialize error_reporting, max_queue_size = DEFAULT_MAX_QUEUE_SIZE
48
- super()
49
- @error_reporting = error_reporting
50
- @max_queue_size = max_queue_size
51
- @queue = []
52
- @queue_resource = new_cond
81
+ @thread_pool = Concurrent::CachedThreadPool.new max_threads: @threads,
82
+ max_queue: @max_queue
83
+
84
+ @error_callbacks = []
85
+
86
+ # Make sure all queued calls are completed when process exits.
87
+ at_exit { stop! }
53
88
  end
54
89
 
55
90
  ##
56
- # Add the error event to the queue. Signal the child thread an item
57
- # has been added.
91
+ # Add the error event to the queue. This will raise if there are no
92
+ # resources available to make the API call.
58
93
  def report error_event
59
- async_start
60
-
61
- synchronize do
62
- @queue.push error_event
63
- @queue_resource.broadcast
94
+ Concurrent::Promises.future_on(@thread_pool, error_event) do |error|
95
+ report_sync error
96
+ end
97
+ rescue Concurrent::RejectedExecutionError => e
98
+ raise AsyncErrorReporterError,
99
+ "Error reporting error_event asynchronously: #{e.message}",
100
+ error_event
101
+ end
64
102
 
65
- retries = 0
66
- while @max_queue_size && @queue.size > @max_queue_size
67
- retries += 1
68
- @queue_resource.wait 1
103
+ ##
104
+ # Begins the process of stopping the reporter. ErrorEvents already
105
+ # in the queue will be published, but no new ErrorEvent can be added.
106
+ # Use {#wait!} to block until the reporter is fully stopped and all
107
+ # pending error_events have been pushed to the API.
108
+ #
109
+ # @return [AsyncErrorReporter] returns self so calls can be chained.
110
+ def stop
111
+ @thread_pool.shutdown if @thread_pool
112
+
113
+ self
114
+ end
69
115
 
70
- # Drop early queue entries when have waited long enough.
71
- @queue.pop while @queue.size > @max_queue_size && retries > 3
72
- end
73
- end
116
+ ##
117
+ # Stop this asynchronous reporter and block until it has been stopped.
118
+ #
119
+ # @param [Number] timeout Timeout in seconds.
120
+ #
121
+ def stop! timeout = nil
122
+ stop
123
+ wait! timeout
74
124
  end
75
125
 
76
126
  ##
77
- # @private Callback fucntion for AsyncActor module to run the async
78
- # job in a loop
79
- def run_backgrounder
80
- error_event = wait_next_item
81
- return if error_event.nil?
82
- begin
83
- error_reporting.report error_event
84
- rescue StandardError => e
85
- warn error_event.message if error_event.message
86
- warn ["#{e.class}: #{e.message}", e.backtrace].join("\n\t")
87
- @last_exception = e
127
+ # Blocks until the reporter is fully stopped, all pending error_events
128
+ # have been published, and all callbacks have completed. Does not stop
129
+ # the reporter. To stop the reporter, first call {#stop} and then call
130
+ # {#wait!} to block until the reporter is stopped.
131
+ #
132
+ # @return [AsyncErrorReporter] returns self so calls can be chained.
133
+ def wait! timeout = nil
134
+ if @thread_pool
135
+ @thread_pool.shutdown
136
+ @thread_pool.wait_for_termination timeout
88
137
  end
138
+
139
+ self
89
140
  end
90
141
 
91
142
  ##
92
- # @private Callback function when the async actor thread state changes
93
- def on_async_state_change
94
- synchronize do
95
- @queue_resource.broadcast
96
- end
143
+ # Whether the reporter has been started.
144
+ #
145
+ # @return [boolean] `true` when started, `false` otherwise.
146
+ #
147
+ def started?
148
+ @thread_pool.running? if @thread_pool
97
149
  end
98
150
 
99
- private
151
+ ##
152
+ # Whether the reporter has been stopped.
153
+ #
154
+ # @return [boolean] `true` when stopped, `false` otherwise.
155
+ #
156
+ def stopped?
157
+ !started?
158
+ end
100
159
 
101
160
  ##
102
- # @private The the next item from the reporter queue. If there are
103
- # no more item, it blocks the reporter thread until an item is
104
- # enqueued
105
- def wait_next_item
106
- synchronize do
107
- @queue_resource.wait_while do
108
- async_suspended? || (async_running? && @queue.empty?)
161
+ # Register to be notified of errors when raised.
162
+ #
163
+ # If an unhandled error has occurred the reporter will attempt to
164
+ # recover from the error and resume reporting error_events.
165
+ #
166
+ # Multiple error handlers can be added.
167
+ #
168
+ # @yield [callback] The block to be called when an error is raised.
169
+ # @yieldparam [Exception] error The error raised.
170
+ #
171
+ def on_error &block
172
+ @error_callbacks << block
173
+ end
174
+
175
+ protected
176
+
177
+ # Calls all error callbacks.
178
+ def error! error
179
+ error_callbacks = @error_callbacks
180
+ error_callbacks = default_error_callbacks if error_callbacks.empty?
181
+ error_callbacks.each { |error_callback| error_callback.call error }
182
+ end
183
+
184
+ def default_error_callbacks
185
+ # This is memoized to reduce calls to the configuration.
186
+ @default_error_callbacks ||= begin
187
+ error_cb = Google::Cloud::ErrorReporting.configuration.on_error
188
+ error_cb ||= Google::Cloud.configure.on_error
189
+ if error_cb
190
+ [error_cb]
191
+ else
192
+ []
109
193
  end
110
- @queue.pop
111
194
  end
112
195
  end
113
196
 
114
- ##
115
- # @private Override the #backgrounder_stoppable? method from AsyncActor
116
- # module. The actor can be gracefully stopped when queue is
117
- # empty.
118
- def backgrounder_stoppable?
119
- synchronize do
120
- @queue.empty?
121
- end
197
+ def report_sync error_event
198
+ error_reporting.report error_event
199
+ rescue StandardError => e
200
+ sync_error = ErrorReporterError.new(
201
+ "Error reporting error_event: #{e.message}",
202
+ error_event
203
+ )
204
+ # Manually set backtrace so we don't have to raise
205
+ sync_error.set_backtrace caller
206
+ error! sync_error
122
207
  end
123
208
  end
124
209
  end
@@ -27,7 +27,7 @@ module Google
27
27
  # and report them to the Stackdriver Error Reporting service.
28
28
  #
29
29
  # The Middleware is only added when certain conditions are met. See
30
- # {Railtie.use_error_reporting?} for detail.
30
+ # `Google::Cloud.configure.use_error_reporting` for detail.
31
31
  #
32
32
  # When loaded, the {Google::Cloud::ErrorReporting::Middleware} will be
33
33
  # inserted after ActionDispatch::DebugExceptions or
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -267,6 +267,25 @@ module Google
267
267
  # Response message for deleting error events.
268
268
  class DeleteEventsResponse; end
269
269
 
270
+ # A sorting order of error groups.
271
+ module ErrorGroupOrder
272
+ # No group order specified.
273
+ GROUP_ORDER_UNSPECIFIED = 0
274
+
275
+ # Total count of errors in the given time window in descending order.
276
+ COUNT_DESC = 1
277
+
278
+ # Timestamp when the group was last seen in the given time window
279
+ # in descending order.
280
+ LAST_SEEN_DESC = 2
281
+
282
+ # Timestamp when the group was created in descending order.
283
+ CREATED_DESC = 3
284
+
285
+ # Number of affected users in the given time window in descending order.
286
+ AFFECTED_USERS_DESC = 4
287
+ end
288
+
270
289
  # Specifies how the time periods of error group counts are aligned.
271
290
  module TimedCountAlignment
272
291
  # No alignment specified.
@@ -288,25 +307,6 @@ module Google
288
307
  # first time period.
289
308
  ALIGNMENT_EQUAL_AT_END = 2
290
309
  end
291
-
292
- # A sorting order of error groups.
293
- module ErrorGroupOrder
294
- # No group order specified.
295
- GROUP_ORDER_UNSPECIFIED = 0
296
-
297
- # Total count of errors in the given time window in descending order.
298
- COUNT_DESC = 1
299
-
300
- # Timestamp when the group was last seen in the given time window
301
- # in descending order.
302
- LAST_SEEN_DESC = 2
303
-
304
- # Timestamp when the group was created in descending order.
305
- CREATED_DESC = 3
306
-
307
- # Number of affected users in the given time window in descending order.
308
- AFFECTED_USERS_DESC = 4
309
- end
310
310
  end
311
311
  end
312
312
  end
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Google LLC
1
+ # Copyright 2019 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
16
16
  module Google
17
17
  module Cloud
18
18
  module ErrorReporting
19
- VERSION = "0.30.5".freeze
19
+ VERSION = "0.31.0".freeze
20
20
  end
21
21
  end
22
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-cloud-error_reporting
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.30.5
4
+ version: 0.31.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Google Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-21 00:00:00.000000000 Z
11
+ date: 2019-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-cloud-core
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: concurrent-ruby
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: minitest
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -128,14 +142,14 @@ dependencies:
128
142
  requirements:
129
143
  - - "~>"
130
144
  - !ruby/object:Gem::Version
131
- version: 0.50.0
145
+ version: 0.61.0
132
146
  type: :development
133
147
  prerelease: false
134
148
  version_requirements: !ruby/object:Gem::Requirement
135
149
  requirements:
136
150
  - - "~>"
137
151
  - !ruby/object:Gem::Version
138
- version: 0.50.0
152
+ version: 0.61.0
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: railties
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -275,7 +289,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
275
289
  version: '0'
276
290
  requirements: []
277
291
  rubyforge_project:
278
- rubygems_version: 2.7.7
292
+ rubygems_version: 2.7.6
279
293
  signing_key:
280
294
  specification_version: 4
281
295
  summary: API Client library for Stackdriver Error Reporting