google-cloud-error_reporting 0.21.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 +7 -0
- data/README.md +82 -0
- data/Rakefile +72 -0
- data/lib/google/cloud/error_reporting/middleware.rb +242 -0
- data/lib/google/cloud/error_reporting/rails.rb +173 -0
- data/lib/google/cloud/error_reporting/v1beta1.rb +24 -0
- data/lib/google/cloud/error_reporting/v1beta1/error_group_service_api.rb +229 -0
- data/lib/google/cloud/error_reporting/v1beta1/error_group_service_client_config.json +38 -0
- data/lib/google/cloud/error_reporting/v1beta1/error_stats_service_api.rb +371 -0
- data/lib/google/cloud/error_reporting/v1beta1/error_stats_service_client_config.json +43 -0
- data/lib/google/cloud/error_reporting/v1beta1/report_errors_service_api.rb +196 -0
- data/lib/google/cloud/error_reporting/v1beta1/report_errors_service_client_config.json +33 -0
- data/lib/google/devtools/clouderrorreporting/v1beta1/common_pb.rb +61 -0
- data/lib/google/devtools/clouderrorreporting/v1beta1/error_group_service_pb.rb +26 -0
- data/lib/google/devtools/clouderrorreporting/v1beta1/error_group_service_services_pb.rb +48 -0
- data/lib/google/devtools/clouderrorreporting/v1beta1/error_stats_service_pb.rb +109 -0
- data/lib/google/devtools/clouderrorreporting/v1beta1/error_stats_service_services_pb.rb +50 -0
- data/lib/google/devtools/clouderrorreporting/v1beta1/report_errors_service_pb.rb +34 -0
- data/lib/google/devtools/clouderrorreporting/v1beta1/report_errors_service_services_pb.rb +52 -0
- metadata +257 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5600f55b4c5304420859f9c425895392f0e8f8e9
|
4
|
+
data.tar.gz: cb684753b01da03c48ca26056318635ecddf65ec
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8b0ccadbb064b195a2a9c40f4dd97a822c01bfd2932b2dc9a792e416c3763ae52c1940180870409845db7102b765cbcce397b5ad0398108a2506d5710e34fcff
|
7
|
+
data.tar.gz: 67b194caaecf90cc12912fc8b2c178e19a67187579a9ac99d546562324d7e4439ce2a5a7807a2668b06baf6f3a1880d14d57e7d06f3ecf7b1fb7b813277d45c2
|
data/README.md
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
Stackdriver Clouderrorreporting API for Ruby
|
2
|
+
=================================================
|
3
|
+
|
4
|
+
google-cloud-error_reporting uses [Google API extensions][google-gax] to provide an
|
5
|
+
easy-to-use client library for the [Stackdriver Clouderrorreporting API][] (v1beta1) defined in the [googleapis][] git repository
|
6
|
+
|
7
|
+
|
8
|
+
[googleapis]: https://github.com/googleapis/googleapis/tree/master/google/google/devtools/clouderrorreporting/v1beta1
|
9
|
+
[google-gax]: https://github.com/googleapis/gax-ruby
|
10
|
+
[Stackdriver Clouderrorreporting API]: https://developers.google.com/apis-explorer/#p/clouderrorreporting/v1beta1/
|
11
|
+
|
12
|
+
Getting started
|
13
|
+
---------------
|
14
|
+
|
15
|
+
google-cloud-error_reporting will allow you to connect to the [Stackdriver Clouderrorreporting API][] and access all its methods.
|
16
|
+
|
17
|
+
In order to achieve so you need to set up authentication as well as install the library locally.
|
18
|
+
|
19
|
+
|
20
|
+
Setup Authentication
|
21
|
+
--------------------
|
22
|
+
|
23
|
+
To authenticate all your API calls, first install and setup the [Google Cloud SDK][].
|
24
|
+
Once done, you can then run the following command in your terminal:
|
25
|
+
|
26
|
+
$ gcloud beta auth application-default login
|
27
|
+
|
28
|
+
or
|
29
|
+
|
30
|
+
$ gcloud auth login
|
31
|
+
|
32
|
+
Please see [[gcloud beta auth application-default login][] document for the difference between these commands.
|
33
|
+
|
34
|
+
[Google Cloud SDK]: https://cloud.google.com/sdk/
|
35
|
+
[gcloud beta auth application-default login]: https://cloud.google.com/sdk/gcloud/reference/beta/auth/application-default/login
|
36
|
+
|
37
|
+
|
38
|
+
Installation
|
39
|
+
-------------------
|
40
|
+
|
41
|
+
Install this library using gem:
|
42
|
+
|
43
|
+
$ [sudo] gem install google-cloud-error_reporting
|
44
|
+
|
45
|
+
|
46
|
+
Rails Integration
|
47
|
+
---------------
|
48
|
+
|
49
|
+
This library also provides a built in Railtie for Ruby on Rails integration. To do this, simply add this line to config/application.rb:
|
50
|
+
```ruby
|
51
|
+
require "google/cloud/error_reporting/rails"
|
52
|
+
```
|
53
|
+
Then the library can be configured through this set of Rails parameters in config/environments/*.rb:
|
54
|
+
```ruby
|
55
|
+
# Sharing authentication parameters
|
56
|
+
config.google_cloud.project_id = "gcp-project-id"
|
57
|
+
config.google_cloud.keyfile = "/path/to/gcp/secret.json"
|
58
|
+
# Or more specificly for ErrorReporting
|
59
|
+
config.google_cloud.error_reporting.project_id = "gcp-project-id"
|
60
|
+
config.google_cloud.error_reporting.keyfile = "/path/to/gcp/sercret.json"
|
61
|
+
|
62
|
+
# Explicitly enable or disable ErrorReporting
|
63
|
+
config.google_cloud.use_error_reporting = true
|
64
|
+
|
65
|
+
# Set Stackdriver Error Reporting service context
|
66
|
+
config.google_cloud.error_reporting.service_name = "my-app-name"
|
67
|
+
config.google_cloud.error_reporting.service_version = "my-app-version"
|
68
|
+
```
|
69
|
+
|
70
|
+
Alternatively, check out [stackdriver](../stackdriver) gem, which includes this Railtie by default.
|
71
|
+
|
72
|
+
Rack Integration
|
73
|
+
---------------
|
74
|
+
|
75
|
+
Other Rack base framework can also directly leverage the built-in Middleware.
|
76
|
+
```ruby
|
77
|
+
require "google/cloud/error_reporting/v1beta1"
|
78
|
+
|
79
|
+
use Google::Cloud::ErrorReporting::Middleware
|
80
|
+
```
|
81
|
+
|
82
|
+
At this point you are all set to continue.
|
data/Rakefile
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Copyright 2016 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 "bundler/setup"
|
17
|
+
require "bundler/gem_tasks"
|
18
|
+
|
19
|
+
task :test do
|
20
|
+
$LOAD_PATH.unshift "lib", "test"
|
21
|
+
Dir.glob("test/**/*_test.rb").each { |file| require_relative file }
|
22
|
+
end
|
23
|
+
|
24
|
+
task :rubocop do
|
25
|
+
end
|
26
|
+
|
27
|
+
namespace :test do
|
28
|
+
desc "Runs tests with coverage."
|
29
|
+
task :coverage do
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Acceptance tests
|
34
|
+
desc "Runs the error_reporting acceptance tests."
|
35
|
+
task :acceptance, :project, :keyfile do |_, args|
|
36
|
+
end
|
37
|
+
|
38
|
+
namespace :acceptance do
|
39
|
+
desc "Runs acceptance tests with coverage."
|
40
|
+
task :coverage, :project, :keyfile do |t, args|
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
desc "Runs acceptance cleanup."
|
45
|
+
task :cleanup do
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "Runs yard-doctest example tests."
|
50
|
+
task :doctest do
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "Start an interactive shell."
|
54
|
+
task :console do
|
55
|
+
end
|
56
|
+
|
57
|
+
require "yard"
|
58
|
+
require "yard/rake/yardoc_task"
|
59
|
+
YARD::Rake::YardocTask.new
|
60
|
+
|
61
|
+
desc "Generates JSON output from google-cloud-error_reporting .yardoc"
|
62
|
+
task :jsondoc => :yard do
|
63
|
+
require "rubygems"
|
64
|
+
require "gcloud/jsondoc"
|
65
|
+
|
66
|
+
registry = YARD::Registry.load! ".yardoc"
|
67
|
+
generator = Gcloud::Jsondoc::Generator.new registry, "google-cloud-error_reporting"
|
68
|
+
generator.write_to "jsondoc"
|
69
|
+
cp ["docs/toc.json"], "jsondoc", verbose: true
|
70
|
+
end
|
71
|
+
|
72
|
+
task :default => :test
|
@@ -0,0 +1,242 @@
|
|
1
|
+
# Copyright 2016 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
|
+
require "rack"
|
16
|
+
require "rack/request"
|
17
|
+
|
18
|
+
module Google
|
19
|
+
module Cloud
|
20
|
+
module ErrorReporting
|
21
|
+
##
|
22
|
+
# Middleware
|
23
|
+
#
|
24
|
+
# Google::Cloud::ErrorReporting::Middleware defines a Rack Middleware
|
25
|
+
# that can automatically catch upstream exceptions and report them
|
26
|
+
# to Stackdriver Error Reporting.
|
27
|
+
#
|
28
|
+
class Middleware
|
29
|
+
attr_reader :error_reporting, :ignore_classes, :project_id,
|
30
|
+
:service_name, :service_version
|
31
|
+
|
32
|
+
##
|
33
|
+
# Construct a new instance of Middleware
|
34
|
+
#
|
35
|
+
# @param [Rack Application] app The Rack application
|
36
|
+
# @param [Google::Cloud::ErrorReporting::V1beta1::ReportErrorsServiceApi]
|
37
|
+
# error_reporting A ErrorReporting::V1beta1::ReportErrorsServiceApi
|
38
|
+
# object to for reporting exceptions
|
39
|
+
# @param [String] project_id Name of GCP project. Default to
|
40
|
+
# ENV["ERROR_REPORTING_PROJECT"] then ENV["GOOGLE_CLOUD_PROJECT"].
|
41
|
+
# Automatically discovered if on GAE
|
42
|
+
# @param [String] service_name Name of the service. Default to
|
43
|
+
# ENV["ERROR_REPORTING_SERVICE"] then "ruby". Automatically discovered
|
44
|
+
# if on GAE
|
45
|
+
# @param [String] service_version Version of the service. Optional.
|
46
|
+
# ENV["ERROR_REPORTING_VERSION"]. Automatically discovered if on GAE
|
47
|
+
# @param [Array<Class>] ignore_classes A single or an array of Exception
|
48
|
+
# classes to ignore
|
49
|
+
#
|
50
|
+
# @return A new instance of Middleware
|
51
|
+
#
|
52
|
+
def initialize app, error_reporting: nil, project_id: nil,
|
53
|
+
service_name: nil, service_version: nil,
|
54
|
+
ignore_classes: nil
|
55
|
+
@app = app
|
56
|
+
@error_reporting = error_reporting ||
|
57
|
+
Google::Cloud::ErrorReporting::V1beta1::ReportErrorsServiceApi.new
|
58
|
+
|
59
|
+
@service_name = service_name ||
|
60
|
+
ENV["ERROR_REPORTING_SERVICE"] ||
|
61
|
+
Google::Cloud::Core::Environment.gae_module_id ||
|
62
|
+
"ruby"
|
63
|
+
@service_version = service_version ||
|
64
|
+
ENV["ERROR_REPORTING_VERSION"] ||
|
65
|
+
Google::Cloud::Core::Environment.gae_module_version
|
66
|
+
@ignore_classes = Array(ignore_classes)
|
67
|
+
@project_id = project_id ||
|
68
|
+
ENV["ERROR_REPORTING_PROJECT"] ||
|
69
|
+
ENV["GOOGLE_CLOUD_PROJECT"] ||
|
70
|
+
Google::Cloud::Core::Environment.project_id
|
71
|
+
|
72
|
+
raise ArgumentError, "project_id is required" if @project_id.nil?
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Implements the mandatory Rack Middleware call method.
|
77
|
+
#
|
78
|
+
# Catch all Exceptions from upstream and report them to Stackdriver
|
79
|
+
# Error Reporting. Unless the exception's class is defined to be ignored
|
80
|
+
# by this Middleware.
|
81
|
+
#
|
82
|
+
# @param [Hash] env Rack environment hash
|
83
|
+
#
|
84
|
+
def call env
|
85
|
+
response = @app.call env
|
86
|
+
|
87
|
+
# sinatra doesn't always raise the Exception, but it saves it in
|
88
|
+
# env['sinatra.error']
|
89
|
+
if env["sinatra.error"].is_a? Exception
|
90
|
+
report_exception env, env["sinatra.error"]
|
91
|
+
end
|
92
|
+
|
93
|
+
response
|
94
|
+
rescue Exception => exception
|
95
|
+
report_exception env, exception
|
96
|
+
|
97
|
+
# Always raise exception backup
|
98
|
+
raise exception
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Report an given exception to Stackdriver Error Reporting.
|
103
|
+
#
|
104
|
+
# While it reports most of the exceptions. Certain Rails exceptions that
|
105
|
+
# maps to a HTTP status code less than 500 will be treated as not the
|
106
|
+
# app fault and ignored.
|
107
|
+
#
|
108
|
+
# @param [Hash] env Rack environment hash
|
109
|
+
# @param [Exception] exception The Ruby exception to report.
|
110
|
+
#
|
111
|
+
def report_exception env, exception
|
112
|
+
# Do not any exceptions that's specified by the ignore_classes list.
|
113
|
+
return if ignore_classes.include? exception.class
|
114
|
+
|
115
|
+
error_event = build_error_event_from_exception env,
|
116
|
+
exception
|
117
|
+
|
118
|
+
# If this exception maps to a HTTP status code less than 500, do
|
119
|
+
# not report it.
|
120
|
+
return if
|
121
|
+
error_event.context.http_request.response_status_code.to_i < 500
|
122
|
+
|
123
|
+
error_reporting.report_error_event full_project_id, error_event
|
124
|
+
end
|
125
|
+
|
126
|
+
##
|
127
|
+
# Creates a GRPC ErrorEvent based on the exception. Fill in the
|
128
|
+
# HttpRequestContext section of the ErrorEvent based on the HTTP Request
|
129
|
+
# headers.
|
130
|
+
#
|
131
|
+
# When used in Rails environment. It replies on
|
132
|
+
# ActionDispatch::ExceptionWrapper class to derive a HTTP status code
|
133
|
+
# based on the exception's class.
|
134
|
+
#
|
135
|
+
# @param [Hash] env Rack environment hash
|
136
|
+
# @param [Exception] exception Exception to convert from
|
137
|
+
#
|
138
|
+
# @return [Google::Devtools::Clouderrorreporting::V1beta1::ReportedErrorEvent]
|
139
|
+
# The gRPC ReportedErrorEvent object that's based on given exception
|
140
|
+
#
|
141
|
+
def build_error_event_from_exception env, exception
|
142
|
+
# Build service_context hash
|
143
|
+
service_context = {
|
144
|
+
service: service_name,
|
145
|
+
version: service_version
|
146
|
+
}.delete_if { |k,v| v.nil? }
|
147
|
+
|
148
|
+
# Build error message and source_location hash
|
149
|
+
if exception.backtrace.nil? || exception.backtrace.empty?
|
150
|
+
message = exception.message
|
151
|
+
report_location = nil
|
152
|
+
else
|
153
|
+
message = "#{exception.backtrace.first}: #{exception.message} " \
|
154
|
+
"(#{exception.class})\n\t" +
|
155
|
+
exception.backtrace.drop(1).join("\n\t")
|
156
|
+
file_path, line_number, function_name =
|
157
|
+
exception.backtrace.first.split(":")
|
158
|
+
function_name = function_name.to_s[/`(.*)'/, 1]
|
159
|
+
report_location = {
|
160
|
+
file_path: file_path,
|
161
|
+
function_name: function_name,
|
162
|
+
line_number: line_number.to_i
|
163
|
+
}.delete_if { |k,v| v.nil? }
|
164
|
+
end
|
165
|
+
|
166
|
+
# Build http_request_context hash
|
167
|
+
rack_request = Rack::Request.new env
|
168
|
+
http_method = rack_request.request_method
|
169
|
+
http_url = rack_request.url
|
170
|
+
http_user_agent = rack_request.user_agent
|
171
|
+
http_referrer = rack_request.referrer
|
172
|
+
http_status = get_http_status exception
|
173
|
+
http_remote_ip = rack_request.ip
|
174
|
+
http_request_context = {
|
175
|
+
method: http_method,
|
176
|
+
url: http_url,
|
177
|
+
user_agent: http_user_agent,
|
178
|
+
referrer: http_referrer,
|
179
|
+
response_status_code: http_status,
|
180
|
+
remote_ip: http_remote_ip
|
181
|
+
}.delete_if { |k,v| v.nil? }
|
182
|
+
|
183
|
+
# Build error_context hash
|
184
|
+
error_context = {
|
185
|
+
http_request: http_request_context,
|
186
|
+
user: ENV["USER"],
|
187
|
+
report_location: report_location,
|
188
|
+
}.delete_if { |k,v| v.nil? }
|
189
|
+
|
190
|
+
# Build error_event hash
|
191
|
+
t = Time.now
|
192
|
+
error_event = {
|
193
|
+
event_time: {
|
194
|
+
seconds: t.to_i,
|
195
|
+
nanos: t.nsec
|
196
|
+
},
|
197
|
+
service_context: service_context,
|
198
|
+
message: message,
|
199
|
+
context: error_context
|
200
|
+
}.delete_if { |k,v| v.nil? }
|
201
|
+
|
202
|
+
# Finally build and return GRPC ErrorEvent
|
203
|
+
Google::Devtools::Clouderrorreporting::V1beta1::ReportedErrorEvent.decode_json \
|
204
|
+
error_event.to_json
|
205
|
+
end
|
206
|
+
|
207
|
+
##
|
208
|
+
# Build full ReportErrorsServiceApi project_path from project_id, which
|
209
|
+
# is in "projects/#{project_id}" format.
|
210
|
+
def full_project_id
|
211
|
+
Google::Cloud::ErrorReporting::V1beta1::ReportErrorsServiceApi.project_path project_id
|
212
|
+
end
|
213
|
+
|
214
|
+
private
|
215
|
+
|
216
|
+
##
|
217
|
+
# Helper method to derive HTTP status code base on exception class in
|
218
|
+
# Rails. Returns nil if not in Rails environment
|
219
|
+
#
|
220
|
+
# @param [Exception] exception An Ruby exception
|
221
|
+
#
|
222
|
+
# @return [Integer] A number that represents HTTP status code or nil if
|
223
|
+
# status code can't be determined
|
224
|
+
#
|
225
|
+
def get_http_status exception
|
226
|
+
http_status = nil
|
227
|
+
if defined?(ActionDispatch::ExceptionWrapper) &&
|
228
|
+
ActionDispatch::ExceptionWrapper.respond_to?(
|
229
|
+
:status_code_for_exception
|
230
|
+
)
|
231
|
+
http_status =
|
232
|
+
ActionDispatch::ExceptionWrapper.status_code_for_exception(
|
233
|
+
exception.class.name
|
234
|
+
)
|
235
|
+
end
|
236
|
+
|
237
|
+
http_status
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
# Copyright 2016 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/error_reporting/v1beta1"
|
17
|
+
require "google/cloud/credentials"
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Cloud
|
21
|
+
module ErrorReporting
|
22
|
+
##
|
23
|
+
# Railtie
|
24
|
+
#
|
25
|
+
# Google::Cloud::ErrorReporting::Railtie automatically add the
|
26
|
+
# Google::Cloud::ErrorReporting::Middleware to Rack in a Rails environment.
|
27
|
+
# It will automatically capture Exceptions from the Rails app and report
|
28
|
+
# them to Stackdriver Error Reporting.
|
29
|
+
#
|
30
|
+
# The Middleware is only added when certain conditions are met. See
|
31
|
+
# {Railtie.use_error_reporting?} for detail.
|
32
|
+
#
|
33
|
+
# When loaded, the Google::Cloud::ErrorReporting::Middleware will be
|
34
|
+
# inserted after ::ActionDispatch::DebugExceptions Middleware, which allows
|
35
|
+
# it to actually rescue all Exceptions and throw it back up. The middleware
|
36
|
+
# should also be initialized with correct gcp project_id, keyfile,
|
37
|
+
# service_name, and service_version if they are defined in
|
38
|
+
# Rails environment files as follow:
|
39
|
+
# config.google_cloud.project_id = "my-gcp-project"
|
40
|
+
# config.google_cloud.keyfile = "/path/to/secret.json"
|
41
|
+
# or
|
42
|
+
# config.google_cloud.error_reporting.project_id = "my-gcp-project"
|
43
|
+
# config.google_cloud.error_reporting.keyfile = "/path/to/secret.json"
|
44
|
+
# config.google_cloud.error_reporting.service_name = "my-service-name"
|
45
|
+
# config.google_cloud.error_reporting.service_version = "v1"
|
46
|
+
#
|
47
|
+
class Railtie < ::Rails::Railtie
|
48
|
+
config.google_cloud = ActiveSupport::OrderedOptions.new unless
|
49
|
+
config.respond_to? :google_cloud
|
50
|
+
config.google_cloud.error_reporting = ActiveSupport::OrderedOptions.new
|
51
|
+
|
52
|
+
initializer "Google.Cloud.ErrorReporting" do |app|
|
53
|
+
if self.class.use_error_reporting? app.config
|
54
|
+
gcp_config = app.config.google_cloud
|
55
|
+
er_config = gcp_config.error_reporting
|
56
|
+
|
57
|
+
project_id = er_config.project_id || gcp_config.project_id
|
58
|
+
keyfile = er_config.keyfile || gcp_config.keyfile
|
59
|
+
|
60
|
+
channel = self.class.grpc_channel keyfile
|
61
|
+
service_name = er_config.service_name ||
|
62
|
+
error_reporting.class.default_service_name
|
63
|
+
service_version = er_config.service_version ||
|
64
|
+
error_reporting.class.default_service_version
|
65
|
+
|
66
|
+
error_reporting =
|
67
|
+
Google::Cloud::ErrorReporting::V1beta1::ReportErrorsServiceApi.new channel: channel,
|
68
|
+
app_name: service_name,
|
69
|
+
app_version: service_version
|
70
|
+
|
71
|
+
# In later versions of Rails, ActionDispatch::DebugExceptions is
|
72
|
+
# responsible for catching exceptions. But it didn't exist until
|
73
|
+
# Rails 3.2. So we use ShowExceptions as pivot for earlier Rails.
|
74
|
+
rails_exception_middleware =
|
75
|
+
if defined? ::ActionDispatch::DebugExceptions
|
76
|
+
::ActionDispatch::DebugExceptions
|
77
|
+
else
|
78
|
+
::ActionDispatch::ShowExceptions
|
79
|
+
end
|
80
|
+
|
81
|
+
app.middleware.insert_after rails_exception_middleware,
|
82
|
+
Google::Cloud::ErrorReporting::Middleware,
|
83
|
+
project_id: project_id,
|
84
|
+
error_reporting: error_reporting,
|
85
|
+
service_name: service_name,
|
86
|
+
service_version: service_version
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Construct a gRPC Channel object from given keyfile
|
92
|
+
#
|
93
|
+
# @param [String, Hash] keyfile Keyfile downloaded from Google Cloud. If
|
94
|
+
# file path the file must be readable.
|
95
|
+
#
|
96
|
+
# @return [GRPC::Core::Channel] gRPC Channel object based on given
|
97
|
+
# keyfile
|
98
|
+
#
|
99
|
+
def self.grpc_channel keyfile = nil
|
100
|
+
require "grpc"
|
101
|
+
|
102
|
+
scopes = Google::Cloud::ErrorReporting::V1beta1::ReportErrorsServiceApi::ALL_SCOPES
|
103
|
+
credentials = if keyfile.nil?
|
104
|
+
Google::Cloud::Credentials.default(
|
105
|
+
scope: scopes)
|
106
|
+
else
|
107
|
+
Google::Cloud::Credentials.new(
|
108
|
+
keyfile, scope: scopes)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Return nil if :this_channel_is_insecure
|
112
|
+
return nil if credentials == :this_channel_is_insecure
|
113
|
+
|
114
|
+
channel_cred = GRPC::Core::ChannelCredentials.new.compose \
|
115
|
+
GRPC::Core::CallCredentials.new credentials.client.updater_proc
|
116
|
+
host = Google::Cloud::ErrorReporting::V1beta1::ReportErrorsServiceApi::SERVICE_ADDRESS
|
117
|
+
|
118
|
+
GRPC::Core::Channel.new host, nil, channel_cred
|
119
|
+
end
|
120
|
+
|
121
|
+
##
|
122
|
+
# Determine whether to use Stackdriver Error Reporting or not.
|
123
|
+
#
|
124
|
+
# Returns true if valid GCP project_id and keyfile are provided and
|
125
|
+
# either Rails is in "production" environment or \
|
126
|
+
# config.google_cloud.use_error_reporting is explicitly true. Otherwise
|
127
|
+
# false.
|
128
|
+
#
|
129
|
+
# @param config The Rails.application.config
|
130
|
+
#
|
131
|
+
# @return true or false
|
132
|
+
#
|
133
|
+
def self.use_error_reporting? config
|
134
|
+
gcp_config = config.google_cloud
|
135
|
+
er_config = gcp_config.error_reporting
|
136
|
+
|
137
|
+
# Return false if config.google_cloud.use_error_reporting is
|
138
|
+
# explicitly false
|
139
|
+
return false if gcp_config.key?(:use_error_reporting) &&
|
140
|
+
!gcp_config.use_error_reporting
|
141
|
+
|
142
|
+
# Check credentialing. Returns false if authorization errors are
|
143
|
+
# rescued.
|
144
|
+
keyfile = er_config.keyfile || gcp_config.keyfile
|
145
|
+
begin
|
146
|
+
grpc_channel keyfile
|
147
|
+
rescue Exception => e
|
148
|
+
Rails.logger.warn "Google::Cloud::ErrorReporting is not " \
|
149
|
+
"activated due to authorization error: #{e.message}"
|
150
|
+
return false
|
151
|
+
end
|
152
|
+
|
153
|
+
project_id = er_config.project_id ||
|
154
|
+
gcp_config.project_id ||
|
155
|
+
ENV["ERROR_REPORTING_PROJECT"] ||
|
156
|
+
ENV["GOOGLE_CLOUD_PROJECT"] ||
|
157
|
+
Google::Cloud::Core::Environment.project_id
|
158
|
+
if project_id.to_s.empty?
|
159
|
+
Rails.logger.warn "Google::Cloud::ErrorReporting is not " \
|
160
|
+
"activated due to empty project_id"
|
161
|
+
return false
|
162
|
+
end
|
163
|
+
|
164
|
+
# Otherwise return true if Rails is running in production or
|
165
|
+
# config.google_cloud.use_error_reporting is explicitly true
|
166
|
+
Rails.env.production? ||
|
167
|
+
(gcp_config.key?(:use_error_reporting) &&
|
168
|
+
gcp_config.use_error_reporting)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|