Class: Google::Cloud::ErrorReporting::Middleware

Inherits:
Object
  • Object
show all
Defined in:
lib/google/cloud/error_reporting/middleware.rb

Overview

Middleware

Google::Cloud::ErrorReporting::Middleware defines a Rack Middleware that can automatically catch upstream exceptions and report them to Stackdriver Error Reporting.

Constant Summary collapse

EXCEPTION_KEYS =
["sinatra.error", "rack.exception"].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, error_reporting: nil, **kwargs) ⇒ Google::Cloud::ErrorReporting::Middleware

Construct a new instance of Middleware.

Parameters:

  • app (Rack::Application)

    The Rack application

  • error_reporting (Google::Cloud::ErrorReporting::Project) (defaults to: nil)

    A Google::Cloud::ErrorReporting::Project client for reporting exceptions

  • kwargs (Hash)

    Hash of configuration settings. Used for backward API compatibility. See the Configuration Guide for the prefered way to set configuration parameters.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/google/cloud/error_reporting/middleware.rb', line 48

def initialize app, error_reporting: nil, **kwargs
  require "rack"
  require "rack/request"
  @app = app

  load_config kwargs

  @error_reporting =
    error_reporting ||
    ErrorReporting::AsyncErrorReporter.new(
      ErrorReporting.new(project: configuration.project_id,
                         credentials: configuration.credentials)
    )

  # Set module default client to reuse the same client. Update module
  # configuration parameters.
  ErrorReporting.class_variable_set :@@default_client, @error_reporting
end

Instance Attribute Details

#error_reportingObject (readonly)

A Google::Cloud::ErrorReporting::Project client used to report error events.



31
32
33
# File 'lib/google/cloud/error_reporting/middleware.rb', line 31

def error_reporting
  @error_reporting
end

Instance Method Details

#call(env) ⇒ Object

Implements the mandatory Rack Middleware call method.

Catch all Exceptions from upstream and report them to Stackdriver Error Reporting. Unless the exception's class is defined to be ignored by this Middleware.

Parameters:

  • env (Hash)

    Rack environment hash



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/google/cloud/error_reporting/middleware.rb', line 76

def call env
  response = @app.call env

  # sinatra doesn't always raise the Exception, but it saves it in
  # env['sinatra.error']
  #
  # some frameworks (i.e. hanami) will save a rendering exception in
  # env['rack.exception']
  EXCEPTION_KEYS.each do |exception_key|
    next unless env[exception_key].is_a? Exception

    report_exception env, env[exception_key]
  end

  response
rescue Exception => exception
  report_exception env, exception

  # Always raise exception backup
  raise exception
end

#error_event_from_exception(env, exception) ⇒ Google::Cloud::ErrorReporting::ErrorEvent

Creates a ErrorEvent based on the exception. Fill in the HttpRequestContext section of the ErrorEvent based on the HTTP Request headers.

When used in Rails environment. It replies on ActionDispatch::ExceptionWrapper class to derive a HTTP status code based on the exception's class.

Parameters:

  • env (Hash)

    Rack environment hash

  • exception (Exception)

    Exception to convert from

Returns:



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/google/cloud/error_reporting/middleware.rb', line 137

def error_event_from_exception env, exception
  error_event = ErrorReporting::ErrorEvent.from_exception exception

  # Inject service_context info into error_event object
  error_event.service_name = configuration.service_name
  error_event.service_version = configuration.service_version

  # Inject http_request_context info into error_event object
  rack_request = Rack::Request.new env
  error_event.http_method = rack_request.request_method
  error_event.http_url = rack_request.url
  error_event.http_user_agent = rack_request.user_agent
  error_event.http_referrer = rack_request.referrer
  error_event.http_status = http_status(exception)
  error_event.http_remote_ip = rack_request.ip

  error_event
end

#report_exception(env, exception) ⇒ Object

Report an given exception to Stackdriver Error Reporting.

While it reports most of the exceptions. Certain Rails exceptions that maps to a HTTP status code less than 500 will be treated as not the app fault and ignored.

Parameters:

  • env (Hash)

    Rack environment hash

  • exception (Exception)

    The Ruby exception to report.



108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/google/cloud/error_reporting/middleware.rb', line 108

def report_exception env, exception
  # Do not any exceptions that's specified by the ignore_classes list.
  return if configuration.ignore_classes.include? exception.class

  error_event = error_event_from_exception env, exception

  # If this exception maps to a HTTP status code less than 500, do
  # not report it.
  status_code = error_event.http_status.to_i
  return if status_code > 0 && status_code < 500

  error_reporting.report error_event
end