Spec-Zone.ru › Ruby on Rails 4.2

модуль ActiveSupport::Notifications

Уведомления

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

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

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

ActiveSupport::Notifications.instrument('render', extra: :information) do
  render text: '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 text: 'Foo'
end

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

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

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

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

Также возможно передать объект в качестве второго параметра, передаваемого в метод 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 162
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 185
def instrumenter
  InstrumentationRegistry.instance.instrumenter_for(notifier)
end
publish(name, *args) Показать исходный код
# File activesupport/lib/active_support/notifications.rb, line 158
def publish(name, *args)
  notifier.publish(name, *args)
end
subscribe(*args, &block) Показать исходный код
# File activesupport/lib/active_support/notifications.rb, line 170
def subscribe(*args, &block)
  notifier.subscribe(*args, &block)
end
subscribed(callback, *args) { || ... } Показать исходный код
# File activesupport/lib/active_support/notifications.rb, line 174
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 181
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