lib/semantic_logger/base.rb in semantic_logger-2.16.0 vs lib/semantic_logger/base.rb in semantic_logger-2.17.0
- old
+ new
@@ -312,11 +312,14 @@
# exception
# Ruby Exception object to log
#
# metric [Object]
# Object supplied when benchmark_x was called
- Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags, :level_index, :exception, :metric)
+ #
+ # backtrace [Array<String>]
+ # The backtrace captured at source when the log level >= SemanticLogger.backtrace_level
+ Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags, :level_index, :exception, :metric, :backtrace)
# Whether to log the supplied message based on the current filter if any
def include_message?(struct)
return true if @filter.nil?
@@ -327,18 +330,22 @@
end
end
# Log message at the specified level
def log_internal(level, index, message=nil, payload=nil, exception=nil, &block)
+ # Detect exception being logged
if exception.nil? && payload.nil? && message.kind_of?(Exception)
exception = message
message = exception.inspect
- elsif exception.nil? && payload && payload.is_a?(Exception)
+ elsif exception.nil? && payload && payload.respond_to?(:backtrace) && payload.respond_to?(:message)
+ # Under JRuby a java exception is not a Ruby Exception
+ # Java::JavaLang::ClassCastException.new.is_a?(Exception) => false
exception = payload
payload = nil
end
+ # Add result of block as message or payload if not nil
if block && (result = block.call)
if result.is_a?(String)
message = message.nil? ? result : "#{message} -- #{result}"
elsif payload && payload.respond_to?(:merge)
payload.merge(result)
@@ -349,17 +356,28 @@
# Add scoped payload
if self.payload
payload = payload.nil? ? self.payload : self.payload.merge(payload)
end
- struct = Log.new(level, Thread.current.name, name, message, payload, Time.now, nil, tags, index, exception)
+
+ # Add caller stack trace
+ backtrace =
+ if !exception && (index >= SemanticLogger.backtrace_level_index)
+ trace = caller
+ # Remove call to this internal method
+ trace.shift(1)
+ trace
+ end
+
+ struct = Log.new(level, Thread.current.name, name, message, payload, Time.now, nil, tags, index, exception, nil, backtrace)
log(struct) if include_message?(struct)
end
# Measure the supplied block and log the message
def benchmark_internal(level, index, message, params, &block)
- start = Time.now
+ start = Time.now
+ exception = nil
begin
if block
result =
if silence_level = params[:silence]
# In case someone accidentally sets `silence: true` instead of `silence: :error`
@@ -392,10 +410,11 @@
if self.payload
payload = payload.nil? ? self.payload : self.payload.merge(payload)
end
if exception
logged_exception = exception
+ backtrace = nil
case log_exception
when :full
# On exception change the log level
if on_exception_level
level = on_exception_level
@@ -407,19 +426,32 @@
level = on_exception_level
index = SemanticLogger.level_to_index(level)
end
message = "#{message} -- Exception: #{exception.class}: #{exception.message}"
logged_exception = nil
+ backtrace = exception.backtrace
else
# Log the message with its duration but leave out the exception that was raised
logged_exception = nil
+ backtrace = exception.backtrace
end
- struct = Log.new(level, Thread.current.name, name, message, payload, end_time, duration, tags, index, logged_exception, metric)
+ struct = Log.new(level, Thread.current.name, name, message, payload, end_time, duration, tags, index, logged_exception, metric, backtrace)
log(struct) if include_message?(struct)
raise exception
elsif duration >= min_duration
# Only log if the block took longer than 'min_duration' to complete
- struct = Log.new(level, Thread.current.name, name, message, payload, end_time, duration, tags, index, nil, metric)
+ # Add caller stack trace
+ backtrace =
+ if index >= SemanticLogger.backtrace_level_index
+ trace = caller
+ # Remove call to this internal method
+ trace.shift
+ # Ruby 1.9 has additional stack entry for parent that calls this method
+ trace.shift if RUBY_VERSION.to_f <= 2.0
+ trace
+ end
+
+ struct = Log.new(level, Thread.current.name, name, message, payload, end_time, duration, tags, index, nil, metric, backtrace)
log(struct) if include_message?(struct)
end
end
end