在 Rails 3 中为特定控制器重定向记录器输出

     2023-02-23     246

关键词:

【中文标题】在 Rails 3 中为特定控制器重定向记录器输出【英文标题】:Redirect logger output for a specific controller in Rails 3 【发布时间】:2015-05-03 12:08:35 【问题描述】:

我们希望有一个控制器集合,我们将所有操作和下游方法的记录器输出路由到单独的日志文件。这是一个 Rails 3 项目。在 Rails 2 中,我们通过重新定义“logger”方法来做到这一点,但在 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 中,并且我不希望报告控制器的任何流量消息显示在主日志中(即 production.log,如果在生产中)

更新:

感谢@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

【问题讨论】:

【参考方案1】:

您是否尝试过预先添加一个 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

【讨论】:

结果与我的代码示例相同,显式记录器调用确实被路由到新的控制器日志文件,但是,控制器操作的所有默认记录器消息仍然被路由到环境默认日志文件。同样,默认情况下,我指的是 rails 自己编写的消息,例如“开始...”、“由...处理”并包括数据库(即,如果环境是开发环境)消息等。 Hmm - 这个响应激发了我更多的修补,我扩展了方法以包括 ActiveRecord::Base.logger = new_logger (并在产量后重置),这将活动记录数据库日志记录到新的特定记录器 - 但我似乎无法将 Started...Processing by...Completed... 消息路由到特定日志文件 @Streamline - 你有没有想过,如何在另一个日志文件中记录“开始...”和“处理...”? @Mattherick - 不幸的是没有。我希望尽快重新审视这一点,因为生产日志超载它没有用。我正在评论的这个答案实际上只有助于基本级别的记录器重定向,而不是仍然路由到 production.log 的其余提到的项目【参考方案2】:

不是所有的东西都被controller filter重定向的原因,是这些“Started...”等是rack middleware写的,也就是before > 控制器甚至被实例化了。

因此,要获取和重定向与某些条件相关的所有内容,应该进行更深入的干预。下面是一个[可能不完整的]关于如何侵入管道的示例。

定义切换记录器的中间件

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,甚至在那里使用正则表达式过滤消息(尽管这不应该被认为是一种好的做法。)

【讨论】:

那么这种通过在中间件中设置 Rails.logger 基于评估 REQUEST_URI 的方法会影响从该点开始的所有日志记录吗?或者这只是一个额外的位置来捕捉更多?例如,在另一个答案之后,我注意到如果我希望也路由数据库日志记录,我必须单独重定向 ActiveRecord::Base.logger。机架中间件是否覆盖并设置记录器以及其他定义记录器的位置,或者我需要增强它以在该点(或更上游?)包含更多记录器。 设置Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log) 会影响一切(我确实在生产中使用它。)仅设置Rails::logger 取决于我没有深入研究的smth(简而言之:我建议设置底层Logger .) 当您说现在在生产中设置 Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log) 时,您是否以与通过中间件和只是用这个when %r|\A/api/v1/| then Rails::logger.instance_variable_get(:@logger).instance_variable_set(:@log,@my_logger)替换上面的这一行when %r|\A/api/v1/| then Rails::logger = @my_logger 没错。坦率地说,我不记得我为什么要这样做。也许我在设置Rails::logger 时遇到了一些小故障,也许还有其他原因。我也重置了格式化程序,也许这就是原因。无论如何,我建议您按照上述方式尝试,如果失败,请尝试使用logger.logger.log 我认为我已经接近可测试的情况了,但是 1)我的中间件列表中没有 Rack::Cache(可能是因为这是 Rails 3.2?)所以而不是 insert_before Rack::缓存我将它更改为 insert_after Rails::Rack::Logger 像这样Rails.application.middleware.insert_after Rails::Rack::Logger, MyApp::LoggerMiddleWare, :my_app 2) 我在文档中找不到最后一个参数应该是什么以及它抛出的异常,比如undefined method 'info' for :my_app:Symbol - 那么第三个参数应该是什么是你有 :my_app 上面的地方,它在哪里记录?【参考方案3】:

要添加@messanjah 的答案,您可以覆盖这些记录器: Rails::logger, ActionView::Base.logger, ActionController::Base.logger, ActiveRecord::Base.logger.

通过抑制这些记录器,您可以删除大多数消息。但是正如@mudasobwa 指出的那样 Started ... 消息是在控制器之前写入的。

如果您不想使用中间件,您可以随时使用锤子和monkeypatch Rails::Rack::Logger 来广泛使用您的记录器应用程序。或者您可以检查路径并在那里拒绝某些消息。

【讨论】:

当你说 monkeypatch Rails::Rack::Logger 应用程序范围时,这将如何发生 1) 与 @mudasobwa 建议使用中间件的方式不同,以及 2) 如何对每个控制器调用进行选择性甚至尽管它是在调用控制器之前而不是解析 REQUEST_URI?

从前一个控制器重定向时未调用 Post 方法

】从前一个控制器重定向时未调用Post方法【英文标题】:Postmethodnotcalledwhenredirectedfrompreviouscontroller【发布时间】:2019-01-1001:25:59【问题描述】:所以我有3个jsp表单。第一个带有一般信息。在完成第一个表单时,它应该基于下拉... 查看详情

在spring boot中将控制从一个控制器重定向到另一个控制器

】在springboot中将控制从一个控制器重定向到另一个控制器【英文标题】:Redirectingcontrolfromonecontrollertoanotherinspringboot【发布时间】:2018-02-1105:01:27【问题描述】:我正在尝试将控制从一个控制器重定向到另一个控制器,但它没有... 查看详情

在 POST 数据中从 Api 控制器重定向到 MVC 控制器

】在POST数据中从Api控制器重定向到MVC控制器【英文标题】:RedirectionfromApiControllerToMVCControllerinPOSTdata【发布时间】:2016-10-0819:54:20【问题描述】:我是MVC和WebAPI的新手。我在这里受到打击。我们有一个APIController和MVC控制器。这... 查看详情

文件上传进度条干扰控制器重定向

】文件上传进度条干扰控制器重定向【英文标题】:FileuploadprogressbarinterfereswithControllerredirect【发布时间】:2021-11-1610:23:43【问题描述】:我有一个文件提交表单和一个跟踪上传进度的进度条。但是,控制进度条的javascript会干扰... 查看详情

从基本控制器重定向到操作方法

】从基本控制器重定向到操作方法【英文标题】:redirecttoactionmethodfrombasecontroller【发布时间】:2013-06-2023:35:04【问题描述】:我在我的基本控制器类中初始化了方法,每当执行任何操作方法时都会调用该方法。在每个操作方法... 查看详情

从 MVC 4 控制器重定向到 .aspx 页面

】从MVC4控制器重定向到.aspx页面【英文标题】:Redirecttoan.aspxpagefromaMVC4Controller【发布时间】:2015-03-1204:17:06【问题描述】:我对MVC很陌生,并且一直在努力在各个页面之间进行重定向。我正在尝试从amController重定向到项目根文... 查看详情

如何在 IOS 应用程序中从视图控制器重定向回主故事板

】如何在IOS应用程序中从视图控制器重定向回主故事板【英文标题】:HowtoredirectbackfromViewcontrollertoMainStoryboardinIOSapp【发布时间】:2013-05-2405:36:24【问题描述】:在我的IOS应用程序中,我有一个关于从视图控制器重定向到主故事... 查看详情

Cakephp 内部从控制器重定向到另一个控制器

】Cakephp内部从控制器重定向到另一个控制器【英文标题】:Cakephpinternalredirectfromcontrollertoanothercontroller【发布时间】:2011-05-1302:45:38【问题描述】:更新:我写了一些关于在php中使用header的错误陈述;所以忘记那部分:)我想要的... 查看详情

在 ASP.NET MVC 中使用 AJAX 方法时使用 C# 控制器重定向到页面

】在ASP.NETMVC中使用AJAX方法时使用C#控制器重定向到页面【英文标题】:RedirecttoapageusingC#controllerwhileusingAJAXmethodinASP.NETMVC【发布时间】:2018-12-0300:24:10【问题描述】:我正在使用C#ASP.NETMVC,想知道有没有办法在成功的情况下从控... 查看详情

如何在 Rails 3.2.1 中使用控制器特定的样式表?

】如何在Rails3.2.1中使用控制器特定的样式表?【英文标题】:HowdoIuseControllerspecificstylesheetsinRails3.2.1?【发布时间】:2012-03-0322:51:11【问题描述】:使用Rails3.2.1我使用以下命令创建了一个名为Home的简单控制器:railsgcontrollerHomeinde... 查看详情

Nest.Js 从一个控制器重定向到另一个

】Nest.Js从一个控制器重定向到另一个【英文标题】:Nest.JsRedirectfromacontrollertoanother【发布时间】:2019-10-1706:25:24【问题描述】:所以我有这个模块:@Module(imports:[],controllers:[AppController,AnotherController],providers:[],)在AppController的某些... 查看详情

如果来自特定区域,则 Google Cloud 负载平衡器重定向

】如果来自特定区域,则GoogleCloud负载平衡器重定向【英文标题】:GoogleCloudloadbalancerredirectiffromacertainregion【发布时间】:2020-09-1309:22:50【问题描述】:我有两个静态页面(英语、丹麦语),目前位于GoogleCloudStorageBucket中。此存... 查看详情

Rails 4 - 如何在活动记录查询中为包含()和连接()提供别名

】Rails4-如何在活动记录查询中为包含()和连接()提供别名【英文标题】:Rails4-howtogivealiasnamestoincludes()andjoins()inactiverecordquerying【发布时间】:2015-04-2003:55:51【问题描述】:我怎样才能给例如一个别名?includes()?下面给出:... 查看详情

如何在 lighttpd 中为特定域设置 HTTP 到 HTTPS 重定向?

】如何在lighttpd中为特定域设置HTTP到HTTPS重定向?【英文标题】:HowdoIsetupaHTTPtoHTTPSredirectionforaspecificdomaininlighttpd?【发布时间】:2011-04-1508:51:02【问题描述】:我想将特定域从http重定向到lighttpd中相应的https地址。我尝试了lighttpd... 查看详情

在 Rails 中为数据库视图创建子记录时出现问题

】在Rails中为数据库视图创建子记录时出现问题【英文标题】:ProblemcreatingachildrecordtoadatabaseviewinRails【发布时间】:2021-08-1718:00:50【问题描述】:我创建了一个数据库视图(basketball_players),它是常规表(watchlist_players)的父级:classB... 查看详情

如何使用命名 URL 映射从控制器重定向?

】如何使用命名URL映射从控制器重定向?【英文标题】:HowtoredirectfromacontrollerusinganamedURLmapping?【发布时间】:2011-04-2118:27:40【问题描述】:我有一个如下的URL映射:staticmappings=nameregister:"/register"controller="account"action="createuser"我... 查看详情

在 rails 3 中设置记录器

】在rails3中设置记录器【英文标题】:Settinguptheloggerinrails3【发布时间】:2011-08-2613:11:21【问题描述】:我正在尝试弄清楚如何将记录器与rails3一起使用。我需要登录到控制台中没有它的文件,但我只是不知道如何设置它,然后... 查看详情

可以在 Rails 中创建此重定向路线吗?

...到/javascripts/embed.js目前我能想到的唯一方法是创建一个j控制器,并使用e方法重定向到该控制器。【问题讨论】:【参考方案1】:假设3之前的 查看详情