系统配置了 nginx 以后 nginx 会对/nginx_check/alive 页面频繁的进行健康检查,(就是一个 get 请求)来确保机器没有 down 掉,但是这会导致大量的无用 log,使得排查问题的时候非常艰难 现在想屏蔽这个这个 action 默认的系统 log(或者把这部分系统 log 重定向到其他文件)
尝试使用 Rails.logger.silence,但是没有效果
class NginxCheckController < ApplicationController
layout false
def alive
Rails.logger.silence do
end
end
end
google 了很久,rails 对 logger 似乎也没有提供 hook,让我们去做事前操作。
不知道该怎么解决,求帮助~
#1 楼 @hw676018683 我前阵子就是参考 quiet_assets 做的,本地开发环境跑没有问题,但是以下这段代码在线上跑时会有问题
def call_with_quiet_assets(env)
begin
if env['PATH_INFO'] =~ ASSETS_REGEX
env[KEY] = Rails.logger.level
Rails.logger.level = Logger::ERROR
end
call_without_quiet_assets(env)
ensure
Rails.logger.level = env[KEY] if env[KEY]
end
end
我猜想是在多进程的情况下,env[KEY] 线程不安全导致,但我本地试了用 puma 起多个 worker 然后写了个脚本并发地试了好多次,都没有办法重现。为了尽快解决这个问题,我不用 env[KEY],而是先直接写死
module QuietHeartbeat
class Railtie < ::Rails::Railtie
initializer 'quiet_heartbeat.initialize' do |app|
PATH_PREFIX_REGEX = /\A(\/heartbeats)/
Rails::Rack::Logger.class_eval do
def call_with_quiet_heartbeat_request(env)
begin
Rails.logger.level = Logger::ERROR if env['PATH_INFO'] =~ PATH_PREFIX_REGEX
call_without_quiet_heartbeat_request(env)
ensure
Rails.logger.level = Logger::DEBUG
end
end
alias_method_chain :call, :quiet_heartbeat_request
end
end
end
end
另外,可用 rack middleware 的方式实现
# lib/quiet_heartbeats_middleware.rb
class QuietHeartbeatsMiddleware
PATH_PREFIX_REGEX = /\A(\/heartbeats)/
def initialize(app)
@app = app
end
def call(env)
if env['PATH_INFO'] =~ PATH_PREFIX_REGEX
# 如果你想直接就返回 OK,那么可以
[200, { 'Context-Type' => 'text/plain' }, ['']]
# 如果还想要 Rails 处理,那么
# Rails.logger.silence do
# @app.call(env)
# end
else
@app.call(env)
end
end
end
嵌入到 middleware stack 里去
# config/application.rb
module Your_Rails_App_name
class Application < Rails::Application
require 'quiet_heartbeats_middleware'
config.middleware.insert_before Rack::Lock, QuietHeartbeatsMiddleware
# .....
end
end
#3 楼 @so_zengtao 我也是这样做的,自定义了一些 log,在自定义的 log 里可以过滤一些 controller 或者 action,不过也没考虑过怎么去过滤掉系统的 log,关注
# lib/silent_logger.rb
#
# SilentLogger can be used to keep requests out of log file
# It is best used for ping requests from uptime services like
# NewRelic, Uptime Robot, etc.
#
# Source: http://dennisreimann.de/blog/silencing-the-rails-log-on-a-per-action-basis/
#
# Include logger in your config/application.rb after require 'rails/all'
# require File.dirname(__FILE__) + '/../lib/silent_logger.rb'
#
# In application.rb or environments/production.rb swap Rails logger:
# config.middleware.swap Rails::Rack::Logger, SilentLogger, silenced: ['/newrelic-ping']
#
class SilentLogger < Rails::Rack::Logger
def initialize(app, taggers = nil)
@app = app
@taggers = taggers
if @taggers.keys.include? :silence
@silenced_paths = @taggers[:silence]
@taggers.delete(:silence)
end
super
end
def call(env)
if env['X-SILENCE-LOGGER'] || @silenced_paths.include?(env['PATH_INFO']) || @silenced_paths.any?{|path| path.is_a?(Regexp) && path.match(env['PATH_INFO'])}
Rails.logger.silence do
@app.call(env)
end
else
super(env)
end
end
end
config/application.rb
require File.dirname(__FILE__) + '/../lib/silent_logger.rb'
module YourApp
class Application < Rails::Application
config.middleware.swap Rails::Rack::Logger, SilentLogger, silence: ['/live-ping', %r'^/assets/']
end
end