Rails 3.2.x:如何在不重新启动应用程序的情况下更改日志记录级别



我想在不重新启动应用程序的情况下更改正在运行的 Rails 3.2.x 应用程序的日志记录级别。我的目的是使用它来进行短时调试和信息收集,然后再将其恢复到通常的日志记录级别。

我还了解,按升序排列的级别是调试、信息、警告、错误和致命,生产服务器记录信息及更高,而开发日志调试及更高。

我明白,如果我跑步

Rails.logger.level=:debug #or :info, :warn, :error, :fatal

这会立即更改日志记录级别吗?

如果是这样,我可以通过编写 Rake 任务来调整日志记录级别来做到这一点,还是需要通过添加路由来支持这一点?例如在config/routes.rb中:

match "/set_logging_level/:level/:secret" => "logcontroller#setlevel" 

,然后在日志控制器中设置级别。(:level 是日志记录级别,客户端和服务器之间共享的 :secret 是防止随机用户调整日志级别的东西)

耙子任务和/set_logging_level哪个更合适?

为什么不使用操作系统信号呢?例如,在 UNIX 上,user1 和 user2 信号可以自由用于您的应用程序:

config/initializers/signals.rb:
trap('USR1') do
  Rails.logger.level = Logger::DEBUG
end
trap('USR2') do
  Rails.logger.level = Logger::WARN
end

然后只需这样做:

kill -SIGUSR1 pid
kill -SIGUSR2 pid

只要确保你没有覆盖服务器的信号 - 每个服务器都利用各种信号来执行日志轮换、子进程终止和终止等操作。

在 Rails 控制台中,您可以简单地执行以下操作:

Rails.logger.level = :debug

现在,所有执行的代码都将使用此日志级别运行

由于您必须更改正在运行的轨道实例中的级别,因此简单的 rake 任务将不起作用。
我会选择专用路线。

而不是共享密钥,我将使用应用程序的标准用户身份验证(如果您的应用程序有用户)并限制管理员/超级用户的访问。

在你的控制器日志控制器中试试这个

def setlevel
  begin
      Rails.logger.level = Logger.const_get(params[:level].upcase)
  rescue
      logger.info("Logging level #{params[:level]} not supported")
  end
end

你也可以使用 gdb 附加到正在运行的进程,将 Rails.logger 设置为调试级别,然后分离。我创建了以下 1 个衬里来为我的 puma 过程执行此操作:

gdb attach $(pidof puma) -ex 'call(rb_eval_string("Rails.logger.level = Logger::DEBUG"))' -ex detach -ex quit

注意:pidof 将按降序返回多个 pid。因此,如果您有多个同名进程,则只会在 pidof 返回的第一个进程上运行。其他的将被"gdb attach"命令丢弃,并显示消息:"忽略多余的命令行参数。(26762)".但是,如果您只关心pidof返回的第一个进程,则可以安全地忽略它。

使用 rufus-scheduler,我创建了这个调度:

scheduler.every 1.second do
  file_path = "#{Rails.root}/tmp/change_log_level.#{Process.pid}"
  if File.exists? file_path
    log_level = File.open(file_path).read.strip
    case log_level
    when "INFO"
      Rails.logger.level = Logger::INFO
      Rails.logger.info "Changed log_level to INFO"
    when "DEBUG"
      Rails.logger.level = Logger::DEBUG
      Rails.logger.info "Changed log_level to DEBUG"
    end
    File.delete file_path
  end
end

然后,可以通过在 tmp/change_log_level.PID 下创建一个文件来更改日志级别,其中 pid 是 rails 进程的进程 ID。您可以创建 rake/capistrano 任务来检测和创建这些文件,从而快速切换正在运行的生产服务器的日志级别。

只要记住在工作线程中启动rufus,如果你使用的是独角兽或类似的东西。

我认为这是一个很好的例子,可以放在动态配置系统之上。动态配置负责将日志级别实时传播到服务器,然后在发生日志记录时,它可以评估日志级别的当前状态。大多数 FeatureFlags 产品都以类似的方式推送这样的新配置。

这样做的优点是,除了简单的全局日志级别之外,您还可以拥有带有规则的更复杂的 LogLevel 对象。这使您可以为Services::Billing90 minutes打开DEBUG user1234

我已经考虑到这一点构建了 prefab.cloud,因此值得一试。动态日志记录的核心 ruby 代码是 https://github.com/prefab-cloud/prefab-cloud-ruby/blob/main/lib/prefab/logger_client.rb

简化,这是:

    def log(message, path, progname, severity)
      severity ||= ::Logger::UNKNOWN
      return true if severity < level_of(@dynamic_config.get(path, @context))
      ...log as normal...
    end

如果您不想使用预制件,则可以使用另一个动态配置系统来执行类似操作。

相关内容

  • 没有找到相关文章

最新更新