1

我正在开发升级到 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:

标准输出或开发日志文件中没有更多信息。

经过一番调查,似乎问题出现在 better_errors gem 中,特别是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.

4

2 回答 2

3

这里真正的问题是错误来自 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)/}
于 2018-10-04T15:41:09.093 回答
1

移除better_errorsgem 可以解决这个问题。现在我得到:

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 根目录之外。

通常,在这种情况下,当回溯清理器过滤掉所有行时,ActionDispatch::DebugExceptions#log_error会将完整的回溯显示为不显示任何内容的回退。

但是,当使用better_errors通常的 Rails 代码时, in#log_error不会出现它被调用。我推测better_errors猴子修补 Rails。对于已过滤掉所有行的情况,无论哪种方式都better_errors使用Rails.backtrace_cleaner过滤掉所有行而没有后备。

于 2018-10-04T10:52:47.753 回答