机架中间件中的跟踪错误
Trace Error in Rack Middleware
我现在不是 100% 确定,但我相信我遇到了一个异常,导致请求的状态以 401 响应。
我已经删除了控制器中的所有代码,但问题仍然存在,并且似乎为了 return 401 状态而捕获了异常,所以没有堆栈跟踪。
我已经创建了一个自定义中间件来尝试调试,但我仍然无法找到问题的根源。
如何确定问题发生的位置?
我们使用的是 heroku,所以 pry 似乎不起作用,我也没有命令行访问 运行 服务器。我无法在我的本地开发机器上复制该问题。
我从来不知道如何注入日志记录,但有点棘手的解决方法是创建一个额外的中间件,它可以在您需要的地方执行日志记录。
class Debugger
def initialize(app, *args)
@app = app
@args = args
end
def call(env)
Rails.logger.debug "executing app.call Debugger #{@args.first}"
status, headers, body = @app.call(env)
Rails.logger.debug "Status: #{status} after app.call Debugger #{@args.first}"
[status, headers, body]
end
end
然后在中间件堆栈中添加记录器,在 Rails 中,这将进入 config/application.rb
:
config.middleware.insert_before Rack::Sendfile, "Debugger", "1"
这会导致 Rails 记录器添加
Executing app.call Debugger 1
然后执行Rack:Sendfile,日志:
Status: 400 after app.call Debugger 1
假设您正在使用 rails,并且 Rack::Sendfile 返回的状态代码返回了 400 状态代码。
请注意,如果您不使用 Rails。
,您将需要修改记录器,以及如何将中间件配置为 运行
这不是一个理想的解决方案,可能有更好的方法,但在撰写本文时我没有更好的方法。
另一种方法是以下模块,它在 each 中间件 entry/return 处插入一条调试消息(在每个 return 之后打印状态代码)
(改编自 https://github.com/DataDog/dd-trace-rb/issues/368)
# Trace each middleware module entry/exit. Freely adapted from
# https://github.com/DataDog/dd-trace-rb/issues/368 "Trace each middleware in the Rails stack"
module MiddlewareTracer
def call(env)
Rails.logger.debug { "MiddleWare: entry #{self.class.name}" }
status, headers, response = super(env)
Rails.logger.debug { "MiddleWare: #{self.class.name}, returning with status #{status}" }
[status, headers, response]
end
end
# Instrument the middleware stack after initialization so that we
# know the stack won't be changed afterwards.
Rails.configuration.after_initialize do
Rails.application.middleware.each do |middleware|
klass = middleware.klass
# There are a few odd middlewares that aren't classes.
klass.prepend(MiddlewareTracer) if klass.respond_to?(:prepend)
end
end
我现在不是 100% 确定,但我相信我遇到了一个异常,导致请求的状态以 401 响应。
我已经删除了控制器中的所有代码,但问题仍然存在,并且似乎为了 return 401 状态而捕获了异常,所以没有堆栈跟踪。
我已经创建了一个自定义中间件来尝试调试,但我仍然无法找到问题的根源。
如何确定问题发生的位置?
我们使用的是 heroku,所以 pry 似乎不起作用,我也没有命令行访问 运行 服务器。我无法在我的本地开发机器上复制该问题。
我从来不知道如何注入日志记录,但有点棘手的解决方法是创建一个额外的中间件,它可以在您需要的地方执行日志记录。
class Debugger
def initialize(app, *args)
@app = app
@args = args
end
def call(env)
Rails.logger.debug "executing app.call Debugger #{@args.first}"
status, headers, body = @app.call(env)
Rails.logger.debug "Status: #{status} after app.call Debugger #{@args.first}"
[status, headers, body]
end
end
然后在中间件堆栈中添加记录器,在 Rails 中,这将进入 config/application.rb
:
config.middleware.insert_before Rack::Sendfile, "Debugger", "1"
这会导致 Rails 记录器添加
Executing app.call Debugger 1
然后执行Rack:Sendfile,日志:
Status: 400 after app.call Debugger 1
假设您正在使用 rails,并且 Rack::Sendfile 返回的状态代码返回了 400 状态代码。
请注意,如果您不使用 Rails。
,您将需要修改记录器,以及如何将中间件配置为 运行这不是一个理想的解决方案,可能有更好的方法,但在撰写本文时我没有更好的方法。
另一种方法是以下模块,它在 each 中间件 entry/return 处插入一条调试消息(在每个 return 之后打印状态代码) (改编自 https://github.com/DataDog/dd-trace-rb/issues/368)
# Trace each middleware module entry/exit. Freely adapted from
# https://github.com/DataDog/dd-trace-rb/issues/368 "Trace each middleware in the Rails stack"
module MiddlewareTracer
def call(env)
Rails.logger.debug { "MiddleWare: entry #{self.class.name}" }
status, headers, response = super(env)
Rails.logger.debug { "MiddleWare: #{self.class.name}, returning with status #{status}" }
[status, headers, response]
end
end
# Instrument the middleware stack after initialization so that we
# know the stack won't be changed afterwards.
Rails.configuration.after_initialize do
Rails.application.middleware.each do |middleware|
klass = middleware.klass
# There are a few odd middlewares that aren't classes.
klass.prepend(MiddlewareTracer) if klass.respond_to?(:prepend)
end
end