class ActiveSupport::BacktraceCleaner
Очиститель трассировки стека
Трассировки стека часто содержат множество строк, не относящихся к рассматриваемому контексту. Из-за этого трудно отделить полезную информацию от шума в трассировке стека, а отладка занимает больше времени. С помощью BacktraceCleaner фильтры и подавители удаляют шумные строки, оставляя только наиболее важные.
Фильтры изменяют строки данных, а подавители полностью удаляют их. Типичный сценарий использования фильтра — удаление длинных сведений о путях в начале каждой строки, чтобы вместо корня файловой системы отображались пути к файлам, относящимся к каталогу приложения. Типичный сценарий использования подавителя — исключение из трассировки стека вывода шумной библиотеки, чтобы можно было сосредоточиться на остальном.
bc = ActiveSupport::BacktraceCleaner.new
root = "#{Rails.root}/"
bc.add_filter { |line| line.delete_prefix(root) } # strip the Rails.root prefix
bc.add_silencer { |line| /puma|rubygems/.match?(line) } # skip any lines from puma or rubygems
bc.clean(exception.backtrace) # perform the cleanup
Чтобы перенастроить существующий BacktraceCleaner (например, используемый по умолчанию в Rails) и отображать как можно больше данных, можно вызвать BacktraceCleaner#remove_silencers!, который вернёт трассировку стека в исходное состояние. Если нужно перенастроить существующий BacktraceCleaner так, чтобы он не фильтровал и не изменял пути ни в одной строке трассировки стека, можно вызвать BacktraceCleaner#remove_filters! Эти два метода вернут трассировку стека в полностью неизменённое состояние.
Вдохновлено гемом Quiet Backtrace от thoughtbot.
Константы
- FORMATTED_GEMS_PATTERN
Публичные методы класса
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 35 def initialize @filters, @silencers = [], [] add_core_silencer add_gem_filter add_gem_silencer add_stdlib_silencer end
Публичные методы экземпляра
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 154 def add_filter(&block) @filters << block end
Добавляет фильтр из переданного блока. Каждая строка трассировки стека будет обработана этим фильтром.
# Will turn "/my/rails/root/app/models/person.rb" into "app/models/person.rb"
root = "#{Rails.root}/"
backtrace_cleaner.add_filter { |line| line.delete_prefix(root) }
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 163 def add_silencer(&block) @silencers << block end
Добавляет подавитель из переданного блока. Если для заданной строки подавитель возвращает true, эта строка исключается из очищенной трассировки стека.
# Will reject all lines that include the word "puma", like "/gems/puma/server.rb" or "/app/my_puma_server/rb"
backtrace_cleaner.add_silencer { |line| /puma/.match?(line) }
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 45
def clean(backtrace, kind = :silent)
filtered = filter_backtrace(backtrace)
case kind
when :silent
silence(filtered)
when :noise
noise(filtered)
else
filtered
end
end Возвращает трассировку стека после применения всех фильтров и подавителей. Сначала применяются фильтры, затем подавители.
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 73
def clean_frame(frame, kind = :silent)
frame = frame.to_s
@filters.each do |f|
frame = f.call(frame.to_s)
end
case kind
when :silent
frame unless @silencers.any? { |s| s.call(frame) }
when :noise
frame if @silencers.any? { |s| s.call(frame) }
else
frame
end
end Возвращает кадр после применения всех фильтров. Возвращает nil, если кадр был подавлен.
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 67
def clean_locations(locations, kind = :silent)
locations.select { |location| clean_frame(location, kind) }
end Принимает массив объектов Thread::Backtrace::Location и возвращает массив очищенных объектов:
clean_locations = backtrace_cleaner.clean_locations(caller_locations)
Фильтры и подавители, как обычно, получают строки. Однако атрибуты path объектов в возвращаемом массиве содержат исходные, нефильтрованные значения, поскольку объекты Location неизменяемы.
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 94
def first_clean_frame(kind = :silent)
caller_location_skipped = false
Thread.each_caller_location do |location|
unless caller_location_skipped
caller_location_skipped = true
next
end
frame = clean_frame(location, kind)
return frame if frame
end
end Возвращает первый очищенный кадр из трассировки стека вызывающего кода или nil.
Кадры представлены строками.
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 113
def first_clean_location(kind = :silent)
caller_location_skipped = false
Thread.each_caller_location do |location|
unless caller_location_skipped
caller_location_skipped = true
next
end
return location if clean_frame(location, kind)
end
end Возвращает первое очищенное местоположение из стека вызовов вызывающего кода или nil.
Местоположения — это объекты Thread::Backtrace::Location. Поскольку они неизменяемы, их атрибуты path содержат исходные значения, однако фильтры применяются внутренне, чтобы подавители могли использовать их.
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 177 def remove_filters! @filters = [] end
Удаляет все фильтры, но оставляет подавители. Полезно, если внезапно понадобится увидеть в трассировке стека полные пути к файлам, которые ранее были отфильтрованы.
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 170 def remove_silencers! @silencers = [] end
Удаляет все подавители, но оставляет фильтры. Полезно, если область отладки внезапно расширилась, поскольку вы подозреваете ошибку в одной из используемых библиотек.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.