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
# 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.default_reporter do
      ErrorReporting::AsyncErrorReporter.new(
        ErrorReporting.new(project: configuration.project_id,
                           credentials: configuration.credentials)
      )
    end
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



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

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 => e
  report_exception env, e

  # Always raise exception backup
  raise e
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:



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

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.



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

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.positive? && status_code < 500

  error_reporting.report error_event
end