Skip to content

Commit c6a5037

Browse files
authored
Merge pull request #178 from nikz/support-rails-error-handle
Adds support for Rails' new error handling API
2 parents ec3d176 + 630ba91 commit c6a5037

File tree

13 files changed

+140
-23
lines changed

13 files changed

+140
-23
lines changed

lib/raygun.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
require "raygun/middleware/breadcrumbs_store_initializer"
1515
require "raygun/middleware/javascript_exception_tracking"
1616
require "raygun/demo_exception"
17+
require "raygun/error_subscriber"
1718
require "raygun/error"
1819
require "raygun/affected_user"
1920
require "raygun/services/apply_whitelist_filter_to_payload"
@@ -64,11 +65,13 @@ def track_exception(exception_instance, env = {}, user = nil, retry_count = 1)
6465

6566
exception_instance.set_backtrace(caller) if exception_instance.is_a?(Exception) && exception_instance.backtrace.nil?
6667

67-
if configuration.send_in_background
68+
result = if configuration.send_in_background
6869
track_exception_async(exception_instance, env, user, retry_count)
6970
else
7071
track_exception_sync(exception_instance, env, user, retry_count)
7172
end
73+
74+
result
7275
end
7376

7477
def track_exceptions
@@ -136,6 +139,8 @@ def track_exception_async(exception_instance, env, user, retry_count)
136139
@@active_futures.delete(future)
137140
end, :call)
138141
@@active_futures << future
142+
143+
future
139144
end
140145

141146
def track_exception_sync(exception_instance, env, user, retry_count)

lib/raygun/breadcrumbs/store.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ def self.should_record?(crumb)
7171
levels = Raygun::Breadcrumbs::BREADCRUMB_LEVELS
7272

7373
active_level = levels.index(Raygun.configuration.breadcrumb_level)
74-
puts crumb.inspect if crumb.is_a?(Array)
7574
crumb_level = levels.index(crumb.level) || -1
7675

7776
discard = crumb_level < active_level

lib/raygun/client.rb

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,9 @@ def build_payload_hash(exception_instance, env = {}, user = nil)
221221

222222
# If we have breadcrumbs passed to us as context from another thread, then include them
223223
# Otherwise, use the default store (which is thread-local)
224-
store = if env.key?(:rg_breadcrumb_store)
225-
::Raygun::Breadcrumbs::Store.initialize(with: env.delete(:rg_breadcrumb_store))
226-
else
227-
::Raygun::Breadcrumbs::Store
228-
end
224+
::Raygun::Breadcrumbs::Store.initialize(with: env.delete(:rg_breadcrumb_store)) if env.key?(:rg_breadcrumb_store)
229225

226+
store = ::Raygun::Breadcrumbs::Store
230227
error_details[:breadcrumbs] = store.take_until_size(MAX_BREADCRUMBS_SIZE).map(&:build_payload) if store.any?
231228

232229
Raygun.log('set details and breadcrumbs')

lib/raygun/configuration.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ def self.proc_config_option(name)
8686
# How long to wait for the POST request to the API server before timing out
8787
config_option :error_report_send_timeout
8888

89+
# Should we register an error handler with [Rails' built in API](https://edgeguides.rubyonrails.org/error_reporting.html)
90+
config_option :register_rails_error_handler
91+
8992
# Exception classes to ignore by default
9093
IGNORE_DEFAULT = ['ActiveRecord::RecordNotFound',
9194
'ActionController::RoutingError',

lib/raygun/error_subscriber.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Subscribes to errors using Rails' error reporting API
2+
# https://edgeguides.rubyonrails.org/error_reporting.html
3+
class Raygun::ErrorSubscriber
4+
def report(error, handled:, severity:, context:, source: nil)
5+
tags = context.delete(:tags) if context.is_a?(Hash)
6+
7+
data = {
8+
custom_data: {
9+
"rails.error": {
10+
handled: handled,
11+
severity: severity,
12+
context: context,
13+
source: source
14+
},
15+
},
16+
tags: ["rails_error_reporter", *tags].compact
17+
}
18+
19+
Raygun.track_exception(error, data)
20+
end
21+
end

lib/raygun/railtie.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,17 @@ class Raygun::Railtie < Rails::Railtie
3131
config.to_prepare do
3232
Raygun.default_configuration.logger = Rails.logger
3333
Raygun.default_configuration.enable_reporting = Rails.env.production?
34+
35+
Raygun::Railtie.setup_error_subscriber
3436
end
3537

3638
rake_tasks do
3739
load "tasks/raygun.tasks"
3840
end
41+
42+
def self.setup_error_subscriber
43+
if ::Rails.version.to_f >= 7.0 && Raygun.configuration.register_rails_error_handler
44+
Rails.error.subscribe(Raygun::ErrorSubscriber.new)
45+
end
46+
end
3947
end

test/rails_helper.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
ENV['RAILS_ENV'] ||= 'test'
2+
require "rails"
3+
4+
major_minor_patch = Rails::VERSION::STRING.split(".").first(3).join(".")
5+
6+
require_relative "../spec/rails_applications/#{major_minor_patch}/config/environment"

test/test_helper.rb

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
ENV['RACK_ENV'] = 'test'
2-
require_relative "../lib/raygun.rb"
32
require "minitest/autorun"
43
require "minitest/pride"
54
require "timecop"
65
require "mocha/minitest"
7-
require 'stringio'
8-
require 'webmock/minitest'
6+
require "stringio"
7+
require "webmock/minitest"
8+
9+
require_relative "./rails_helper"
10+
require_relative "../lib/raygun.rb"
11+
12+
# Ensure we start with a known state
13+
Raygun.reset_configuration
914

1015
class FakeLogger
1116
def initialize
@@ -40,6 +45,8 @@ def setup
4045
end
4146

4247
def teardown
48+
Raygun.wait_for_futures
49+
Raygun.reset_configuration
4350
end
4451

4552
end
@@ -51,17 +58,14 @@ def setup
5158
end
5259

5360
def teardown
54-
reset_configuration
61+
Raygun.wait_for_futures
62+
Raygun.reset_configuration
5563
end
5664

5765
def fake_successful_entry
5866
stub_request(:post, 'https://api.raygun.com/entries').to_return(status: 202)
5967
end
6068

61-
def reset_configuration
62-
Raygun.configuration = Raygun::Configuration.new
63-
end
64-
6569
def setup_logging
6670
logger = FakeLogger.new
6771
Raygun.configuration.debug = true

test/unit/configuration_test.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ def setup
1212
end
1313
end
1414

15-
def teardown
16-
Raygun.reset_configuration
17-
end
18-
1915
def test_setting_api_key_and_version
2016
assert_equal 9.9, Raygun.configuration.version
2117
assert_equal "a test api key", Raygun.configuration.api_key

test/unit/error_subscriber_test.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
require_relative "../test_helper.rb"
2+
3+
class ErrorSubscriberTest < Raygun::UnitTest
4+
5+
def setup
6+
super
7+
Raygun.configuration.send_in_background = false
8+
end
9+
10+
11+
def test_tracking_exception_via_subscriber
12+
body_matcher = lambda do |body|
13+
json = JSON.parse(body)
14+
details = json["details"]
15+
16+
details["userCustomData"] &&
17+
details["userCustomData"]["rails.error"] &&
18+
details["userCustomData"]["rails.error"]["handled"] == true &&
19+
details["tags"] == ["rails_error_reporter", "test_tag", "test"]
20+
end
21+
22+
request_stub = stub_request(:post, 'https://api.raygun.com/entries')
23+
.with(
24+
body: body_matcher
25+
)
26+
.to_return(status: 202).times(1)
27+
28+
result = Raygun::ErrorSubscriber.new.report(
29+
StandardError.new("test error"),
30+
handled: true,
31+
severity: "warning",
32+
context: {
33+
tags: ["test_tag"]
34+
},
35+
source: "application"
36+
)
37+
38+
assert result && result.success?, "Expected success, got #{result.class}, #{result.inspect}"
39+
40+
assert_requested request_stub
41+
end
42+
43+
end

0 commit comments

Comments
 (0)