Module: Tinymon::Stacktrace
- Defined in:
- lib/tinymon/stacktrace.rb
Overview
Convert a Ruby Exception’s backtrace into wire-format stack frames.
Wire format wants frames ordered deepest-LAST. Ruby’s #backtrace returns them deepest-FIRST (raise site first, then callers), so we reverse.
Constant Summary collapse
- GEM_MARKER =
Falsy heuristic: a frame is NOT in_app if its path lives inside a gem directory, the Ruby stdlib, or is a built-in (‘<internal:…>`).
"/gems/"- INTERNAL_PREFIX =
"<"- STDLIB_PATH =
RbConfig::CONFIG["rubylibdir"].to_s
- BT_LINE =
Match strings like:
"path/to/file.rb:123:in `method_name'" "path/to/file.rb:123:in 'method_name'" /\A(.+?):(\d+)(?::in [`'](.+?)')?\z/.freeze
Class Method Summary collapse
- .from_location(loc) ⇒ Object
- .in_app?(path) ⇒ Boolean
- .parse(exception) ⇒ Object
- .parse_string(line) ⇒ Object
Class Method Details
.from_location(loc) ⇒ Object
40 41 42 43 44 45 46 47 48 49 |
# File 'lib/tinymon/stacktrace.rb', line 40 def from_location(loc) path = loc.path.to_s { "filename" => path, "function" => (loc.base_label || loc.label || "<anonymous>").to_s, "lineno" => loc.lineno.to_i, "colno" => 0, "in_app" => in_app?(path), } end |
.in_app?(path) ⇒ Boolean
69 70 71 72 73 74 75 |
# File 'lib/tinymon/stacktrace.rb', line 69 def in_app?(path) return false if path.nil? || path.empty? return false if path.start_with?(INTERNAL_PREFIX) return false if path.include?(GEM_MARKER) return false if !STDLIB_PATH.empty? && path.start_with?(STDLIB_PATH) true end |
.parse(exception) ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/tinymon/stacktrace.rb', line 19 def parse(exception) return [] unless exception locations = nil begin locations = exception.backtrace_locations rescue StandardError locations = nil end if locations && !locations.empty? frames = locations.map { |loc| from_location(loc) } else bt = exception.backtrace || [] frames = bt.map { |line| parse_string(line) }.compact end # Ruby gives deepest-first; wire format wants deepest-LAST. frames.reverse end |
.parse_string(line) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/tinymon/stacktrace.rb', line 56 def parse_string(line) m = BT_LINE.match(line.to_s) return nil unless m filename = m[1] { "filename" => filename, "function" => (m[3] || "<anonymous>"), "lineno" => m[2].to_i, "colno" => 0, "in_app" => in_app?(filename), } end |