Spec-Zone.ru › Ruby on Rails 8.1

класс ActiveSupport::ErrorReporter

Родительский класс:
Object

Средство отправки сообщений об ошибках 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") }

Константы

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
  @context_middlewares = ErrorContextMiddlewareStack.new
end

Открытые методы экземпляра

add_middleware (middleware) Показать исходный код
# File activesupport/lib/active_support/error_reporter.rb, line 218
def add_middleware(middleware)
  @context_middlewares.use(middleware)
end

Добавляет промежуточное ПО для изменения контекста ошибки перед его передачей подписчикам.

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

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

Rails.error.add_middleware(-> (error, context) { context.merge({ foo: :bar }) })
disable (subscriber) { || ... } Показать исходный код
# 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) { || ... } Показать исходный код
# 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

Выполняет указанный блок, отправляя отчёты обо всех необработанных ошибках и подавляя их. Если ошибка не возникла, возвращает значение, возвращённое блоком. В противном случае возвращает результат 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 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

Выполняет указанный блок, отправляя отчёты обо всех необработанных ошибках и повторно вызывая их. Если ошибка не возникла, возвращает значение, возвращённое блоком.

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

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

Rails.error.report(error)

Аргумент error должен быть экземпляром Exception.

Rails.error.report(Exception.new("Something went wrong"))

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

set_context (...) Показать исходный код
# File activesupport/lib/active_support/error_reporter.rb, line 202
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 162
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 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

Отправляет отчёт об указанной ошибке в production-окружении или вызывает её в окружении разработки либо тестирования.

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

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

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

В качестве ошибки можно передать экземпляр исключения или 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 177
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