Spec-Zone.ru › Ruby on Rails 8.0

class ActiveSupport::ErrorReporter

Parent:
Объект

Active Support Error Reporter

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") }

Константы

DEFAULT_RESCUE
DEFAULT_SOURCE
SEVERITIES
UnexpectedError

Атрибуты

debug_mode[RW]
logger[RW]

Общедоступные методы класса

new(*subscribers, logger: nil) Показать исходный код
# File activesupport/lib/active_support/error_reporter.rb, line 35
def initialize(*subscribers, logger: nil)
  @subscribers = subscribers.flatten
  @logger = logger
  @debug_mode = false
end

Общедоступные методы экземпляра

disable(subscriber) { || ... } Показать исходный код
# File activesupport/lib/active_support/error_reporter.rb, line 185
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) { || ... } Показать исходный код
# File activesupport/lib/active_support/error_reporter.rb, line 78
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

Выполняет указанный блок, сообщая и игнорируя любые необработанные ошибки. Если ошибка не возникает, возвращает результат выполнения блока. В противном случае возвращает результат fallback.call, или nil, если fallback не указано.

# 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".

record(*error_classes, severity: :error, context: {}, source: DEFAULT_SOURCE) { || ... } Показать исходный код
# File activesupport/lib/active_support/error_reporter.rb, line 114
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

Выполняет указанный блок, сообщая и повторно возбуждая любые необработанные ошибки. Если ошибка не возникает, возвращает результат выполнения блока.

# 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".

report(error, handled: true, severity: handled ? :warning : :error, context: {}, source: DEFAULT_SOURCE) Показать исходный код
# File activesupport/lib/active_support/error_reporter.rb, line 210
def report(error, handled: true, severity: handled ? :warning : :error, context: {}, source: DEFAULT_SOURCE)
  return if error.instance_variable_defined?(:@__rails_error_reported)
  ensure_backtrace(error)

  unless SEVERITIES.include?(severity)
    raise ArgumentError, "severity must be one of #{SEVERITIES.map(&:inspect).join(", ")}, got: #{severity.inspect}"
  end

  full_context = ActiveSupport::ExecutionContext.to_h.merge(context)
  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

  unless error.frozen?
    error.instance_variable_set(:@__rails_error_reported, true)
  end

  nil
end

Непосредственно сообщать об ошибке подписчикам. Можно использовать этот метод, когда блок-основанные методы handle и record не подходят.

Rails.error.report(error)
set_context(...) Показать исходный код
# File activesupport/lib/active_support/error_reporter.rb, line 201
def set_context(...)
  ActiveSupport::ExecutionContext.set(...)
end

Обновить контекст выполнения, доступный для подписчиков об ошибках. Любой контекст, переданный в handle, record или report, будет объединён с контекстом, установленным здесь.

Rails.error.set_context(section: "checkout", user_id: @user.id)
subscribe(subscriber) Показать исходный код
# File activesupport/lib/active_support/error_reporter.rb, line 161
def subscribe(subscriber)
  unless subscriber.respond_to?(:report)
    raise ArgumentError, "Error subscribers must respond to #report"
  end
  @subscribers << subscriber
end

Зарегистрировать нового подписчика об ошибках. Подписчик должен отвечать на

report(Exception, handled: Boolean, severity: (:error OR :warning OR :info), context: Hash, source: String)

Метод report никогда не должен вызывать ошибку.

unexpected(error, severity: :warning, context: {}, source: DEFAULT_SOURCE) Показать исходный код
# File activesupport/lib/active_support/error_reporter.rb, line 145
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

Сообщить об указанной ошибке в режиме производства или возбудить её в режиме разработки или тестирования.

При вызове в режиме производства после сообщения об ошибке этот метод вернёт пустое значение, и выполнение продолжится.

При вызове в режиме разработки исходная ошибка обернётся в другой класс ошибок, чтобы убедиться, что она не перехватывается выше по стеку, и будет отображена разработчику.

Этот метод предназначен для сообщения о нарушении предпосылок или подобных случаях, которые могут и должны быть корректно обработаны в режиме производства, но не должны происходить.

Ошибка может быть экземпляром исключения или 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
unsubscribe(subscriber) Показать исходный код
# File activesupport/lib/active_support/error_reporter.rb, line 176
def unsubscribe(subscriber)
  @subscribers.delete_if { |s| subscriber === s }
end

Отменить регистрацию подписчика об ошибках. Принимает либо подписчика, либо класс.

subscriber = MyErrorSubscriber.new
Rails.error.subscribe(subscriber)

Rails.error.unsubscribe(subscriber)
# or
Rails.error.unsubscribe(MyErrorSubscriber)

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API