Нет трассировки стека для исключений, возникающих в движках вне корня Rails - PullRequest
0 голосов
/ 02 октября 2018

Я работаю над приложением, обновленным до Rails 5.1, когда возникает внутренняя ошибка сервера, я получаю сообщение об исключении, но нет трассировки стека.Например:

Completed 500 Internal Server Error in 25ms (ActiveRecord: 13.5ms)

NoMethodError - undefined method `performer' for #<AssignSiteToStudy::Form>
Did you mean?  performer_id:

Нет дополнительной информации ни в stdout, ни в файле журнала разработки.

После некоторого исследования кажется, что проблема возникает в геме better_errors, в частности Rails.backtrace_cleaner.clean удаляет все строки обратной трассировки:

# better_errors-2.5.0/lib/better_errors/middleware.rb:

def backtrace_frames
  if defined?(Rails) && defined?(Rails.backtrace_cleaner)
    Rails.backtrace_cleaner.clean @error_page.backtrace_frames.map(&:to_s)
   else
     @error_page.backtrace_frames
   end
end

Обновление: фактическая ошибка возникает в движке, который находится за пределами корня Rails.На него ссылаются в Gemfile, используя path, например gem "my_engine", path: '~/dev/my_engine.

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

Настоящая проблема здесь в том, что ошибка исходит от движка, который находится за пределами корня Rails.В Gemfile он упоминается как gem 'my_engine', path: '~/dev/my_engine'.

. Это означает, что фильтр, удаляющий корень Rails и обычно превращающий /home/user/dev/project/app/... в app/..., не делает этого для пути вне корня Rails, и поэтому ониисключены глушителем Rails, который удаляет все, что не начинается с lib, app и т. д.

Решение состоит в том, чтобы самим управлять глушителями, к счастью, у нас уже есть переменная ENV, ENGINES_HOME, которая указываетв корневой каталог для наших репозиториев.В initializers/backtrace_cleaner.rb:

Rails.backtrace_cleaner.remove_silencers!

if ENV['ENGINES_HOME']
  Rails.backtrace_cleaner.add_filter { |line| line.sub(ENV['ENGINES_HOME'], "engines") } 
end

Rails.backtrace_cleaner.add_silencer { |line| line !~ /^\/?(app|config|lib|spec|engines)/}
0 голосов
/ 04 октября 2018

Удаление драгоценного камня better_errors устраняет эту проблему.Теперь я получаю:

Completed 500 Internal Server Error in 1674ms (ActiveRecord: 50.4ms)

undefined method `sites' for #<Class:0x000055a38ef961b8>

ActionView::Template::Error (undefined method `sites' for #<Class:0x000055a38ef961b8>):
1: $('#sites_panel').html('<%= escape_javascript render partial: ...
activerecord (5.1.6) lib/active_record/dynamic_matchers.rb:22:in `method_missing'
/home/user/dev/engine/app/services/update_site_assigned_to_study.rb:30:in `site'
etc.
etc.

Причина, по которой это работает, заключается в том, что Rails.backtrace_cleaner отфильтровывает все строки.Это связано с тем, что комбинация фильтров и глушителей в Rails :: BacktraceCleaner в конечном итоге приводит к удалению строк из механизма, в котором возникают ошибки, поскольку он находится вне корня Rails.

Обычно, как в этом случае, когдавсе строки были отфильтрованы с помощью очистителя backtrace ActionDispatch::DebugExceptions#log_error будет отображать полную обратную трассировку как отступление к ничего не отображать.

Однако при использовании better_errors обычный код Rails, в #log_error, не отображаетсяназываться.Я предполагаю, что better_errors обезьяна исправляет Rails.В любом случае better_errors использует Rails.backtrace_cleaner фильтрацию всех строк без отступления для случая, когда все строки были отфильтрованы.

...