我们希望拥有一组控制器,我们将记录器输出从所有操作和下游方法路由到单独的日志文件。这是一个Rails 3项目。在Rails 2中,我们通过重新定义"记录器"方法但在Rails 3中,记录方式是使用" Rails.logger"。我试过把
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中,并且我不希望报告控制器的任何消息显示在主日志中(即生产日志,如果在生产中) )
更新:
感谢@ mudasobwa对他的回答和聊天的帮助,我能够使用中间件来解决这个问题,因为他的答案描述了(尽管我必须将我的insert_before更改为Rails :: Rack :: Logger之前)< / p>
他为我解决的修改后的答案如下,它存在于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
答案 0 :(得分:5)
您是否尝试过使用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
答案 1 :(得分:3)
并非所有内容都被控制器过滤器重定向的原因是,这些“已启动...”等由rack middleware编写,即在之前执行 / em>控制器甚至被实例化。
因此,要抓住并重定向与某些条件相关的所有,应该更深入地干预。以下是关于如何入侵管道的[可能不完整]示例。
定义中间件以切换记录器
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,甚至使用正则表达式过滤消息(尽管它不应被视为一种好习惯。)
答案 2 :(得分:0)
要添加@ messanjah的答案,您可以覆盖这些记录器:
Rails::logger, ActionView::Base.logger, ActionController::Base.logger, ActiveRecord::Base.logger
。
通过抑制这些记录器可以消除大多数消息。但正如@mudasobwa指出的那样......消息是在控制器之前编写的。
如果您不想使用中间件,可以随时使用锤子和monkeypatch Rails::Rack::Logger
来使用您的记录器应用程序。或者你可以检查路径并拒绝那里的某些消息。