ruby 如何在Sentry中将SQL Controller::SQL Error分类为错误

vc9ivgsu  于 12个月前  发布在  Ruby
关注(0)|答案(2)|浏览(102)

我在Rails 6.1应用程序中使用了新的Sentry(不是Raven)for Ruby:

gem "sentry-ruby"
gem "sentry-rails"

我可以看到用户触发ActionController::RoutingError时的事务,但我希望这些在Sentry中显示为错误。我不认为ActionController::RoutingError是“忽略”或“排除”错误:

> Sentry::Configuration::IGNORE_DEFAULT
 => ["Mongoid::Errors::DocumentNotFound", "Rack::QueryParser::InvalidParameterError", "Rack::QueryParser::ParameterTypeError", "Sinatra::NotFound"]

我尝试清除sentry.rb初始化器文件中的excluded_exceptions,但没有效果:

Sentry.init do |config|
  ...
  config.excluded_exceptions = []
end

如何配置Sentry,使这些作为错误发送?我还在想,我可以修改中间件(调度?,背包?)并在适当的地方添加Sentry.capture_message,但我不确定如何做到这一点。
我不想要一个重定向到ErrorController或ApplicationController的“catch-all”路由:
match '*path', to: "application#handle_route_error", via: :all

r7xajy2e

r7xajy2e1#

问题是,这个错误在Rails中是默认处理的,并以“Not Found”响应进行救援
当然,你可以手动处理这些错误(“Not Found”,“Unprocessable Entity”,“Internal Server Error”等),使用router和ErrorsController之类的特定操作进行响应。你可以从那里给哨兵发信息
但既然你不想这样的决定,你可以monopatch中间件,甚至完全ActionController::RoutingError。查找此错误的源代码,并像这样添加初始化器

# config/initializers/handle_routing_error.rb

module ActionController
  class RoutingError < ActionControllerError
    attr_reader :failures
    def initialize(message, failures = [])
      Sentry.capture_message(message) # or Sentry.capture_error(self)

      super(message)
      @failures = failures
    end
  end
end

通常monthlatch是一些黑客和不好的解决方案,但它会工作

rggaifut

rggaifut2#

我不使用sentry,只是用任何sentry命令替换p。但我可以用三个解决方案来弥补:

救援

仅对于生产,这是必需的:config.consider_all_requests_local = false

# config/initializers/report_routing_error.rb

class ReportRoutingErrorMiddleware
  def initialize app
    @app = app
  end

  def call(env)
    @app.call(env)
  rescue ActionController::RoutingError => e
    p ["NOT FOUND", e]
    raise
  end
end

# DebugExceptions raises RoutingError when consider_all_requests_local is false
# insert_before - to catch the error
Rails.application.config.middleware.insert_before ActionDispatch::DebugExceptions, ReportRoutingErrorMiddleware

#=> ["NOT FOUND", #<ActionController::RoutingError: No route matches [GET] "/asdf">]

404

在开发过程中,DebugExceptions中间件在技术上会引发错误,但它也会挽救错误并呈现完整的错误页面。在响应到达该中间件之前,它只是来自路由器的404响应:https:github.com/rails/rails/blob/v7.0.7/actionpack/lib/action_dispatch/routing/route_set.rb#L37

# config/initializers/report_routing_error.rb

class ReportRoutingErrorMiddleware
  def initialize app
    @app = app
  end

  def call(env)
    status, headers, body = response = @app.call(env)
    if status == 404
      # no error, so get what you need from env
      p ["NOT FOUND", env["REQUEST_METHOD"], env["PATH_INFO"]]
    end
    response
  end
end

# insert_after - to get response first, because it doesn't go past DebugExceptions
Rails.application.config.middleware.insert_after ActionDispatch::DebugExceptions, ReportRoutingErrorMiddleware

#=> ["NOT FOUND", "GET", "/asdf"]

拦截

很显然,他们很久以前就发现了register_interceptor

# config/initializers/report_routing_error.rb

ActionDispatch::DebugExceptions.register_interceptor do |req, exception|
  if exception.is_a? ActionController::RoutingError
    p ["NOT FOUND", req, exception]
  end
end

#=> ["NOT FOUND", #<ActionDispatch::Request GET "http://0.0.0.0:3000/asdf" for 127.0.0.1>, #<ActionController::RoutingError: No route matches [GET] "/asdf">]

引入ActionDispatch::DebugExceptions.register_interceptor,这是一种挂接到DebugExceptions并在呈现之前处理异常的方法。
https://github.com/rails/rails/pull/23868

相关问题