2015-03-02 1 views
6

Мы хотим иметь коллекцию контроллеров, в которых мы отправляем логин, выводимый из всех действий и методов нижестоящих потоков, в отдельный файл журнала. Это проект Rails 3. В Rails 2 мы сделали это, переопределив метод «logger», но в Rails 3 способ записи - «Rails.logger». Я попытался положитьРелейный выход регистратора для определенного контроллера в Rails 3

Rails::logger = Logger.new(File.join(Rails.root, 'log', "reports_controller.log"), 10, 1000000) 

в верхней части контроллера, а только конкретные случаи, когда Rails.logger используется именно в действия послана на указанный лог-файл, все выхода журнала по умолчанию для контроллера по-прежнему маршрутизируется в основной файл журнала.

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

По выходе контроллера по умолчанию, я имею в виду все сообщения, которые начинаются с самого начала въездного запроса

Started POST "/api/v1/reports.json" for 10.XXX.XX.XX at 2015-03-07 01:30:22 +0000 
Processing by Api::V1::ReportsController#create as JSON 
    Parameters: {"report"=>{"cloud_file_path"=>"report.zip", "company_id"=>nil, "created_at"=>"2015-03-07T01:30:17Z", "type_id"=>"2", "updated_at"=>"2015-03-07T01:30:17Z", "master"=>"1"}} 

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

В принципе, я хочу, чтобы все отчеты для контроллера отчетов находились в файле reports_controller.log, и я не хочу, чтобы сообщения для трафика отображались в главном журнале (т. е. production.log если в производстве)

Update:

Благодаря @ mudasobwa-х помочь с его ответом и чат, я был в состоянии решить это с помощью промежуточного программного, как его ответ Изображает (хотя я должен был изменить свой insert_before, чтобы быть перед Rails :: Rack :: Logger)

пересмотренный ответ от него, что решил это для меня ниже, и он живет в config/initializers/logger_middleware.rb

module MyApp 
    class LoggerMiddleware 

    REPORTS_API_CONTROLLER_PATH = %r|\A/api/v.*/reports/.*| 
    REPORTS_API_CONTROLLER_LOGFILE = "reports_controller.log" 

    def initialize(app) 
     @app, @logger = app, Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log) 
     @reports_api_controller_logger = Logger.new(Rails.root.join('log', REPORTS_API_CONTROLLER_LOGFILE), 10, 1000000) 
    end 

    def call(env) 
     Rails::logger 
      .instance_variable_get(:@logger) 
      .instance_variable_set(:@log, 
       case env['PATH_INFO'] 
       when REPORTS_API_CONTROLLER_PATH then 
       @reports_api_controller_logger 
       else 
       @logger 
       end 
      ) 
     @app.call(env) 
    end 
    end 
end 

Rails.application.middleware.insert_before Rails::Rack::Logger, MyApp::LoggerMiddleware 

ответ

2

Причина, по которой не все вещи перенаправляется контроллера фильтра, что эти «работы ...» и т.д. написаны rack middleware, что выполняется перед тем контроллер даже инстанцированный.

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

Определение промежуточного уровня для переключения лесорубов

module MyApp 
    class MyMiddleware 

    def initialize(app) 
     @app, @logger = app, Rails.logger 
           .instance_variable_get(:@logger) 
           .instance_variable_get(:@log) 
     @my_logger = Logger.new('reports_controller.log', ...) 
    end 

    def call(env) 
     # env['action_dispatch.logger'].inspect 
     #⇒ <TaggedLogging... @logger=#<BufferedLogger...> @log_dest=...> 

     # here we do not have a controller name 
     Rails.logger 
      .instance_variable_get(:@logger) 
      .instance_variable_set(:@log, 
       case env['PATH_INFO'] # or PATH_INFO, or whatever 
       when %r|\A/api/v1/| then @my_logger 
       else @logger 
       end 
      ) 

     @app.call(env) 
    end 
    end 
end 

Добавить инициализатор где-то в config/initializers/my_logger.rb

Rails.application.middleware.insert_before \ 
    Rails::Rack::Logger, MyApp::MyMiddleware 

Пожалуйста, обратите внимание, что регистратор Rails' является вложенной зверь:

Rails::logger 
#⇒ #<ActiveSupport::TaggedLogging:0x000000020f5ad0 @logger=... 
Rails::logger.instance_variable_get(:@logger) 
#⇒ #<ActiveSupport::BufferedLogger:0x000000020f6188 @log_dest=... 
Rails::logger.instance_variable_get(:@logger) 
      .instance_variable_get(:@log) 
#⇒ #<Logger:0x000000020f6138 @progname=nil, @level=0, @default_formatter=... 

Один может понадобиться установить определенный formatter на регистраторе, или даже сообщения фильтра, используя регулярные выражения там (хотя это не должно рассматриваться как хорошая практика.)

+0

. Так же этот подход, установив Rails.logger в промежуточном программном обеспечении, оценивая REQUEST_URI, повлиять на все протоколирование с этой точки вперед для этого вызова? Или это еще одно дополнительное место, чтобы поймать больше? Например, после другого ответа я заметил, что мне пришлось перенаправить ActiveRecord :: Base.logger отдельно, если я хотел, чтобы протоколы db также маршрутизировались. Переустанавливает ли промежуточное программное обеспечение стойки и устанавливает логгер для этого и других мест, где также определен логгер, или мне нужно будет улучшить это, чтобы включить в это время большее количество регистраторов (или дальше вверх по течению?). – Streamline

+0

Установка 'Rails :: logger.instance_variable_get (: @ logger) .instance_variable_get (: @ log)' влияет на все (я использую это в процессе производства.) Установка только 'Rails :: logger' зависит от того, что я не глубоко вникнул (вкратце: я предлагаю установить базовый 'Logger'.) – mudasobwa

+0

Когда вы говорите, что теперь устанавливаются Rails :: logger.instance_variable_get (: @ logger) .instance_variable_get (: @ log), вы делаете это в том же как вы разместили через промежуточное программное обеспечение и просто заменили эту строку 'когда% r | \ A/api/v1/| то Rails :: logger = @ my_logger' выше с этим 'when% r | \ A/api/v1/| затем Rails :: logger.instance_variable_get (: @ logger) .instance_variable_set (: @ log, @ my_logger) '? – Streamline

4

вы пробовали предваряя в around_filter?

class MyController < ApplicationController 
    prepend_around_filter :set_logger 

    private 

    def set_logger 
    old_logger = Rails::logger 
    Rails::logger = Logger.new(Rails.root.join('log', "reports_controller.log"), 10, 1000000) 
    yield 
    Rails.logger = old_logger 
    end 
end 
+0

Результат такой же, как и в моем примере кода, явные вызовы журналов переходят в новый файл журнала контроллера, однако все сообщения регистратора по умолчанию для действия контроллера по-прежнему маршрутизируются в файл журнала по умолчанию для среды. Снова по умолчанию я имею в виду сообщения, которые рельсы записывают самостоятельно, такие как «Начал ...», «Обработка по ...» и в том числе сообщения о базе данных (то есть, если среда является разработкой) и т. Д. – Streamline

+1

Хмм - этот ответ вдохновил меня tinker more, и я расширил этот метод, включив в него параметр «ActiveRecord :: Base.logger = new_logger» (и сброс после выхода), и это маршрутизирует ведение базы данных активной записи в новый конкретный регистратор, но я не могу получить ' Started ... 'и' Processing by ... 'и' Completed ... 'для маршрутизации к определенному файлу журнала – Streamline

+0

@Streamline - вы когда-нибудь выясняли, как также регистрировать« Started ... »и «Обработка по ...» в другом лог-файле? – Mattherick

0

Чтобы добавить поверх ответа @ messanjah в , вы можете перезаписать эти регистраторы: Rails::logger, ActionView::Base.logger, ActionController::Base.logger, ActiveRecord::Base.logger.

При подавлении этих регистраторов вы избавляетесь от большинства сообщений. Но поскольку @mudasobwa указал Started ... сообщения пишутся перед контроллером.

Если вы не хотите использовать промежуточное программное обеспечение, вы всегда можете использовать молоток и monkeypatch Rails::Rack::Logger, чтобы использовать широко используемую регистрацию. Или вы можете проверить путь и отклонить там определенные сообщения.

+0

Когда вы говорите, что приложение monkeypatch Rails :: Rack :: Logger широко распространено, как это произойдет 1) по-другому, чем способ, которым @mudasobwa предлагает с помощью промежуточного программного обеспечения, и 2) как быть выборочным для каждого вызова контроллера, даже если он находится до того, как контроллер иначе, чем разбор REQUEST_URI? – Streamline

Смежные вопросы