Active Support 错误报告器¶ ↑
ActiveSupport::ErrorReporter 是一个通用的错误报告服务接口。
要捕获并报告任何未处理的错误,您可以使用 handle 方法
Rails.error.handle do do_something! end
如果引发错误,它将被报告并吞没。
或者,如果您想报告错误但不想吞没它,可以使用 record
Rails.error.record do do_something! end
这两个方法都可以限制为只处理特定的错误类
maybe_tags = Rails.error.handle(Redis::BaseError) { redis.get("tags") }
- A
- D
- H
- N
- R
- S
- U
常量
| DEFAULT_RESCUE | = | [StandardError].freeze |
| DEFAULT_SOURCE | = | "application" |
| SEVERITIES | = | %i(error warning info) |
| UnexpectedError | = | Class.new(Exception) |
Attributes
| [RW] | debug_mode | |
| [RW] | logger |
类公共方法
new(*subscribers, logger: nil) Link
Source: 显示 | 在 GitHub 上
# File activesupport/lib/active_support/error_reporter.rb, line 35 def initialize(*subscribers, logger: nil) @subscribers = subscribers.flatten @logger = logger @debug_mode = false @context_middlewares = ErrorContextMiddlewareStack.new end
实例公共方法
add_middleware(middleware) Link
添加一个中间件来修改错误上下文,然后再发送给订阅者。
中间件被添加到可调用栈中,在将错误传递给订阅者之前,在错误执行上下文上运行。允许在所有订阅者共享的错误上下文中创建条目。
上下文中间件接收与 report 相同的参数。它必须返回一个哈希——中间件栈在所有中间件运行后返回该哈希。中间件可以修改或替换哈希。
Rails.error.add_middleware(-> (error, context) { context.merge({ foo: :bar }) })
Source: 显示 | 在 GitHub 上
# File activesupport/lib/active_support/error_reporter.rb, line 218 def add_middleware(middleware) @context_middlewares.use(middleware) end
disable(subscriber) Link
阻止订阅者在块的持续时间内收到错误通知。您可以传入订阅者本身,或其类。
这对于错误报告服务集成很有帮助,当它们希望处理堆栈中更高的任何错误时。
Source: 显示 | 在 GitHub 上
# File activesupport/lib/active_support/error_reporter.rb, line 186 def disable(subscriber) disabled_subscribers = (ActiveSupport::IsolatedExecutionState[self] ||= []) disabled_subscribers << subscriber begin yield ensure disabled_subscribers.delete(subscriber) end end
handle(*error_classes, severity: :warning, context: {}, fallback: nil, source: DEFAULT_SOURCE) Link
评估给定的块,报告并吞没任何未处理的错误。如果没有引发错误,则返回块的返回值。否则,返回 fallback.call 的结果,如果 fallback 未指定,则返回 nil。
# Will report a TypeError to all subscribers and return nil. Rails.error.handle do 1 + '1' end
可以限制为只处理特定的错误类
maybe_tags = Rails.error.handle(Redis::BaseError) { redis.get("tags") }
选项¶ ↑
-
:severity- 此值会传递给订阅者,以指示错误报告的重要性。可以是:error、:warning或:info。默认为:warning。 -
:context- 传递给订阅者的额外信息。例如Rails.error.handle(context: { section: "admin" }) do # ... end
-
:fallback- 一个可调用对象,当引发未处理的错误时,它提供handle的返回值。例如user = Rails.error.handle(fallback: -> { User.anonymous }) do User.find_by(params) end
-
:source- 此值会传递给订阅者,以指示错误的来源。订阅者可以使用此值忽略某些错误。默认为"application"。
Source: 显示 | 在 GitHub 上
# File activesupport/lib/active_support/error_reporter.rb, line 79 def handle(*error_classes, severity: :warning, context: {}, fallback: nil, source: DEFAULT_SOURCE) error_classes = DEFAULT_RESCUE if error_classes.empty? yield rescue *error_classes => error report(error, handled: true, severity: severity, context: context, source: source) fallback.call if fallback end
record(*error_classes, severity: :error, context: {}, source: DEFAULT_SOURCE) Link
评估给定的块,报告并重新抛出任何未处理的错误。如果没有引发错误,则返回块的返回值。
# Will report a TypeError to all subscribers and re-raise it. Rails.error.record do 1 + '1' end
可以限制为只处理特定的错误类
tags = Rails.error.record(Redis::BaseError) { redis.get("tags") }
选项¶ ↑
-
:severity- 此值会传递给订阅者,以指示错误报告的重要性。可以是:error、:warning或:info。默认为:error。 -
:context- 传递给订阅者的额外信息。例如Rails.error.record(context: { section: "admin" }) do # ... end
-
:source- 此值会传递给订阅者,以指示错误的来源。订阅者可以使用此值忽略某些错误。默认为"application"。
Source: 显示 | 在 GitHub 上
# File activesupport/lib/active_support/error_reporter.rb, line 115 def record(*error_classes, severity: :error, context: {}, source: DEFAULT_SOURCE) error_classes = DEFAULT_RESCUE if error_classes.empty? yield rescue *error_classes => error report(error, handled: false, severity: severity, context: context, source: source) raise end
report(error, handled: true, severity: handled ? :warning : :error, context: {}, source: DEFAULT_SOURCE) Link
直接向订阅者报告错误。当块式的 handle 和 record 方法不适用时,您可以使用此方法。
Rails.error.report(error)
error 参数必须是 Exception 的实例。
Rails.error.report(Exception.new("Something went wrong"))
否则,您可以使用 unexpected 来报告接受字符串参数的错误。
Source: 显示 | 在 GitHub 上
# File activesupport/lib/active_support/error_reporter.rb, line 233 def report(error, handled: true, severity: handled ? :warning : :error, context: {}, source: DEFAULT_SOURCE) return if error.instance_variable_defined?(:@__rails_error_reported) raise ArgumentError, "Reported error must be an Exception, got: #{error.inspect}" unless error.is_a?(Exception) ensure_backtrace(error) unless SEVERITIES.include?(severity) raise ArgumentError, "severity must be one of #{SEVERITIES.map(&:inspect).join(", ")}, got: #{severity.inspect}" end full_context = @context_middlewares.execute( error, context: ActiveSupport::ExecutionContext.to_h.merge(context || {}), handled:, severity:, source: ) disabled_subscribers = ActiveSupport::IsolatedExecutionState[self] @subscribers.each do |subscriber| unless disabled_subscribers&.any? { |s| s === subscriber } subscriber.report(error, handled: handled, severity: severity, context: full_context, source: source) end rescue => subscriber_error if logger logger.fatal( "Error subscriber raised an error: #{subscriber_error.message} (#{subscriber_error.class})\n" + subscriber_error.backtrace.join("\n") ) else raise end end while error unless error.frozen? error.instance_variable_set(:@__rails_error_reported, true) end error = error.cause end nil end
set_context(...) Link
更新可供错误订阅者访问的执行上下文。传递给 handle、record 或 report 的任何上下文都将与此处设置的上下文合并。
Rails.error.set_context(section: "checkout", user_id: @user.id)
Source: 显示 | 在 GitHub 上
# File activesupport/lib/active_support/error_reporter.rb, line 202 def set_context(...) ActiveSupport::ExecutionContext.set(...) end
subscribe(subscriber) Link
注册一个新的错误订阅者。订阅者必须响应
report(Exception, handled: Boolean, severity: (:error OR :warning OR :info), context: Hash, source: String)
report 方法**绝不能**引发错误。
Source: 显示 | 在 GitHub 上
# File activesupport/lib/active_support/error_reporter.rb, line 162 def subscribe(subscriber) unless subscriber.respond_to?(:report) raise ArgumentError, "Error subscribers must respond to #report" end @subscribers << subscriber end
unexpected(error, severity: :warning, context: {}, source: DEFAULT_SOURCE) Link
在生产环境中报告给定错误,或在开发或测试环境中引发它。
在生产环境中调用时,错误报告后,此方法将返回 nil,执行将继续。
在开发环境中调用时,原始错误将被包装在一个不同的错误类中,以确保它不会被堆栈上层捕获,并会显示给开发人员。
此方法用于报告违反前提条件的断言,或类似情况,这些情况在生产环境中可以并且应该得到妥善处理,但不应该发生。
错误可以是异常实例或 String。
example:
def edit
if published?
Rails.error.unexpected("[BUG] Attempting to edit a published article, that shouldn't be possible")
return false
end
# ...
end
Source: 显示 | 在 GitHub 上
# File activesupport/lib/active_support/error_reporter.rb, line 146 def unexpected(error, severity: :warning, context: {}, source: DEFAULT_SOURCE) error = RuntimeError.new(error) if error.is_a?(String) if @debug_mode ensure_backtrace(error) raise UnexpectedError, "#{error.class.name}: #{error.message}", error.backtrace, cause: error else report(error, handled: true, severity: severity, context: context, source: source) end end
unsubscribe(subscriber) Link
注销错误订阅者。可以接受订阅者或类。
subscriber = MyErrorSubscriber.new Rails.error.subscribe(subscriber) Rails.error.unsubscribe(subscriber) # or Rails.error.unsubscribe(MyErrorSubscriber)
Source: 显示 | 在 GitHub 上
# File activesupport/lib/active_support/error_reporter.rb, line 177 def unsubscribe(subscriber) @subscribers.delete_if { |s| subscriber === s } end