module Airbrake::Backtrace
Represents a cross-Ruby backtrace from exceptions (including JRuby Java exceptions). Provides information about stack frames (such as line number, file and method) in convenient for Airbrake format.
@example
begin raise 'Oops!' rescue Backtrace.parse($!, Logger.new(STDOUT)) end
@api private @since v1.0.0
Constants
- CODE_FRAME_LIMIT
@return [Integer] how many first frames should include code hunks
Public Class Methods
java_exception?(exception)
click to toggle source
Checks whether the given exception was generated by JRuby's VM.
@param [Exception] exception @return [Boolean]
# File lib/airbrake-ruby/backtrace.rb, line 119 def self.java_exception?(exception) if defined?(Java::JavaLang::Throwable) && exception.is_a?(Java::JavaLang::Throwable) return true end return false unless exception.respond_to?(:backtrace) (Patterns::JAVA =~ exception.backtrace.first) != nil end
parse(config, exception)
click to toggle source
Parses an exception's backtrace.
@param [Exception] exception The exception, which contains a backtrace to
parse
@return [Array<Hash{Symbol=>String,Integer}>] the parsed backtrace
# File lib/airbrake-ruby/backtrace.rb, line 109 def self.parse(config, exception) return [] if exception.backtrace.nil? || exception.backtrace.none? parse_backtrace(config, exception) end
Private Class Methods
best_regexp_for(exception)
click to toggle source
# File lib/airbrake-ruby/backtrace.rb, line 133 def best_regexp_for(exception) if java_exception?(exception) Patterns::JAVA elsif oci_exception?(exception) Patterns::OCI elsif execjs_exception?(exception) Patterns::EXECJS else Patterns::RUBY end end
execjs_exception?(exception)
click to toggle source
rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
# File lib/airbrake-ruby/backtrace.rb, line 150 def execjs_exception?(exception) return false unless defined?(ExecJS::RuntimeError) return true if exception.is_a?(ExecJS::RuntimeError) if Airbrake::RUBY_20 # Ruby <2.1 doesn't support Exception#cause. We work around this by # parsing backtraces. It's slow, so we check only a few first frames. exception.backtrace[0..2].each do |frame| return true if frame =~ Patterns::EXECJS_SIMPLIFIED end elsif exception.cause && exception.cause.is_a?(ExecJS::RuntimeError) return true end false end
match_frame(regexp, stackframe)
click to toggle source
# File lib/airbrake-ruby/backtrace.rb, line 184 def match_frame(regexp, stackframe) match = regexp.match(stackframe) return match if match Patterns::GENERIC.match(stackframe) end
oci_exception?(exception)
click to toggle source
# File lib/airbrake-ruby/backtrace.rb, line 145 def oci_exception?(exception) defined?(OCIError) && exception.is_a?(OCIError) end
parse_backtrace(config, exception)
click to toggle source
# File lib/airbrake-ruby/backtrace.rb, line 191 def parse_backtrace(config, exception) regexp = best_regexp_for(exception) root_directory = config.root_directory.to_s exception.backtrace.map.with_index do |stackframe, i| frame = stack_frame(config, regexp, stackframe) next(frame) if config.code_hunks.nil? || frame[:file].nil? if !root_directory.empty? populate_code(config, frame) if frame[:file].start_with?(root_directory) elsif i < CODE_FRAME_LIMIT populate_code(config, frame) end frame end end
populate_code(config, frame)
click to toggle source
# File lib/airbrake-ruby/backtrace.rb, line 209 def populate_code(config, frame) code = Airbrake::CodeHunk.new(config).get(frame[:file], frame[:line]) frame[:code] = code if code end
stack_frame(config, regexp, stackframe)
click to toggle source
rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
# File lib/airbrake-ruby/backtrace.rb, line 168 def stack_frame(config, regexp, stackframe) if (match = match_frame(regexp, stackframe)) return { file: match[:file], line: (Integer(match[:line]) if match[:line]), function: match[:function] } end config.logger.error( "can't parse '#{stackframe}' (please file an issue so we can fix " \ "it: https://github.com/airbrake/airbrake-ruby/issues/new)" ) { file: nil, line: nil, function: stackframe } end