diff --git a/.reek.yml b/.reek.yml index 279e5dc..d6c82d7 100644 --- a/.reek.yml +++ b/.reek.yml @@ -20,6 +20,7 @@ detectors: enabled: true exclude: - ExceptionHunter::ErrorCreator + - ExceptionHunter::Tracking max_copies: 2 min_clump_size: 2 diff --git a/CHANGELOG.md b/CHANGELOG.md index bb8b68a..c88d8dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ ### New features - [#113](https://github.com/rootstrap/exception_hunter/pull/113) Add configuration to turn on/off async logging using ActionJob. ( - [@matteo95g][]) + [@matteo95g][]) +- [#119](https://github.com/rootstrap/exception_hunter/pull/119) Add support for tracking manual exceptions within transactions. ([@lalopsb][]) ### Bug fixes diff --git a/lib/exception_hunter/tracking.rb b/lib/exception_hunter/tracking.rb index 0eb4e4b..c34a04f 100644 --- a/lib/exception_hunter/tracking.rb +++ b/lib/exception_hunter/tracking.rb @@ -19,6 +19,26 @@ module Tracking # @param [User] user in the current session. (optional) # @return [void] def track(exception, custom_data: {}, user: nil) + if open_transactions? + create_error_within_new_thread(exception, custom_data, user) + else + create_error(exception, custom_data, user) + end + + nil + end + + private + + def create_error_within_new_thread(exception, custom_data, user) + Thread.new { + ActiveRecord::Base.connection_pool.with_connection do + create_error(exception, custom_data, user) + end + }.join + end + + def create_error(exception, custom_data, user) ErrorCreator.call( tag: ErrorCreator::MANUAL_TAG, class_name: exception.class.to_s, @@ -28,8 +48,10 @@ def track(exception, custom_data: {}, user: nil) user: user, environment_data: {} ) + end - nil + def open_transactions? + ActiveRecord::Base.connection.open_transactions.positive? end end end diff --git a/spec/exception_hunter_spec.rb b/spec/exception_hunter_spec.rb index e6fb09b..692387d 100644 --- a/spec/exception_hunter_spec.rb +++ b/spec/exception_hunter_spec.rb @@ -17,6 +17,8 @@ module ExceptionHunter let(:user) { OpenStruct.new(id: 3, email: 'example@example.com', name: 'John') } context 'when tracking is enabled' do + before { allow(ActiveRecord::Base.connection).to receive(:open_transactions).and_return(0) } + let(:error) { Error.last } it 'creates a new error' do @@ -55,6 +57,24 @@ module ExceptionHunter expect(error.error_group.tags).to eq(['Manual']) end + + it ' does not create a new thread' do + expect(Thread).to_not receive(:new) + + subject + end + + context 'when the error is tracked within a transaction' do + before do + allow(ActiveRecord::Base.connection).to receive(:open_transactions).and_return(1) + allow(Thread).to receive(:new).and_call_original + end + + it 'creates a new error within a new thread' do + expect { subject }.to change(Error, :count).by(1) + expect(Thread).to have_received(:new) + end + end end context 'when tracking is disabled' do