1
0
mirror of https://github.com/meineerde/rackstash.git synced 2025-10-17 14:01:01 +00:00

Add Rackstash::Logger#add_exception to easily add details about exceptions as buffer fields

This commit is contained in:
Holger Just 2017-07-20 23:06:23 +02:00
parent d9ea199d4f
commit 25dfa87de7
3 changed files with 101 additions and 0 deletions

View File

@ -73,6 +73,10 @@ module Rackstash
FIELD_TIMESTAMP = '@timestamp'.freeze
FIELD_VERSION = '@version'.freeze
FIELD_ERROR = 'error'.freeze
FIELD_ERROR_MESSAGE = 'error_message'.freeze
FIELD_ERROR_TRACE = 'error_trace'.freeze
def self.severity_label(severity)
if severity.is_a?(Integer)
return SEVERITY_LABELS.last if severity < 0

View File

@ -272,6 +272,37 @@ module Rackstash
end
alias log add
# Extract useful data from an exception and add it to fields of the buffer
# for structured logging. The following fields will be set:
#
# * `error` - The class name of the exception
# * `error_message` - The exception's message
# * `error_trace` - The backtrace of the exception, one frame per line
#
# The exception will not be added to the buffer's `message` field.
# Log it manually with {#add} if desired.
#
# By default, the details of subsequent exceptions will overwrite those of
# older exceptions in the current buffer. Only by the `force` argument to
# `false`, we will preserve existing exceptions.
#
# @param exception [Exception] an Exception object as catched by `rescue`
# @param force [Boolean] set to `false` to preserve the details of an
# existing exception in the current buffer's fields, set to `true` to
# overwrite them.
# @return [Exception] the passed `exception`
def add_exception(exception, force: true)
return exception if !force && buffer.fields[FIELD_ERROR]
exception_fields = {
FIELD_ERROR => exception.class.name,
FIELD_ERROR_MESSAGE => exception.message,
FIELD_ERROR_TRACE => (exception.backtrace || []).join("\n")
}
buffer.fields.merge!(exception_fields)
exception
end
# Create a new buffering {Buffer} and puts in on the {BufferStack} for the
# current Thread. For the duration of the block, all new logged messages
# and any access to fields and tags will be sent to this new buffer.

View File

@ -401,6 +401,72 @@ describe Rackstash::Logger do
end
end
describe '#add_exception' do
let(:fields) { Rackstash::Fields::Hash.new }
before(:each) do
buffer = instance_double('Rackstash::Buffer')
allow(buffer).to receive(:fields).and_return(fields)
allow(logger).to receive(:buffer).and_return(buffer)
end
it 'adds the exception fields' do
begin
raise 'My Error'
rescue => e
logger.add_exception(e)
end
expect(fields['error']).to eql 'RuntimeError'
expect(fields['error_message']).to eql 'My Error'
expect(fields['error_trace']).to match %r{\A#{__FILE__}:#{__LINE__ - 7}:in}
end
it 'does not require a backtrace' do
logger.add_exception(StandardError.new('Error'))
expect(fields['error']).to eql 'StandardError'
expect(fields['error_message']).to eql 'Error'
expect(fields['error_trace']).to eql ''
end
context 'with force: true' do
it 'overwrites exceptions' do
begin
raise 'Error'
rescue => first
logger.add_exception(first, force: true)
end
begin
raise TypeError, 'Another Error'
rescue => second
logger.add_exception(second, force: true)
end
expect(fields['error']).to eql 'TypeError'
expect(fields['error_message']).to eql 'Another Error'
expect(fields['error_trace']).to match %r{\A#{__FILE__}:#{__LINE__ - 7}:in}
end
end
context 'with force: false' do
it 'does not overwrite exceptions' do
fields['error'] = 'Something is wrong'
begin
raise TypeError, 'Error'
rescue => second
logger.add_exception(second, force: false)
end
expect(fields['error']).to eql 'Something is wrong'
expect(fields['error_message']).to be_nil
expect(fields['error_trace']).to be_nil
end
end
end
describe '#with_buffer' do
it 'requires a block' do
expect { logger.with_buffer }.to raise_error ArgumentError