Module: FormatException

Defined in:
lib/format_exception.rb,
lib/format_exception/version.rb

Overview

Simple exception formatter

Provides utility methods for formatting an exception as a String.

Examples:

The contextual clean format


require "logger"
require "format_exception"

logger = Logger.new($stderr)
begin
  File.open("message.txt", "r") do |io|
    puts io.read
  end
rescue IOError => ex
  logger.error(FormatException[ex, "Printing welcome message"])
end

# Prints
#
# E, [2017-02-11T01:56:08.763049 #4302] ERROR -- : Printing welcome message: Errno::ENOENT: No such file or directory @ rb_sysopen - message.txt:
#         foo.rb:10:in `initialize'
#         foo.rb:10:in `open'
#         foo.rb:10:in `<main>'

Constant Summary collapse

CLASSIC_FORMAT =

The classic format (see classic)

"%f: %:m%M (%C)\n%R"
CLEAN_FORMAT =

The clean format (see clean)

"%:m%C: %M:\n%B"
VERSION =
"0.2.2"

Class Method Summary collapse

Class Method Details

.[](e, context_message = nil) ⇒ Object

Alias for clean



45
46
47
# File 'lib/format_exception.rb', line 45

def self.[](e, context_message = nil)
  clean(e, context_message)
end

.classic(e, context_message = nil) ⇒ String

The Ruby interpreter’s default format

Formats the exception exactly as the Ruby interpreter would if the exception was uncaught. The first line includes the first line of the backtrace, and the exception message and class name, with the rest of the backtrace on subsequent, indented lines.

If the context_message is given, it is included on the first line, between the first line of the backtrace and the exception message.

Parameters:

  • e (Exception)

    the exception to format

  • context_message (String) (defaults to: nil)

    the additional message to include in the formatted exception

Returns:

  • (String)

    the formatted exception



66
67
68
# File 'lib/format_exception.rb', line 66

def self.classic(e, context_message = nil)
  format(CLASSIC_FORMAT, e, context_message)
end

.clean(e, context_message = nil) ⇒ String

The log-friendly format

Formats the exception as the Rails logger would, with the exception class name and message on the first line, with the backtrace on subsequent, indented lines.

If the context_message is given, it is prepended to the first line.

Parameters:

  • e (Exception)

    the exception to format

  • context_message (String) (defaults to: nil)

    the additional message to prepend to the formatted exception

Returns:

  • (String)

    the formatted exception



84
85
86
# File 'lib/format_exception.rb', line 84

def self.clean(e, context_message = nil)
  format(CLEAN_FORMAT, e, context_message)
end

.format(f, e, c = nil) ⇒ Object

Format exception as per printf-like format specifier

The following format specifiers are supported:

  • %C - the exception class name

  • %M - the exception message

  • %m - the context message if given

  • %:m - the context message, a colon and a space, if the context message is given

  • %f - the first line of the backtrace, unindented

  • %r - all lines of the backtrace but the first, newline-separated, unindented

  • %R - all lines of the backtrace but the first, newline-separated, indented

  • %b - all lines of the backtrace, newline-separated, unindented

  • %B - all lines of the backtrace, newline-separated, indented

  • %% - a literal %



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/format_exception.rb', line 104

def self.format(f, e, c = nil)
  scanner = StringScanner.new(f)
  formatted = ""
  loop do
    formatted << scanner.scan(/[^%]*/)
    token = scanner.scan(/%:?./)
    case token
    when "%C" then formatted << e.class.to_s
    when "%M" then formatted << e.message
    when "%m" then formatted << c if c
    when "%:m" then formatted << "#{c}: " if c
    when "%f" then formatted << e.backtrace.first
    when "%r" then formatted << e.backtrace.drop(1).join("\n")
    when "%R" then formatted << ("\t" + e.backtrace.drop(1).join("\n\t"))
    when "%b" then formatted << e.backtrace.join("\n")
    when "%B" then formatted << ("\t" + e.backtrace.join("\n\t"))
    when "%%" then formatted << "%"
    when nil then break
    else
      raise ArgumentError, "unknown format specifier '#{scanner.matched}'"
    end
    break if scanner.eos?
  end
  formatted
end