class Bugsnag::CodeExtractor
@api private
Constants
- MAXIMUM_LINES_TO_KEEP
Public Class Methods
new(configuration)
click to toggle source
@param configuration [Configuration]
# File lib/bugsnag/code_extractor.rb, line 8 def initialize(configuration) @files = {} @configuration = configuration end
Public Instance Methods
add_file(path, trace)
click to toggle source
Add a file and its corresponding trace hash to be processed.
@param path [String] The full path to the file @param trace [Hash] @return [void]
# File lib/bugsnag/code_extractor.rb, line 19 def add_file(path, trace) # If the file doesn't exist we can't extract code from it, so we can skip # this file entirely unless File.exist?(path) trace[:code] = nil return end @files[path] ||= [] @files[path].push(trace) # Record the line numbers we want to fetch for this trace # We grab extra lines so that we can compensate if the error is on the # first or last line of a file first_line_number = trace[:lineNumber] - MAXIMUM_LINES_TO_KEEP trace[:first_line_number] = first_line_number < 1 ? 1 : first_line_number trace[:last_line_number] = trace[:lineNumber] + MAXIMUM_LINES_TO_KEEP end
extract!()
click to toggle source
Add the code to the hashes that were given in {#add_file} by modifying them in-place. They will have a new ‘:code’ key containing a hash of line number => string of code for that line
@return [void]
# File lib/bugsnag/code_extractor.rb, line 46 def extract! @files.each do |path, traces| begin line_numbers = Set.new traces.each do |trace| trace[:first_line_number].upto(trace[:last_line_number]) do |line_number| line_numbers << line_number end end extract_from(path, traces, line_numbers) rescue StandardError => e # Clean up after ourselves traces.each do |trace| trace[:code] ||= nil trace.delete(:first_line_number) trace.delete(:last_line_number) end @configuration.warn("Error extracting code: #{e.inspect}") end end end
Private Instance Methods
associate_code_with_trace(code, traces)
click to toggle source
@param code [Hash{Integer => String}] @param traces [Array<Hash>] @return [void]
# File lib/bugsnag/code_extractor.rb, line 100 def associate_code_with_trace(code, traces) traces.each do |trace| trace[:code] = {} code.each do |line_number, line| # If we've gone past the last line we care about, we can stop iterating break if line_number > trace[:last_line_number] # Skip lines that aren't in the range we want next unless line_number >= trace[:first_line_number] trace[:code][line_number] = line end trim_excess_lines(trace[:code], trace[:lineNumber]) trace.delete(:first_line_number) trace.delete(:last_line_number) end end
extract_from(path, traces, line_numbers)
click to toggle source
@param path [String] @param traces [Array<Hash>] @param line_numbers [Set<Integer>] @return [void]
# File lib/bugsnag/code_extractor.rb, line 78 def extract_from(path, traces, line_numbers) code = {} File.open(path) do |file| current_line_number = 0 file.each_line do |line| current_line_number += 1 next unless line_numbers.include?(current_line_number) code[current_line_number] = line[0...200].rstrip end end associate_code_with_trace(code, traces) end
trim_excess_lines(code, line_number)
click to toggle source
@param code [Hash{Integer => String}] @param line_number [Integer] @return [void]
# File lib/bugsnag/code_extractor.rb, line 124 def trim_excess_lines(code, line_number) while code.length > MAXIMUM_LINES_TO_KEEP last_line = code.keys.max first_line = code.keys.min if (last_line - line_number) > (line_number - first_line) code.delete(last_line) else code.delete(first_line) end end end