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,224 @@
|
|
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/errors"
|
17
|
+
require "google/cloud/env"
|
18
|
+
require "google/cloud/error_reporting/service"
|
19
|
+
require "google/cloud/error_reporting/credentials"
|
20
|
+
require "google/cloud/error_reporting/error_event"
|
21
|
+
|
22
|
+
module Google
|
23
|
+
module Cloud
|
24
|
+
module ErrorReporting
|
25
|
+
##
|
26
|
+
# Project
|
27
|
+
#
|
28
|
+
# Projects are top-level containers in Google Cloud Platform. They store
|
29
|
+
# information about billing and authorized users, and they control access
|
30
|
+
# to Stackdriver ErrorReporting. Each project has a friendly name and a
|
31
|
+
# unique ID. Projects can be created only in the [Google Developers
|
32
|
+
# Console](https://console.developers.google.com).
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# require "google/cloud/error_reporting"
|
36
|
+
#
|
37
|
+
# error_reporting = Google::Cloud::ErrorReporting.new
|
38
|
+
# error_event = error_reporting.error_event "Error with Backtrace",
|
39
|
+
# timestamp: Time.now
|
40
|
+
# service_name: "my_app_name"
|
41
|
+
# error_reporting.report error_event
|
42
|
+
#
|
43
|
+
# See {Google::Cloud::ErrorReporting.new}
|
44
|
+
#
|
45
|
+
class Project
|
46
|
+
##
|
47
|
+
# Find default project_id from `ERROR_REPORTING_RPOJECT`,
|
48
|
+
# `GOOGLE_CLOUD_PROJECT`, `GCLOUD_PROJECT` environment varaibles, or
|
49
|
+
# query from GCE meta service.
|
50
|
+
#
|
51
|
+
# @return [String] default valid GCP project_id
|
52
|
+
#
|
53
|
+
def self.default_project
|
54
|
+
ENV["ERROR_REPORTING_PROJECT"] ||
|
55
|
+
ENV["GOOGLE_CLOUD_PROJECT"] ||
|
56
|
+
Google::Cloud.env.project_id
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Find default service_name from `ERROR_REPORTING_SERVICE`,
|
61
|
+
# `GAE_MODULE_NAME` environment Variables, or just "ruby".
|
62
|
+
#
|
63
|
+
# @return [String] default GCP service_name
|
64
|
+
#
|
65
|
+
def self.default_service_name
|
66
|
+
ENV["ERROR_REPORTING_SERVICE"] ||
|
67
|
+
Google::Cloud.env.app_engine_service_id ||
|
68
|
+
"ruby"
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Find default service_version from `ERROR_REPORTING_VERSION` or
|
73
|
+
# `GAE_MODULE_VERSION` environment varaibles.
|
74
|
+
#
|
75
|
+
# @return [String] default GCP service_version
|
76
|
+
#
|
77
|
+
def self.default_service_version
|
78
|
+
ENV["ERROR_REPORTING_VERSION"] ||
|
79
|
+
Google::Cloud.env.app_engine_service_version
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# @private The Service object
|
84
|
+
attr_accessor :service
|
85
|
+
|
86
|
+
##
|
87
|
+
# @private Create a new Project instance.
|
88
|
+
#
|
89
|
+
# @param [Google::Cloud::ErrorReporting::Service] service The underlying
|
90
|
+
# Service object
|
91
|
+
#
|
92
|
+
# @return [Google::Cloud::ErrorReporting::Project] A new Project
|
93
|
+
# instance
|
94
|
+
#
|
95
|
+
def initialize service
|
96
|
+
@service = service
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Get the name of current project_id from underneath gRPC Service
|
101
|
+
# object.
|
102
|
+
#
|
103
|
+
# @return [String] The current project_id
|
104
|
+
#
|
105
|
+
def project
|
106
|
+
service.project
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Report a {Google::Cloud::ErrorReporting::ErrorEvent} to Stackdriver
|
111
|
+
# Error Reporting service.
|
112
|
+
#
|
113
|
+
# @example
|
114
|
+
# require "google/cloud/error_reporting"
|
115
|
+
#
|
116
|
+
# error_reporting = Google::Cloud::ErrorReporting.new
|
117
|
+
#
|
118
|
+
# error_event = error_reporting.error_event "Error with Backtrace"
|
119
|
+
# error_reporting.report error_event
|
120
|
+
#
|
121
|
+
def report *args, &block
|
122
|
+
service.report *args, &block
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Create a {Google::Cloud::ErrorReporting::ErrorEvent} from the
|
127
|
+
# given exception, and report this ErrorEvent to Stackdriver Error
|
128
|
+
# Reporting service.
|
129
|
+
#
|
130
|
+
# @param [Exception] exception A Ruby exception
|
131
|
+
# @param [String] service_name The service's name.
|
132
|
+
# Default to {default_service_name}
|
133
|
+
# @param [String] service_version The service's version.
|
134
|
+
# Default to {default_service_version}
|
135
|
+
#
|
136
|
+
# @example
|
137
|
+
# require "google/cloud/error_reporting"
|
138
|
+
#
|
139
|
+
# error_reporting = Google::Cloud::ErrorReporting.new
|
140
|
+
#
|
141
|
+
# begin
|
142
|
+
# fail StandardError, "A serious problem"
|
143
|
+
# rescue StandardError => exception
|
144
|
+
# error_reporting.report_exception, service_name: "my_app_name",
|
145
|
+
# service_version: "v8"
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
def report_exception exception, service_name: nil, service_version: nil
|
149
|
+
error_event = ErrorEvent.from_exception exception
|
150
|
+
|
151
|
+
error_event.service_name =
|
152
|
+
service_name || self.class.default_service_name
|
153
|
+
error_event.service_version =
|
154
|
+
service_version || self.class.default_service_version
|
155
|
+
|
156
|
+
yield error_event if block_given?
|
157
|
+
|
158
|
+
report error_event
|
159
|
+
end
|
160
|
+
|
161
|
+
##
|
162
|
+
# Create a new {Google::Cloud::ErrorReporting::ErrorEvent} instance
|
163
|
+
# with given parameters.
|
164
|
+
#
|
165
|
+
# @param [String] message The error message along with backtrace
|
166
|
+
# @param [String] service_name The service's name.
|
167
|
+
# Default to {default_service_name}
|
168
|
+
# @param [String] service_version The service's version.
|
169
|
+
# Default to {default_service_version}
|
170
|
+
# @param [Time] event_time Time when the event occurred. If not
|
171
|
+
# provided, the time when the event was received by the Error
|
172
|
+
# Reporting system will be used.
|
173
|
+
# @param [String] user The user who caused or was affected by the crash.
|
174
|
+
# This can be a user ID, an email address, or an arbitrary token that
|
175
|
+
# uniquely identifies the user. When sending an error report, leave
|
176
|
+
# this field empty if the user was not logged in. In this case the
|
177
|
+
# Error Reporting system will use other data, such as remote IP
|
178
|
+
# address, to distinguish affected users.
|
179
|
+
# @param [String] file_path The source code filename, which can include
|
180
|
+
# a truncated relative path, or a full path from a production machine.
|
181
|
+
# @param [Number] line_number 1-based. 0 indicates that the line number
|
182
|
+
# is unknown.
|
183
|
+
# @param [String] function_name Human-readable name of a function or
|
184
|
+
# method. The value can include optional context like the class or
|
185
|
+
# package name. For example, my.package.MyClass.method in case of
|
186
|
+
# Java.
|
187
|
+
#
|
188
|
+
# @return [ErrorEvent] A new ErrorEvent instance
|
189
|
+
#
|
190
|
+
# @example
|
191
|
+
# require "google/cloud/error_reporting"
|
192
|
+
#
|
193
|
+
# error_reporting = Google::Cloud::ErrorReporting.new
|
194
|
+
#
|
195
|
+
# error_event =
|
196
|
+
# error_reporting.error_event "Error Message with Backtrace",
|
197
|
+
# event_time: Time.now,
|
198
|
+
# service_name: "my_app_name",
|
199
|
+
# service_version: "v8",
|
200
|
+
# user: "johndoh",
|
201
|
+
# file_path: "MyController.rb",
|
202
|
+
# line_number: 123,
|
203
|
+
# function_name: "index"
|
204
|
+
# error_reporting.report error_event
|
205
|
+
#
|
206
|
+
def error_event message = nil, service_name: nil, service_version: nil,
|
207
|
+
event_time: nil, user: nil, file_path: nil,
|
208
|
+
line_number: nil, function_name: nil
|
209
|
+
ErrorEvent.new.tap do |e|
|
210
|
+
e.message = message
|
211
|
+
e.event_time = event_time
|
212
|
+
e.service_name = service_name || self.class.default_service_name
|
213
|
+
e.service_version = service_version ||
|
214
|
+
self.class.default_service_version
|
215
|
+
e.user = user
|
216
|
+
e.file_path = file_path
|
217
|
+
e.line_number = line_number
|
218
|
+
e.function_name = function_name
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2017 Google Inc. All rights reserved.
|
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.
|
@@ -13,38 +13,30 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
|
16
|
-
require "google/cloud/
|
17
|
-
require "google/cloud/error_reporting/v1beta1"
|
18
|
-
require "google/cloud/error_reporting/middleware"
|
19
|
-
require "google/cloud/credentials"
|
16
|
+
require "google/cloud/error_reporting"
|
20
17
|
|
21
18
|
module Google
|
22
19
|
module Cloud
|
23
20
|
module ErrorReporting
|
24
21
|
##
|
25
|
-
# Railtie
|
22
|
+
# # Railtie
|
26
23
|
#
|
27
24
|
# Google::Cloud::ErrorReporting::Railtie automatically add the
|
28
|
-
# Google::Cloud::ErrorReporting::Middleware to Rack in a Rails
|
25
|
+
# {Google::Cloud::ErrorReporting::Middleware} to Rack in a Rails
|
29
26
|
# environment. It will automatically capture Exceptions from the Rails app
|
30
|
-
# and report them to Stackdriver Error Reporting.
|
27
|
+
# and report them to the Stackdriver Error Reporting service.
|
31
28
|
#
|
32
29
|
# The Middleware is only added when certain conditions are met. See
|
33
30
|
# {Railtie.use_error_reporting?} for detail.
|
34
31
|
#
|
35
|
-
# When loaded, the Google::Cloud::ErrorReporting::Middleware will be
|
36
|
-
# inserted after
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
# or
|
44
|
-
# config.google_cloud.error_reporting.project_id = "my-gcp-project"
|
45
|
-
# config.google_cloud.error_reporting.keyfile = "/path/to/secret.json"
|
46
|
-
# config.google_cloud.error_reporting.service_name = "my-service-name"
|
47
|
-
# config.google_cloud.error_reporting.service_version = "v1"
|
32
|
+
# When loaded, the {Google::Cloud::ErrorReporting::Middleware} will be
|
33
|
+
# inserted after ActionDispatch::DebugExceptions or
|
34
|
+
# ActionDispatch::ShowExceptions Middleware, which allows it to intercept
|
35
|
+
# and handle all Exceptions without interfering with Rails's normal error
|
36
|
+
# pages.
|
37
|
+
# See the [Configuration
|
38
|
+
# Guide](https://googlecloudplatform.github.io/google-cloud-ruby/#/docs/stackdriver/guides/instrumentation_configuration)
|
39
|
+
# on how to configure the Railtie and Middleware.
|
48
40
|
#
|
49
41
|
class Railtie < ::Rails::Railtie
|
50
42
|
config.google_cloud = ActiveSupport::OrderedOptions.new unless
|
@@ -52,134 +44,112 @@ module Google
|
|
52
44
|
config.google_cloud.error_reporting = ActiveSupport::OrderedOptions.new
|
53
45
|
|
54
46
|
initializer "Google.Cloud.ErrorReporting" do |app|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
project_id = er_config.project_id || gcp_config.project_id
|
60
|
-
keyfile = er_config.keyfile || gcp_config.keyfile
|
61
|
-
|
62
|
-
channel = self.class.grpc_channel keyfile
|
63
|
-
service_name = er_config.service_name
|
64
|
-
service_version = er_config.service_version
|
65
|
-
|
66
|
-
error_reporting = V1beta1::ReportErrorsServiceClient.new(
|
67
|
-
channel: channel
|
68
|
-
)
|
69
|
-
|
70
|
-
# In later versions of Rails, ActionDispatch::DebugExceptions is
|
71
|
-
# responsible for catching exceptions. But it didn't exist until
|
72
|
-
# Rails 3.2. So we use ShowExceptions as pivot for earlier Rails.
|
73
|
-
rails_exception_middleware =
|
74
|
-
if defined? ::ActionDispatch::DebugExceptions
|
75
|
-
::ActionDispatch::DebugExceptions
|
76
|
-
else
|
77
|
-
::ActionDispatch::ShowExceptions
|
78
|
-
end
|
79
|
-
|
80
|
-
app.middleware.insert_after rails_exception_middleware,
|
81
|
-
Middleware,
|
82
|
-
project_id: project_id,
|
83
|
-
error_reporting: error_reporting,
|
84
|
-
service_name: service_name,
|
85
|
-
service_version: service_version
|
86
|
-
end
|
47
|
+
self.class.consolidate_rails_config app.config
|
48
|
+
|
49
|
+
self.class.init_middleware app if Cloud.configure.use_error_reporting
|
87
50
|
end
|
88
51
|
|
89
52
|
##
|
90
|
-
#
|
91
|
-
#
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
else
|
106
|
-
Google::Cloud::Credentials.new(
|
107
|
-
keyfile, scope: scopes)
|
108
|
-
end
|
109
|
-
|
110
|
-
# Return nil if :this_channel_is_insecure
|
111
|
-
return nil if credentials == :this_channel_is_insecure
|
112
|
-
|
113
|
-
channel_cred = GRPC::Core::ChannelCredentials.new.compose \
|
114
|
-
GRPC::Core::CallCredentials.new credentials.client.updater_proc
|
115
|
-
host = V1beta1::ReportErrorsServiceClient::SERVICE_ADDRESS
|
116
|
-
|
117
|
-
GRPC::Core::Channel.new host, nil, channel_cred
|
53
|
+
# @private Init Error Reporting integration for Rails. Setup
|
54
|
+
# configuration and insert the Middleware.
|
55
|
+
def self.init_middleware app
|
56
|
+
# In later versions of Rails, ActionDispatch::DebugExceptions is
|
57
|
+
# responsible for catching exceptions. But it didn't exist until
|
58
|
+
# Rails 3.2. So we use ShowExceptions as fallback for earlier Rails.
|
59
|
+
rails_exception_middleware =
|
60
|
+
if defined? ::ActionDispatch::DebugExceptions
|
61
|
+
::ActionDispatch::DebugExceptions
|
62
|
+
else
|
63
|
+
::ActionDispatch::ShowExceptions
|
64
|
+
end
|
65
|
+
|
66
|
+
app.middleware.insert_after rails_exception_middleware,
|
67
|
+
Google::Cloud::ErrorReporting::Middleware
|
118
68
|
end
|
119
69
|
|
120
70
|
##
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
71
|
+
# @private Consolidate Rails configuration into Error Reporting
|
72
|
+
# instrumentation configuration. Also consolidate the
|
73
|
+
# `use_error_reporting` setting by verifying credentials and Rails
|
74
|
+
# environment. The `use_error_reporting` setting will be true if
|
75
|
+
# credentials are valid, and the setting is manually set to true or
|
76
|
+
# Rails is in production environment.
|
127
77
|
#
|
128
78
|
# @param [Rails::Railtie::Configuration] config The
|
129
79
|
# Rails.application.config
|
130
80
|
#
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
81
|
+
def self.consolidate_rails_config config
|
82
|
+
merge_rails_config config
|
83
|
+
|
84
|
+
init_default_config
|
85
|
+
|
86
|
+
# Done if Google::Cloud.configure.use_error_reporting is explicitly
|
87
|
+
# false
|
88
|
+
return if Google::Cloud.configure.use_error_reporting == false
|
89
|
+
|
90
|
+
# Verify credentials and set use_error_reporting to false if
|
91
|
+
# credentials are invalid
|
92
|
+
unless valid_credentials? ErrorReporting.configure.project_id,
|
93
|
+
ErrorReporting.configure.keyfile
|
94
|
+
Cloud.configure.use_error_reporting = false
|
95
|
+
return
|
96
|
+
end
|
97
|
+
|
98
|
+
# Otherwise set use_error_reporting to true if Rails is running in
|
99
|
+
# production
|
100
|
+
Google::Cloud.configure.use_error_reporting ||= Rails.env.production?
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# @private Merge Rails configuration into Error Reporting
|
105
|
+
# instrumentation configuration.
|
106
|
+
def self.merge_rails_config rails_config
|
107
|
+
gcp_config = rails_config.google_cloud
|
135
108
|
er_config = gcp_config.error_reporting
|
136
109
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
110
|
+
Cloud.configure.use_error_reporting ||= gcp_config.use_error_reporting
|
111
|
+
ErrorReporting.configure do |config|
|
112
|
+
config.project_id ||= er_config.project_id || gcp_config.project_id
|
113
|
+
config.keyfile ||= er_config.keyfile || gcp_config.keyfile
|
114
|
+
config.service_name ||= er_config.service_name
|
115
|
+
config.service_version ||= er_config.service_version
|
116
|
+
config.ignore_classes ||= er_config.ignore_classes
|
117
|
+
end
|
118
|
+
end
|
141
119
|
|
142
|
-
|
143
|
-
|
144
|
-
|
120
|
+
##
|
121
|
+
# Fallback to default config values if config parameters not provided.
|
122
|
+
def self.init_default_config
|
123
|
+
config = ErrorReporting.configure
|
124
|
+
config.project_id ||= ErrorReporting::Project.default_project
|
125
|
+
config.service_name ||= ErrorReporting::Project.default_service_name
|
126
|
+
config.service_version ||=
|
127
|
+
ErrorReporting::Project.default_service_version
|
128
|
+
end
|
129
|
+
|
130
|
+
##
|
131
|
+
# @private Verify credentials
|
132
|
+
def self.valid_credentials? project_id, keyfile
|
145
133
|
begin
|
146
|
-
|
147
|
-
rescue
|
148
|
-
|
149
|
-
|
134
|
+
ErrorReporting::Credentials.credentials_with_scope keyfile
|
135
|
+
rescue => e
|
136
|
+
STDOUT.puts "Note: Google::Cloud::ErrorReporting is disabled " \
|
137
|
+
"because it failed to authorize with the service. (#{e.message})"
|
150
138
|
return false
|
151
139
|
end
|
152
140
|
|
153
|
-
if project_id
|
154
|
-
|
155
|
-
|
141
|
+
if project_id.to_s.empty?
|
142
|
+
STDOUT.puts "Note: Google::Cloud::ErrorReporting is disabled " \
|
143
|
+
"because the project ID could not be determined."
|
156
144
|
return false
|
157
145
|
end
|
158
146
|
|
159
|
-
|
160
|
-
# config.google_cloud.use_error_reporting is explicitly true
|
161
|
-
Rails.env.production? ||
|
162
|
-
(gcp_config.key?(:use_error_reporting) &&
|
163
|
-
gcp_config.use_error_reporting)
|
147
|
+
true
|
164
148
|
end
|
165
149
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
#
|
170
|
-
# @param [Rails::Railtie::Configuration] config The
|
171
|
-
# Rails.application.config
|
172
|
-
#
|
173
|
-
# @return [String] GCP project_id
|
174
|
-
#
|
175
|
-
def self.project_id config
|
176
|
-
config.google_cloud.error_reporting.project_id ||
|
177
|
-
config.google_cloud.project_id ||
|
178
|
-
ENV["ERROR_REPORTING_PROJECT"] ||
|
179
|
-
ENV["GOOGLE_CLOUD_PROJECT"] ||
|
180
|
-
Google::Cloud.env.project_id
|
181
|
-
end
|
182
|
-
private_class_method :project_id
|
150
|
+
private_class_method :merge_rails_config,
|
151
|
+
:init_default_config,
|
152
|
+
:valid_credentials?
|
183
153
|
end
|
184
154
|
end
|
185
155
|
end
|