require 'spec_helper' require 'roqua/support/errors' require 'appsignal' describe 'Error reporting' do let(:exception) do Exception.new('exception_message').tap do |exception| exception.set_backtrace ['back', 'trace', 'lines'] end end let(:logstream) { StringIO.new } let(:logger) { Logger.new(logstream) } let(:logwrapper) { Roqua::LogWrapper.new(logger) } before do Rails.env = 'foo' # in test we don't log Roqua.logger = logwrapper end context 'when the Roqua logger is defined' do it 'supports default extra params' do allow(Roqua::Support::Errors).to receive(:extra_parameters).and_return(organization: 'some_org') expect(Roqua.logger).to receive(:error).with('roqua.exception', class_name: 'Exception', message: 'exception_message', backtrace: ['back', 'trace', 'lines'], parameters: {organization: 'some_org'}) Roqua::Support::Errors.report exception end it 'sends notifications to the eventlog' do expect(Roqua.logger).to receive(:error).with('roqua.exception', class_name: 'Exception', message: 'exception_message', backtrace: ['back', 'trace', 'lines'], parameters: {}) Roqua::Support::Errors.report exception end it 'skips the backtrace when the skip_backtrace flag is set' do expect(Roqua.logger).to receive(:error).with('roqua.exception', class_name: 'Exception', message: 'exception_message', parameters: {}) Roqua::Support::Errors.report exception, skip_backtrace: true end it 'can add extra parameters by calling add_parameters' do expect(Roqua.logger).to receive(:error).with \ 'roqua.exception', class_name: 'RuntimeError', message: 'exception_message', parameters: {more: 'params', even_more: 'params'} begin begin begin fail 'exception_message' rescue Roqua::Support::Errors.add_parameters(more: 'params') raise end rescue Roqua::Support::Errors.add_parameters(even_more: 'params') raise end rescue => e Roqua::Support::Errors.report e, skip_backtrace: true end end it 'will not fail when called outside of rescue or when passed the wrong format to add_parameters' do expect(Roqua.logger).to receive(:error).with \ 'roqua.exception', class_name: 'RuntimeError', message: 'exception_message', parameters: {} begin Roqua::Support::Errors.add_parameters('just a string') begin fail 'exception_message' rescue Roqua::Support::Errors.add_parameters('just a string') raise end rescue => e Roqua::Support::Errors.report e, skip_backtrace: true end end end context 'when Appsignal is loaded' do let(:agent) { double("agent") } let(:transaction) { double("transaction") } before do Appsignal.config = Appsignal::Config.new(Dir.pwd, "test") allow(Appsignal).to receive(:active?).and_return(true) allow(Appsignal).to receive(:agent).and_return(agent) end it 'it will send an error' do expect(Appsignal).to receive(:send_error) Roqua::Support::Errors.report exception end it 'defaults to a background job' do transaction = Appsignal::Transaction.new(SecureRandom.uuid, Appsignal::Transaction::FRONTEND, nil) expect(Appsignal).to receive(:send_error).with(exception).and_yield(transaction) Roqua::Support::Errors.report exception expect(transaction.namespace).to eq Appsignal::Transaction::BACKGROUND_JOB end it 'it will send an error under the provided category' do transaction = Appsignal::Transaction.new(SecureRandom.uuid, Appsignal::Transaction::FRONTEND, nil) expect(Appsignal) .to receive(:send_error) .with(exception).and_yield(transaction) Roqua::Support::Errors.report exception, a: 'b', namespace: :web expect(transaction.namespace).to eq Appsignal::Transaction::HTTP_REQUEST expect(transaction.tags).to eq a: 'b' end describe 'when a current transaction is present' do let(:current_transaction) do Appsignal::Transaction.new(SecureRandom.uuid, Appsignal::Transaction::HTTP_REQUEST, nil) end before do expect(Appsignal::Transaction).to receive(:current).at_least(:once).and_return(current_transaction) end it 'sets the correct properties if a current transaction is present' do expect(current_transaction).to receive(:set_tags).with(a: 'b').and_call_original expect(current_transaction).to receive(:add_exception).with(exception).and_call_original Roqua::Support::Errors.report exception, a: 'b', namespace: :web end describe "if the current transaction isn't a http request" do let(:current_transaction) do Appsignal::Transaction.new(SecureRandom.uuid, Appsignal::Transaction::BACKGROUND_JOB, nil) end it "will not set the properties if the current transaction isn't a http request" do expect(current_transaction).to_not receive(:set_tags) expect(current_transaction).to_not receive(:add_exception) Roqua::Support::Errors.report exception, a: 'b', namespace: :web end end end end context '.appsignal_namespace_for_category' do it 'returns the correct string based on the category' do expect(Roqua::Support::Errors.appsignal_namespace_for_category(:background)) .to eql(Appsignal::Transaction::BACKGROUND_JOB) expect(Roqua::Support::Errors.appsignal_namespace_for_category(:web)) .to eql(Appsignal::Transaction::HTTP_REQUEST) expect(Roqua::Support::Errors.appsignal_namespace_for_category('')) .to eql(Appsignal::Transaction::BLANK) end end end