lib/semantic_logger/log.rb in semantic_logger-2.21.0 vs lib/semantic_logger/log.rb in semantic_logger-3.0.0

- old
+ new

@@ -62,10 +62,23 @@ ex.original_exception end end end + # Returns [String] the exception backtrace including all of the child / caused by exceptions + def backtrace_to_s + trace = '' + each_exception do |exception, i| + if i == 0 + trace = (exception.backtrace || []).join("\n") + else + trace << "\nCause: #{exception.class.name}: #{exception.message}\n#{(exception.backtrace || []).join("\n")}" + end + end + trace + end + # Returns [String] duration of the log entry as a string # Returns nil if their is no duration # Java time precision does not include microseconds if defined? JRuby def duration_to_s @@ -87,11 +100,11 @@ elsif seconds >= 3600.0 # 1 hour Time.at(seconds).strftime('%-Hh %-Mm') elsif seconds >= 60.0 # 1 minute Time.at(seconds).strftime('%-Mm %-Ss') elsif seconds >= 1.0 # 1 second - Time.at(seconds).strftime('%-Ss %Lms') + "#{'%.3f' % seconds}s" else duration_to_s end end @@ -102,22 +115,30 @@ # Returns [String] the available process info # Example: # 18934:thread 23 test_logging.rb:51 def process_info(thread_name_length = 30) - file, line = file_name_and_line + file, line = file_name_and_line(true) file_name = " #{file}:#{line}" if file "#{$$}:#{"%.#{thread_name_length}s" % thread_name}#{file_name}" end + CALLER_REGEXP = /^(.*):(\d+).*/ + + # Extract the filename and line number from the last entry in the supplied backtrace + def extract_file_and_line(stack, short_name = false) + match = CALLER_REGEXP.match(stack.first) + [short_name ? File.basename(match[1]) : match[1], match[2].to_i] + end + # Returns [String, String] the file_name and line_number from the backtrace supplied # in either the backtrace or exception - def file_name_and_line + def file_name_and_line(short_name = false) if backtrace || (exception && exception.backtrace) - stacktrace = backtrace || exception.backtrace - stacktrace[0].split('/').last.split(':')[0..1] if stacktrace && stacktrace.size > 0 + stack = backtrace || exception.backtrace + extract_file_and_line(stack, short_name) if stack && stack.size > 0 end end # Strip the standard Rails colorizing from the logged message def cleansed_message @@ -144,9 +165,68 @@ # Return the Time as a formatted string # Ruby MRI supports micro seconds def formatted_time "#{time.strftime('%Y-%m-%d %H:%M:%S')}.#{'%06d' % (time.usec)}" end + end + + # Returns [Hash] representation of this log entry + def to_h + # Header + h = { + host: SemanticLogger.host, + application: SemanticLogger.application, + name: name, + pid: $$, + thread: thread_name, + time: time, + level: level, + level_index: level_index, + } + file, line = file_name_and_line + if file + h[:file] = file + h[:line] = line.to_i + end + + # Tags + h[:tags] = tags if tags && (tags.size > 0) + + # Duration + if duration + h[:duration_ms] = duration + h[:duration] = duration_human + end + + # Log message + h[:message] = cleansed_message if message + + # Payload + if payload + if payload.is_a?(Hash) + h.merge!(payload) + else + h[:payload] = payload + end + end + + # Exceptions + if exception + root = h + each_exception do |exception, i| + name = i == 0 ? :exception : :cause + root[name] = { + name: exception.class.name, + message: exception.message, + stack_trace: exception.backtrace + } + root = root[name] + end + end + + # Metric + h[:metric] = metric if metric + h end end end