Измените формат и содержимое журнала из ActionController по умолчанию LogSubscriber в Rails 3 - PullRequest
8 голосов
/ 16 июня 2011

Контекст:

В проекте rails 3 я хочу (сильно) настроить формат и содержимое строк журнала «Обработка» и «Завершено в» из ActionController. Это сделано для того, чтобы они соответствовали (также пользовательскому) формату старого приложения rails 2.3, позволяя повторно использовать различные инструменты анализа. Создание их с фиксированным полем (с использованием заполнителей там, где это необходимо) также значительно упрощает выполнение специальных запросов к ним с помощью (скажем) awk или загрузку их в БД или разделение без интеллектуального анализа.

Я быстро и настойчиво достиг этой цели, разветвив рельсы и исправив рассматриваемый LogSubscriber, но сейчас я собираюсь сделать это правильным способом.

Вот что Я думаю Я хочу сделать:

  1. Создать LogSubscriber наследуя ActionController::LogSubscriber.
  2. Переопределять только методы start_processing и process_action.
  3. Отписаться оригинал ActionController::LogSubscriber, который (к сожалению) регистрирует себя, как только класс загружается. Это шаг, на котором я застрял.
  4. Присоедините моего пользовательского подписчика к :action_controller, используя attach_to.

Замечу, что было бы проще, если бы подключение подписчика журнала ActionController по умолчанию было выполнено как шаг настройки, а не при загрузке класса .

Вопрос:

Если подход, описанный выше, подходит, как я могу отменить подписку или отменить подписку на журнал по умолчанию ActionController::LogSubscriber? Базовый класс, ActiveSupport :: LogSubscriber обеспечивает attach_to , но без средств отсоединения.

В качестве альтернативы, каков самый чистый способ изменения поведения (или полного подавления) двух методов (start_processing, process_action) в вышеупомянутом классе, ActionController :: LogSubscriber .

Конечно, я также приветствовал бы любой другой (поддерживаемый) подход, который предоставляет полную свободу в настройке формата журнала двух упомянутых строк.

Неподходящие подходы:

  • Моя проблема не может быть решена путем добавления инструментов , как хорошо документировано mnutt .
  • Я бы хотел избежать мартышек-патчей или взломов, которые могут сломаться при изменении реализации (не интерфейса) направляющих.

Ссылка:

Ответы [ 4 ]

4 голосов
/ 17 июня 2011

Я разработал следующее решение.

Я не особенно доволен его аспектами (например, необходимостью отписаться от ВСЕХ интересов в 'process_action.action_controller'), и я непременно примулучший ответ.

Мы добавили следующее как config/initializers/custom_ac_log_subscriber.rb

module MyApp
  class CustomAcLogSubscriber < ActiveSupport::LogSubscriber
    INTERNAL_PARAMS = ActionController::LogSubscriber::INTERNAL_PARAMS

    #Do your custom stuff here. (The following is much simplified).
    def start_processing(event)
      payload = event.payload
      params  = payload[:params].except(*INTERNAL_PARAMS)
      info "Processing #{payload[:controller]}##{payload[:action]} (...)"
      info "  Parameters: #{params.inspect}" unless params.empty?
    end

    def process_action(event)
      payload   = event.payload
      message = "Completed in %.0fms [#{payload[:path]}]" % event.duration
      info(message)
    end

    def logger
      ActionController::Base.logger
    end
  end
end

#Prevent ActionController::LogSubscriber from also acting on these notifications
#Note that the following undesireably unregisters *everyone's*
#interest in these.  We can't target one LogSubscriber, it seems(?)
%w(process_action start_processing).each do |evt|
  ActiveSupport::Notifications.unsubscribe "#{evt}.action_controller"
end

#Register our own interest
MyApp::CustomAcLogSubscriber.attach_to :action_controller

Примечания по прерванному начальному подходу:

Сначала я попытался подойтиотменить регистрацию LogSubscriber по умолчанию с намерением, чтобы наш пользовательский наследовал и выполнял всю работу (без переопределения).

Однако существует ряд проблем.

1)Недостаточно удалить LogSubscriber следующим образом:

ActiveSupport::LogSubscriber.log_subscribers.delete_if{ |ls| 
  ls.instance_of? ActionController::LogSubscriber } 

Поскольку запрос уведомлений остается зарегистрированным.

2) Кроме того, когда вы наследуете LogSubscriber и регистрируете его, он появляется непереопределенные методы не будут вызываться с использованием унаследованной реализации.

3 голосов
/ 20 марта 2012

Для отписки я нашел это решение: (Rails 3.0.10):

notifier = ActiveSupport::Notifications.notifier
subscribers = notifier.listeners_for("sql.active_record")
subscribers.each {|s| ActiveSupport::Notifications.unsubscribe s }
2 голосов
/ 25 сентября 2012

Для всех, кто ищет это, у Матиаса Мейера есть хорошая запись

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

0 голосов
/ 29 сентября 2015

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

ActiveSupport::Subscriber.subscribers.flat_map(&:patterns).grep(/sql/).map \
  &ActiveSupport::Notifications.method(:unsubscribe)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...