google-cloud-error_reporting 0.24.0 → 0.25.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 +4 -4
- data/README.md +87 -60
- data/lib/google-cloud-error_reporting.rb +93 -5
- data/lib/google/cloud/error_reporting.rb +238 -0
- data/lib/google/cloud/error_reporting/credentials.rb +41 -0
- data/lib/google/cloud/error_reporting/error_event.rb +313 -0
- data/lib/google/cloud/error_reporting/middleware.rb +84 -183
- data/lib/google/cloud/error_reporting/project.rb +224 -0
- data/lib/google/cloud/error_reporting/rails.rb +97 -127
- data/lib/google/cloud/error_reporting/service.rb +118 -0
- data/lib/google/cloud/error_reporting/version.rb +22 -0
- metadata +61 -13
@@ -0,0 +1,41 @@
|
|
1
|
+
# Copyright 2017 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "google/cloud/credentials"
|
17
|
+
|
18
|
+
module Google
|
19
|
+
module Cloud
|
20
|
+
module ErrorReporting
|
21
|
+
##
|
22
|
+
# @private Represents the OAuth 2.0 signing logic for ErrorReporting.
|
23
|
+
class Credentials < Google::Cloud::Credentials
|
24
|
+
SCOPE = ["https://www.googleapis.com/auth/cloud-platform"]
|
25
|
+
PATH_ENV_VARS = %w(ERROR_REPORTING_KEYFILE GOOGLE_CLOUD_KEYFILE)
|
26
|
+
JSON_ENV_VARS =
|
27
|
+
%w(ERROR_REPORTING_KEYFILE_JSON GOOGLE_CLOUD_KEYFILE_JSON)
|
28
|
+
|
29
|
+
##
|
30
|
+
# @private Create credentials with given scope and/or keyfile.
|
31
|
+
def self.credentials_with_scope keyfile, scope = nil
|
32
|
+
if keyfile.nil?
|
33
|
+
default(scope: scope)
|
34
|
+
else
|
35
|
+
new(keyfile, scope: scope)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,313 @@
|
|
1
|
+
# Copyright 2017 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
module Google
|
17
|
+
module Cloud
|
18
|
+
module ErrorReporting
|
19
|
+
##
|
20
|
+
# # ErrorEvent
|
21
|
+
#
|
22
|
+
# An individual error event to report to Stackdriver Error Reporting
|
23
|
+
# service.
|
24
|
+
#
|
25
|
+
# Google::Cloud::ErrorReporting::ErrorEvent is able to be transformed
|
26
|
+
# into
|
27
|
+
# {Google::Devtools::Clouderrorreporting::V1beta1::ReportedErrorEvent}
|
28
|
+
# gRPC structure. Once an error event is reported, the GCP
|
29
|
+
# Stackdriver ErrorReporting service is able to parse the message and
|
30
|
+
# backtrace, then group the error events by content.
|
31
|
+
#
|
32
|
+
# @see https://cloud.google.com/error-reporting/reference/rest/v1beta1/projects.events
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# require "google/cloud/error_reporting"
|
36
|
+
#
|
37
|
+
# error_reporting = Google::Cloud::ErrorReporting.new
|
38
|
+
#
|
39
|
+
# error_event = error_reporting.error_event "Error with Backtrace",
|
40
|
+
# timestamp: Time.now,
|
41
|
+
# service_name: "my_app_name",
|
42
|
+
# service_version: "v8"
|
43
|
+
# error_reporting.report error_event
|
44
|
+
#
|
45
|
+
class ErrorEvent
|
46
|
+
##
|
47
|
+
# Time when the event occurred. If not provided, the time when the event
|
48
|
+
# was received by the Error Reporting system will be used.
|
49
|
+
attr_accessor :event_time
|
50
|
+
|
51
|
+
##
|
52
|
+
# A message describing the error. The message can contain an exception
|
53
|
+
# stack in one of the supported programming languages and formats. In
|
54
|
+
# that case, the message is parsed and detailed exception information is
|
55
|
+
# returned when retrieving the error event again.
|
56
|
+
attr_accessor :message
|
57
|
+
|
58
|
+
##
|
59
|
+
# An identifier of the service, such as the name of the executable, job,
|
60
|
+
# or Google App Engine service name. This field is expected to have a
|
61
|
+
# low number of values that are relatively stable over time, as opposed
|
62
|
+
# to version, which can be changed whenever new code is deployed.
|
63
|
+
attr_accessor :service_name
|
64
|
+
|
65
|
+
##
|
66
|
+
# Represents the source code version that the developer provided, which
|
67
|
+
# could represent a version label or a Git SHA-1 hash, for example.
|
68
|
+
attr_accessor :service_version
|
69
|
+
|
70
|
+
##
|
71
|
+
# The type of HTTP request, such as GET, POST, etc.
|
72
|
+
attr_accessor :http_method
|
73
|
+
|
74
|
+
##
|
75
|
+
# The URL of the request.
|
76
|
+
attr_accessor :http_url
|
77
|
+
|
78
|
+
##
|
79
|
+
# The user agent information that is provided with the request.
|
80
|
+
attr_accessor :http_user_agent
|
81
|
+
|
82
|
+
##
|
83
|
+
# The referrer information that is provided with the request.
|
84
|
+
attr_accessor :http_referrer
|
85
|
+
|
86
|
+
##
|
87
|
+
# The HTTP response status code for the request.
|
88
|
+
attr_accessor :http_status
|
89
|
+
|
90
|
+
##
|
91
|
+
# The IP address from which the request originated. This can be IPv4,
|
92
|
+
# IPv6, or a token which is derived from the IP address, depending on
|
93
|
+
# the data that has been provided in the error report.
|
94
|
+
attr_accessor :http_remote_ip
|
95
|
+
|
96
|
+
##
|
97
|
+
# The user who caused or was affected by the crash. This can be a user
|
98
|
+
# ID, an email address, or an arbitrary token that uniquely identifies
|
99
|
+
# the user. When sending an error report, leave this field empty if the
|
100
|
+
# user was not logged in. In this case the Error Reporting system will
|
101
|
+
# use other data, such as remote IP address, to distinguish affected
|
102
|
+
# users. See affectedUsersCount in ErrorGroupStats.
|
103
|
+
attr_accessor :user
|
104
|
+
|
105
|
+
##
|
106
|
+
# The source code filename, which can include a truncated relative path,
|
107
|
+
# or a full path from a production machine.
|
108
|
+
attr_accessor :file_path
|
109
|
+
|
110
|
+
##
|
111
|
+
# 1-based. 0 indicates that the line number is unknown.
|
112
|
+
attr_accessor :line_number
|
113
|
+
|
114
|
+
##
|
115
|
+
# Human-readable name of a function or method. The value can include
|
116
|
+
# optional context like the class or package name. For example,
|
117
|
+
# my.package.MyClass.method in case of Java.
|
118
|
+
attr_accessor :function_name
|
119
|
+
|
120
|
+
##
|
121
|
+
# Build a new ErrorEvent from a
|
122
|
+
# Google::Devtools::Clouderrorreporting::V1beta1::ReportedErrorEvent
|
123
|
+
# object.
|
124
|
+
#
|
125
|
+
# @param [
|
126
|
+
# Google::Devtools::Clouderrorreporting::V1beta1::ReportedErrorEvent]
|
127
|
+
# grpc A
|
128
|
+
# Google::Devtools::Clouderrorreporting::V1beta1::ReportedErrorEvent
|
129
|
+
# object
|
130
|
+
#
|
131
|
+
# @return [ErrorEvent] A new ErrorEvent instance derived from given grpc
|
132
|
+
# object
|
133
|
+
#
|
134
|
+
def self.from_grpc grpc
|
135
|
+
return new if grpc.nil?
|
136
|
+
new.tap do |event|
|
137
|
+
event.event_time = extract_timestamp grpc.event_time
|
138
|
+
event.message = grpc.message
|
139
|
+
|
140
|
+
extract_service_context event, grpc.service_context
|
141
|
+
extract_error_context event, grpc.context
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# @private Get a Time object from a Google::Protobuf::Timestamp object.
|
147
|
+
#
|
148
|
+
# @param [Google::Protobuf::Timestamp] timestamp_grpc A protobuf
|
149
|
+
# Timestamp object
|
150
|
+
#
|
151
|
+
# @return [Time] The time object derived from input grpc timestamp
|
152
|
+
#
|
153
|
+
def self.extract_timestamp timestamp_grpc
|
154
|
+
return nil if timestamp_grpc.nil?
|
155
|
+
Time.at timestamp_grpc.seconds, Rational(timestamp_grpc.nanos, 1000)
|
156
|
+
end
|
157
|
+
|
158
|
+
##
|
159
|
+
# @private Extract service context info from gRPC into an ErrorEvent.
|
160
|
+
def self.extract_service_context error_event, service_context_grpc
|
161
|
+
return nil if service_context_grpc.nil?
|
162
|
+
|
163
|
+
error_event.service_name = service_context_grpc.service
|
164
|
+
error_event.service_version = service_context_grpc.version
|
165
|
+
end
|
166
|
+
|
167
|
+
##
|
168
|
+
# @private Extract error context info from gRPC into an ErrorEvent.
|
169
|
+
def self.extract_error_context error_event, error_context_grpc
|
170
|
+
return nil if error_context_grpc.nil?
|
171
|
+
|
172
|
+
error_event.user = error_context_grpc.user
|
173
|
+
extract_http_request error_event, error_context_grpc.http_request
|
174
|
+
extract_source_location error_event,
|
175
|
+
error_context_grpc.report_location
|
176
|
+
end
|
177
|
+
|
178
|
+
##
|
179
|
+
# @private Extract http request info from gRPC into an ErrorEvent.
|
180
|
+
def self.extract_http_request error_event, http_request_grpc
|
181
|
+
return nil if http_request_grpc.nil?
|
182
|
+
|
183
|
+
error_event.http_method = http_request_grpc["method"]
|
184
|
+
error_event.http_url = http_request_grpc.url
|
185
|
+
error_event.http_user_agent = http_request_grpc.user_agent
|
186
|
+
error_event.http_referrer = http_request_grpc.referrer
|
187
|
+
error_event.http_status = http_request_grpc.response_status_code
|
188
|
+
error_event.http_remote_ip = http_request_grpc.remote_ip
|
189
|
+
end
|
190
|
+
|
191
|
+
##
|
192
|
+
# @private Extract source location info from gRPC into an ErrorEvent.
|
193
|
+
def self.extract_source_location error_event, source_location_grpc
|
194
|
+
return nil if source_location_grpc.nil?
|
195
|
+
|
196
|
+
error_event.file_path = source_location_grpc.file_path
|
197
|
+
error_event.line_number = source_location_grpc.line_number
|
198
|
+
error_event.function_name = source_location_grpc.function_name
|
199
|
+
end
|
200
|
+
|
201
|
+
private_class_method :extract_timestamp,
|
202
|
+
:extract_service_context,
|
203
|
+
:extract_error_context,
|
204
|
+
:extract_http_request,
|
205
|
+
:extract_source_location
|
206
|
+
|
207
|
+
##
|
208
|
+
# Construct an ErrorEvent object based on a given exception.
|
209
|
+
#
|
210
|
+
# @param [Exception] exception A Ruby exception.
|
211
|
+
#
|
212
|
+
# @return [ErrorEvent] An ErrorEvent object containing information
|
213
|
+
# from the given exception.
|
214
|
+
def self.from_exception exception
|
215
|
+
backtrace = exception.backtrace
|
216
|
+
message = exception.message
|
217
|
+
|
218
|
+
unless backtrace.nil?
|
219
|
+
error_location = backtrace.first
|
220
|
+
|
221
|
+
message = "#{error_location}: #{message} (#{exception.class})\n\t" +
|
222
|
+
backtrace.drop(1).join("\n\t")
|
223
|
+
file_path, line_number, function_name = error_location.split(":")
|
224
|
+
function_name = function_name.to_s[/`(.*)'/, 1]
|
225
|
+
end
|
226
|
+
|
227
|
+
new.tap do |e|
|
228
|
+
e.message = message
|
229
|
+
e.file_path = file_path
|
230
|
+
e.line_number = line_number.to_i
|
231
|
+
e.function_name = function_name
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
##
|
236
|
+
# Convert ErrorEvent object to gRPC struct.
|
237
|
+
#
|
238
|
+
# @return [Devtools::Clouderrorreporting::V1beta1::ReportedErrorEvent]
|
239
|
+
# gRPC struct that represent an ErrorEvent.
|
240
|
+
def to_grpc
|
241
|
+
error_event_hash = {
|
242
|
+
event_time: event_time_hash,
|
243
|
+
message: message,
|
244
|
+
service_context: service_context_hash,
|
245
|
+
context: error_context_hash
|
246
|
+
}.delete_if { |_, v| v.nil? }
|
247
|
+
|
248
|
+
grpc_class =
|
249
|
+
Devtools::Clouderrorreporting::V1beta1::ReportedErrorEvent
|
250
|
+
grpc_class.decode_json error_event_hash.to_json
|
251
|
+
end
|
252
|
+
|
253
|
+
private
|
254
|
+
|
255
|
+
##
|
256
|
+
# @private Formats the event_time as the hash representation of
|
257
|
+
# Google::Protobuf::Timestamp struct.
|
258
|
+
#
|
259
|
+
def event_time_hash
|
260
|
+
return nil if event_time.nil?
|
261
|
+
{
|
262
|
+
seconds: event_time.to_i,
|
263
|
+
nanos: event_time.nsec
|
264
|
+
}
|
265
|
+
end
|
266
|
+
|
267
|
+
##
|
268
|
+
# @private Formats the service_name and service_version as the hash
|
269
|
+
# representation of
|
270
|
+
# Google::Devtools::Clouderrorreporting::V1beta1::SourceContext struct.
|
271
|
+
#
|
272
|
+
def service_context_hash
|
273
|
+
return nil if !service_name && !service_version
|
274
|
+
{
|
275
|
+
service: service_name,
|
276
|
+
version: service_version
|
277
|
+
}.delete_if { |_, v| v.nil? }
|
278
|
+
end
|
279
|
+
|
280
|
+
##
|
281
|
+
# @private Formats the error context info as the hash
|
282
|
+
# representation of
|
283
|
+
# Google::Devtools::Clouderrorreporting::V1beta1::ErrorContext struct.
|
284
|
+
#
|
285
|
+
def error_context_hash
|
286
|
+
http_request_hash = {
|
287
|
+
method: http_method,
|
288
|
+
url: http_url,
|
289
|
+
user_agent: http_user_agent,
|
290
|
+
referrer: http_referrer,
|
291
|
+
response_status_code: http_status,
|
292
|
+
remote_ip: http_remote_ip
|
293
|
+
}.delete_if { |_, v| v.nil? }
|
294
|
+
|
295
|
+
source_location_hash = {
|
296
|
+
file_path: file_path,
|
297
|
+
line_number: line_number,
|
298
|
+
function_name: function_name
|
299
|
+
}.delete_if { |_, v| v.nil? }
|
300
|
+
|
301
|
+
result = {
|
302
|
+
http_request: http_request_hash.empty? ? nil : http_request_hash,
|
303
|
+
user: user,
|
304
|
+
report_location:
|
305
|
+
source_location_hash.empty? ? nil : source_location_hash
|
306
|
+
}.delete_if { |_, v| v.nil? }
|
307
|
+
|
308
|
+
result.empty? ? nil : result
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
@@ -13,69 +13,51 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
|
16
|
-
require "google/cloud/env"
|
17
|
-
require "google/cloud/error_reporting/v1beta1"
|
18
|
-
require "rack"
|
19
|
-
require "rack/request"
|
20
|
-
|
21
16
|
module Google
|
22
17
|
module Cloud
|
23
18
|
module ErrorReporting
|
24
19
|
##
|
25
|
-
# Middleware
|
20
|
+
# # Middleware
|
26
21
|
#
|
27
22
|
# Google::Cloud::ErrorReporting::Middleware defines a Rack Middleware
|
28
23
|
# that can automatically catch upstream exceptions and report them
|
29
24
|
# to Stackdriver Error Reporting.
|
30
25
|
#
|
31
26
|
class Middleware
|
32
|
-
|
33
|
-
|
27
|
+
# A Google::Cloud::ErrorReporting::Project client used to report
|
28
|
+
# error events.
|
29
|
+
attr_reader :error_reporting
|
34
30
|
|
35
31
|
##
|
36
|
-
# Construct a new instance of Middleware
|
32
|
+
# Construct a new instance of Middleware.
|
37
33
|
#
|
38
|
-
# @param [Rack
|
39
|
-
# @param [
|
40
|
-
# Google::Cloud::ErrorReporting::
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
# @param [String] service_name Name of the service. Default to
|
47
|
-
# ENV["ERROR_REPORTING_SERVICE"] then "ruby". Automatically discovered
|
48
|
-
# if on GAE
|
49
|
-
# @param [String] service_version Version of the service. Optional.
|
50
|
-
# ENV["ERROR_REPORTING_VERSION"]. Automatically discovered if on GAE
|
51
|
-
# @param [Array<Class>] ignore_classes A single or an array of Exception
|
52
|
-
# classes to ignore
|
34
|
+
# @param [Rack::Application] app The Rack application
|
35
|
+
# @param [Google::Cloud::ErrorReporting::Project] error_reporting A
|
36
|
+
# Google::Cloud::ErrorReporting::Project client for reporting
|
37
|
+
# exceptions
|
38
|
+
# @param [Hash] *kwargs Hash of configuration settings. Used for
|
39
|
+
# backward API compatibility. See the [Configuration
|
40
|
+
# Guide](https://googlecloudplatform.github.io/google-cloud-ruby/#/docs/stackdriver/guides/instrumentation_configuration)
|
41
|
+
# for the prefered way to set configuration parameters.
|
53
42
|
#
|
54
43
|
# @return [Google::Cloud::ErrorReporting::Middleware] A new instance of
|
55
44
|
# Middleware
|
56
45
|
#
|
57
|
-
def initialize app,
|
58
|
-
|
59
|
-
|
60
|
-
service_name: nil,
|
61
|
-
service_version: nil,
|
62
|
-
ignore_classes: nil
|
46
|
+
def initialize app, error_reporting: nil, **kwargs
|
47
|
+
require "rack"
|
48
|
+
require "rack/request"
|
63
49
|
@app = app
|
64
|
-
@error_reporting = error_reporting
|
65
|
-
@service_name = service_name ||
|
66
|
-
ENV["ERROR_REPORTING_SERVICE"] ||
|
67
|
-
Google::Cloud.env.app_engine_service_id ||
|
68
|
-
"ruby"
|
69
|
-
@service_version = service_version ||
|
70
|
-
ENV["ERROR_REPORTING_VERSION"] ||
|
71
|
-
Google::Cloud.env.app_engine_service_version
|
72
|
-
@ignore_classes = Array(ignore_classes)
|
73
|
-
@project_id = project_id ||
|
74
|
-
ENV["ERROR_REPORTING_PROJECT"] ||
|
75
|
-
ENV["GOOGLE_CLOUD_PROJECT"] ||
|
76
|
-
Google::Cloud.env.project_id
|
77
50
|
|
78
|
-
|
51
|
+
load_config kwargs
|
52
|
+
|
53
|
+
@error_reporting =
|
54
|
+
error_reporting ||
|
55
|
+
ErrorReporting.new(project: configuration.project_id,
|
56
|
+
keyfile: configuration.keyfile)
|
57
|
+
|
58
|
+
# Set module default client to reuse the same client. Update module
|
59
|
+
# configuration parameters.
|
60
|
+
ErrorReporting.class_variable_set :@@default_client, @error_reporting
|
79
61
|
end
|
80
62
|
|
81
63
|
##
|
@@ -116,23 +98,22 @@ module Google
|
|
116
98
|
#
|
117
99
|
def report_exception env, exception
|
118
100
|
# Do not any exceptions that's specified by the ignore_classes list.
|
119
|
-
return if ignore_classes.include? exception.class
|
101
|
+
return if configuration.ignore_classes.include? exception.class
|
120
102
|
|
121
|
-
|
103
|
+
error_event = error_event_from_exception env, exception
|
122
104
|
|
123
105
|
# If this exception maps to a HTTP status code less than 500, do
|
124
106
|
# not report it.
|
125
|
-
status_code =
|
126
|
-
error_event_grpc.context.http_request.response_status_code.to_i
|
107
|
+
status_code = error_event.http_status.to_i
|
127
108
|
return if status_code > 0 && status_code < 500
|
128
109
|
|
129
|
-
error_reporting.
|
110
|
+
error_reporting.report error_event
|
130
111
|
end
|
131
112
|
|
132
113
|
##
|
133
|
-
# Creates a
|
134
|
-
#
|
135
|
-
# headers.
|
114
|
+
# Creates a {Google::Cloud::ErrorReporting::ErrorEvent} based on the
|
115
|
+
# exception. Fill in the HttpRequestContext section of the ErrorEvent
|
116
|
+
# based on the HTTP Request headers.
|
136
117
|
#
|
137
118
|
# When used in Rails environment. It replies on
|
138
119
|
# ActionDispatch::ExceptionWrapper class to derive a HTTP status code
|
@@ -141,56 +122,74 @@ module Google
|
|
141
122
|
# @param [Hash] env Rack environment hash
|
142
123
|
# @param [Exception] exception Exception to convert from
|
143
124
|
#
|
144
|
-
# @return [
|
145
|
-
#
|
146
|
-
# The gRPC ReportedErrorEvent object that's based
|
147
|
-
# on given exception
|
125
|
+
# @return [Google::Cloud::ErrorReporting::ErrorEvent] The gRPC
|
126
|
+
# ErrorEvent object that's based on given env and exception
|
148
127
|
#
|
149
|
-
def
|
150
|
-
error_event = ErrorEvent.from_exception exception
|
128
|
+
def error_event_from_exception env, exception
|
129
|
+
error_event = ErrorReporting::ErrorEvent.from_exception exception
|
151
130
|
|
152
131
|
# Inject service_context info into error_event object
|
153
|
-
error_event
|
154
|
-
|
155
|
-
version: service_version
|
156
|
-
}.delete_if { |_, v| v.nil? }
|
132
|
+
error_event.service_name = configuration.service_name
|
133
|
+
error_event.service_version = configuration.service_version
|
157
134
|
|
158
135
|
# Inject http_request_context info into error_event object
|
159
136
|
rack_request = Rack::Request.new env
|
160
|
-
error_event
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
error_event.to_grpc
|
137
|
+
error_event.http_method = rack_request.request_method
|
138
|
+
error_event.http_url = rack_request.url
|
139
|
+
error_event.http_user_agent = rack_request.user_agent
|
140
|
+
error_event.http_referrer = rack_request.referrer
|
141
|
+
error_event.http_status = http_status(exception)
|
142
|
+
error_event.http_remote_ip = rack_request.ip
|
143
|
+
|
144
|
+
error_event
|
170
145
|
end
|
171
146
|
|
147
|
+
private
|
148
|
+
|
172
149
|
##
|
173
|
-
#
|
174
|
-
#
|
175
|
-
#
|
176
|
-
#
|
177
|
-
|
178
|
-
|
179
|
-
|
150
|
+
# Consolidate configurations from various sources. Also set
|
151
|
+
# instrumentation config parameters to default values if not set
|
152
|
+
# already.
|
153
|
+
#
|
154
|
+
def load_config **kwargs
|
155
|
+
configuration.project_id = kwargs[:project_id] ||
|
156
|
+
configuration.project_id
|
157
|
+
configuration.keyfile = kwargs[:keyfile] ||
|
158
|
+
configuration.keyfile
|
159
|
+
configuration.service_name = kwargs[:service_name] ||
|
160
|
+
configuration.service_name
|
161
|
+
configuration.service_version = kwargs[:service_version] ||
|
162
|
+
configuration.service_version
|
163
|
+
configuration.ignore_classes = kwargs[:ignore_classes] ||
|
164
|
+
configuration.ignore_classes
|
165
|
+
|
166
|
+
init_default_config
|
180
167
|
end
|
181
168
|
|
182
|
-
|
169
|
+
##
|
170
|
+
# Fallback to default configuration values if not defined already
|
171
|
+
def init_default_config
|
172
|
+
configuration.project_id ||= Cloud.configure.project_id ||
|
173
|
+
ErrorReporting::Project.default_project
|
174
|
+
configuration.keyfile ||= Cloud.configure.keyfile
|
175
|
+
configuration.service_name ||=
|
176
|
+
ErrorReporting::Project.default_service_name
|
177
|
+
|
178
|
+
configuration.service_version ||=
|
179
|
+
ErrorReporting::Project.default_service_version
|
180
|
+
configuration.ignore_classes = Array(configuration.ignore_classes)
|
181
|
+
end
|
183
182
|
|
184
183
|
##
|
185
184
|
# Helper method to derive HTTP status code base on exception class in
|
186
|
-
# Rails. Returns nil if not in Rails environment
|
185
|
+
# Rails. Returns nil if not in Rails environment.
|
187
186
|
#
|
188
187
|
# @param [Exception] exception An Ruby exception
|
189
188
|
#
|
190
189
|
# @return [Integer] A number that represents HTTP status code or nil if
|
191
190
|
# status code can't be determined
|
192
191
|
#
|
193
|
-
def
|
192
|
+
def http_status exception
|
194
193
|
http_status = nil
|
195
194
|
if defined?(ActionDispatch::ExceptionWrapper) &&
|
196
195
|
ActionDispatch::ExceptionWrapper.respond_to?(
|
@@ -206,108 +205,10 @@ module Google
|
|
206
205
|
end
|
207
206
|
|
208
207
|
##
|
209
|
-
#
|
210
|
-
|
211
|
-
|
212
|
-
# Internal data structure mirroring gRPC ReportedErrorEvent structure
|
213
|
-
attr_reader :hash
|
214
|
-
|
215
|
-
##
|
216
|
-
# Construct a new ErrorEvent object
|
217
|
-
#
|
218
|
-
# @return [ErrorEvent] A new ErrorEvent object
|
219
|
-
def initialize
|
220
|
-
@hash = {}
|
221
|
-
end
|
222
|
-
|
223
|
-
##
|
224
|
-
# Construct an ErrorEvent object based on a given exception
|
225
|
-
#
|
226
|
-
# @param [Exception] exception A Ruby exception
|
227
|
-
#
|
228
|
-
# @return [ErrorEvent] An ErrorEvent object containing information
|
229
|
-
# from the given exception
|
230
|
-
def self.from_exception exception
|
231
|
-
exception_data = extract_exception exception
|
232
|
-
|
233
|
-
# Build error_context hash
|
234
|
-
error_context = {
|
235
|
-
user: ENV["USER"],
|
236
|
-
report_location: {
|
237
|
-
file_path: exception_data[:file_path],
|
238
|
-
function_name: exception_data[:function_name],
|
239
|
-
line_number: exception_data[:line_number].to_i
|
240
|
-
}.delete_if { |_, v| v.nil? }
|
241
|
-
}.delete_if { |_, v| v.nil? }
|
242
|
-
|
243
|
-
# Build error_event hash
|
244
|
-
error_event = ErrorEvent.new
|
245
|
-
t = Time.now
|
246
|
-
error_event.hash.merge!({
|
247
|
-
event_time: {
|
248
|
-
seconds: t.to_i,
|
249
|
-
nanos: t.nsec
|
250
|
-
},
|
251
|
-
message: exception_data[:message],
|
252
|
-
context: error_context
|
253
|
-
}.delete_if { |_, v| v.nil? })
|
254
|
-
|
255
|
-
error_event
|
256
|
-
end
|
257
|
-
|
258
|
-
##
|
259
|
-
# Helper method extract data from exception
|
260
|
-
#
|
261
|
-
# @param [Exception] exception A Ruby Exception
|
262
|
-
#
|
263
|
-
# @return [Hash] A hash containing formatted error message with
|
264
|
-
# backtrace, file_path, line_number, and function_name
|
265
|
-
def self.extract_exception exception
|
266
|
-
if exception.backtrace.nil? || exception.backtrace.empty?
|
267
|
-
message = exception.message
|
268
|
-
else
|
269
|
-
message = "#{exception.backtrace.first}: #{exception.message} " \
|
270
|
-
"(#{exception.class})\n\t" +
|
271
|
-
exception.backtrace.drop(1).join("\n\t")
|
272
|
-
file_path, line_number, function_name =
|
273
|
-
exception.backtrace.first.split(":")
|
274
|
-
function_name = function_name.to_s[/`(.*)'/, 1]
|
275
|
-
end
|
276
|
-
|
277
|
-
{
|
278
|
-
message: message,
|
279
|
-
file_path: file_path,
|
280
|
-
line_number: line_number,
|
281
|
-
function_name: function_name
|
282
|
-
}
|
283
|
-
end
|
284
|
-
private_class_method :extract_exception
|
285
|
-
|
286
|
-
##
|
287
|
-
# Get the value of the given key from internal hash
|
288
|
-
def [] key
|
289
|
-
hash[key]
|
290
|
-
end
|
291
|
-
|
292
|
-
##
|
293
|
-
# Write new value with the key in internal hash
|
294
|
-
def []= key, value
|
295
|
-
hash[key] = value
|
296
|
-
end
|
297
|
-
|
298
|
-
##
|
299
|
-
# Convert ErrorEvent object to gRPC struct
|
300
|
-
#
|
301
|
-
# @return [Devtools::Clouderrorreporting::V1beta1::ReportedErrorEvent]
|
302
|
-
# gRPC struct that represent an ErrorEvent
|
303
|
-
def to_grpc
|
304
|
-
grpc_module =
|
305
|
-
Devtools::Clouderrorreporting::V1beta1::ReportedErrorEvent
|
306
|
-
grpc_module.decode_json hash.to_json
|
307
|
-
end
|
208
|
+
# @private Get Google::Cloud::ErrorReporting.configure
|
209
|
+
def configuration
|
210
|
+
Google::Cloud::ErrorReporting.configure
|
308
211
|
end
|
309
|
-
|
310
|
-
private_constant :ErrorEvent
|
311
212
|
end
|
312
213
|
end
|
313
214
|
end
|