diff --git a/docs/config.rst b/docs/config.rst index f194d9997..9776e9d24 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -23,8 +23,10 @@ Optional settings Thread.new { Raven.send_event(event) } } - Using a thread to send events will be adequate for truly parallel Ruby platforms such as JRuby, though the benefit on MRI/CRuby will be limited. + Using a thread to send events will be adequate for truly parallel Ruby platforms such as JRuby, though the benefit on MRI/CRuby will be limited. Threads also won't report any exceptions raised inside of them, so be careful! + If the async callback raises an exception, Raven will attempt to send synchronously. + We recommend creating a background job, using your background job processor, that will send Sentry notifications in the background. Rather than enqueuing an entire Raven::Event object, we recommend providing the Hash representation of an event as a job argument. Here's an example for ActiveJob: .. code-block:: ruby @@ -96,7 +98,7 @@ Optional settings If you need to sanitize or pre-process (before its sent to the server) data, you can do so using the Processors implementation. By default, a few processors are installed. The most important is ``Raven::Processor::SanitizeData``, which will attempt to sanitize keys that match various patterns (e.g. password) and values that resemble credit card numbers. In your Sentry UI, data which has been sanitized will appear as "********" (or 0, if the value was an Integer). - + To specify your own (or to remove the defaults), simply pass them with your configuration: .. code-block:: ruby diff --git a/lib/raven/instance.rb b/lib/raven/instance.rb index 5a2cd748b..279cc197b 100644 --- a/lib/raven/instance.rb +++ b/lib/raven/instance.rb @@ -119,7 +119,12 @@ def capture_type(obj, options = {}) if (evt = Event.send("from_" + message_or_exc, obj, options)) yield evt if block_given? if configuration.async? - configuration.async.call(evt) + begin + configuration.async.call(evt) + rescue => ex + Raven.logger.error("async event sending failed: #{ex.message}") + send_event(evt) + end else send_event(evt) end diff --git a/spec/raven/instance_spec.rb b/spec/raven/instance_spec.rb index 05332f461..fbdee6dd4 100644 --- a/spec/raven/instance_spec.rb +++ b/spec/raven/instance_spec.rb @@ -88,24 +88,42 @@ describe 'as #capture_exception when async' do let(:exception) { build_exception } - around do |example| - prior_async = subject.configuration.async - subject.configuration.async = proc { :ok } - example.run - subject.configuration.async = prior_async + context "when correctly configured" do + around do |example| + prior_async = subject.configuration.async + subject.configuration.async = proc { :ok } + example.run + subject.configuration.async = prior_async + end + + it 'sends the result of Event.capture_exception' do + expect(Raven::Event).to receive(:from_exception).with(exception, options) + expect(subject).not_to receive(:send_event).with(event) + + expect(subject.configuration.async).to receive(:call).with(event) + subject.capture_type(exception, options) + end + + it 'returns the generated event' do + returned = subject.capture_type(exception, options) + expect(returned).to eq(event) + end end - it 'sends the result of Event.capture_exception' do - expect(Raven::Event).to receive(:from_exception).with(exception, options) - expect(subject).not_to receive(:send_event).with(event) + context "when async raises an exception" do + around do |example| + prior_async = subject.configuration.async + subject.configuration.async = proc { raise TypeError } + example.run + subject.configuration.async = prior_async + end - expect(subject.configuration.async).to receive(:call).with(event) - subject.capture_type(exception, options) - end + it 'sends the result of Event.capture_exception via fallback' do + expect(Raven::Event).to receive(:from_exception).with(exception, options) - it 'returns the generated event' do - returned = subject.capture_type(exception, options) - expect(returned).to eq(event) + expect(subject).to receive(:send_event).with(event) + subject.capture_type(exception, options) + end end end