Spec-Zone.ru › Ruby on Rails 5.1

module ActiveSupport::Notifications

Уведомления

ActiveSupport::Notifications предоставляет API для инструментирования Ruby.

Инструментаторы

Для инструментирования события вам нужно просто сделать следующее:

ActiveSupport::Notifications.instrument('render', extra: :information) do
  render plain: 'Foo'
end

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

В примере выше render — это имя события, а всё остальное называется данными. Данные — это механизм, который позволяет инструментаторам передавать дополнительную информацию подписчикам. Данные представляют собой хэш, содержимое которого произвольное и, как правило, зависит от события.

Подписчики

Вы можете потреблять эти события и информацию, которую они предоставляют, зарегистрировав подписчика.

ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
  name    # => String, name of the event (such as 'render' from above)
  start   # => Time, when the instrumented block started execution
  finish  # => Time, when the instrumented block ended execution
  id      # => String, unique ID for this notification
  payload # => Hash, the payload
end

Например, сохраним все события «render» в массив:

events = []

ActiveSupport::Notifications.subscribe('render') do |*args|
  events << ActiveSupport::Notifications::Event.new(*args)
end

Этот код возвращает результат сразу же; вы просто подписываетесь на события «render». Блок сохраняется и будет вызываться всякий раз, когда кто-то инструментирует «render»:

ActiveSupport::Notifications.instrument('render', extra: :information) do
  render plain: 'Foo'
end

event = events.first
event.name      # => "render"
event.duration  # => 10 (in milliseconds)
event.payload   # => { extra: :information }

Блок в вызове subscribe получает имя события, отметку времени начала, отметку времени окончания, строку с уникальным идентификатором для этого события (что-то вроде «535801666f04d0298cd6») и хэш с данными в указанном порядке.

Если во время конкретного инструментирования произойдёт исключение, данные будут содержать ключ :exception со значением — массивом из двух элементов: строкой с именем класса исключения и сообщением об исключении. Ключ :exception_object данных будет содержать само исключение в качестве значения.

Как показано в предыдущем примере, класс ActiveSupport::Notifications::Event способен принимать аргументы по мере их поступления и предоставлять объектно-ориентированный интерфейс к этим данным.

Также можно передать объект, который отвечает методу call в качестве второго параметра к методу subscribe вместо блока:

module ActionController
  class PageRequest
    def call(name, started, finished, unique_id, payload)
      Rails.logger.debug ['notification:', name, started, finished, unique_id, payload].join(' ')
    end
  end
end

ActiveSupport::Notifications.subscribe('process_action.action_controller', ActionController::PageRequest.new)

что приведёт к выводу следующего сообщения в логах, включая хэш с данными:

notification: process_action.action_controller 2012-04-13 01:08:35 +0300 2012-04-13 01:08:35 +0300 af358ed7fab884532ec7 {
   controller: "Devise::SessionsController",
   action: "new",
   params: {"action"=>"new", "controller"=>"devise/sessions"},
   format: :html,
   method: "GET",
   path: "/login/sign_in",
   status: 200,
   view_runtime: 279.3080806732178,
   db_runtime: 40.053
 }

Также можно подписываться на все события, имена которых соответствуют определённому регулярному выражению:

ActiveSupport::Notifications.subscribe(/render/) do |*args|
  ...
end

и даже передать без аргументов subscribe, в этом случае вы подписываетесь на все события.

Временные подписки

Иногда вы не хотите подписываться на событие на протяжении всего жизненного цикла приложения. Существуют два способа отписки.

ПРЕДУПРЕЖДЕНИЕ: Система инструментирования предназначена для долгоживущих подписчиков. Используйте эту функцию экономно, так как она очищает некоторые внутренние кэши, что негативно сказывается на производительности.

Подписка во время выполнения блока

Вы можете временно подписываться на некоторое событие во время выполнения какого-то блока. Например, в

callback = lambda {|*args| ... }
ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
  ...
end

обработчик будет вызываться для всех событий «sql.active_record», инструментированных во время выполнения блока. Обработчик отписывается автоматически после этого.

Ручная отписка

Метод subscribe возвращает объект подписчика:

subscriber = ActiveSupport::Notifications.subscribe("render") do |*args|
  ...
end

Чтобы предотвратить вызов этого блока, просто отпишитесь, передав эту ссылку:

ActiveSupport::Notifications.unsubscribe(subscriber)

Вы также можете отписаться, передав имя объекта подписчика. Обратите внимание, что это отпишет все подписки с данным именем:

ActiveSupport::Notifications.unsubscribe("render")

Очередь по умолчанию

Уведомления поставляются с реализацией очереди, которая потребляет и публикует события для всех подписчиков логов. Вы можете использовать любую реализацию очереди, которую хотите.

Атрибуты

notifier[RW]

Публичные методы класса

instrument(name, payload = {}) { |payload| ... } Показать исходный код
# File activesupport/lib/active_support/notifications.rb, line 164
def instrument(name, payload = {})
  if notifier.listening?(name)
    instrumenter.instrument(name, payload) { yield payload if block_given? }
  else
    yield payload if block_given?
  end
end
instrumenter() Показать исходный код
# File activesupport/lib/active_support/notifications.rb, line 187
def instrumenter
  InstrumentationRegistry.instance.instrumenter_for(notifier)
end
publish(name, *args) Показать исходный код
# File activesupport/lib/active_support/notifications.rb, line 160
def publish(name, *args)
  notifier.publish(name, *args)
end
subscribe(*args, &block) Показать исходный код
# File activesupport/lib/active_support/notifications.rb, line 172
def subscribe(*args, &block)
  notifier.subscribe(*args, &block)
end
subscribed(callback, *args) { || ... } Показать исходный код
# File activesupport/lib/active_support/notifications.rb, line 176
def subscribed(callback, *args, &block)
  subscriber = subscribe(*args, &callback)
  yield
ensure
  unsubscribe(subscriber)
end
unsubscribe(subscriber_or_name) Показать исходный код
# File activesupport/lib/active_support/notifications.rb, line 183
def unsubscribe(subscriber_or_name)
  notifier.unsubscribe(subscriber_or_name)
end

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

Spec-Zone.ru

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