标准的Ruby记录器(即::Logger
)是否可以在每次写入后自动刷新?
更新:我按照How to get timestamps in your ruby on rails logs设置自定义日志格式化程序:
class Foo
def initialize(params = {})
@logger = Logger.new $stdout
@logger.formatter = LogFormatter.new
@logger.level = params.include?(:log) ? params[:log] : Logger::INFO
# ...
end
class LogFormatter < Logger::Formatter
def call(severity, time, progname, message)
timestamp = time.iso8601
log_msg = "#{timestamp}#{" [#{severity}]" if %w{ERROR WARN}.include? severity} "
if message.is_a? Exception
log_msg += "#{message.message}"
log_msg += ": #{message.backtrace.join "\n#{timestamp} "}" unless message.backtrace.blank?
else
log_msg += message
end
"#{log_msg}\n"
end
end
end
我尝试使用idlefingers中的建议如下:
def initialize(params = {})
Rails.logger.auto_flushing = 1
@logger = Logger.new $stdout
@logger.formatter = LogFormatter.new
@logger.level = params.include?(:log) ? params[:log] : Logger::INFO
end
但没有骰子。 @logger.auto_flushing = 1
也不适合我。我做错了什么?
更新:事实证明,ActiveSupport的::Logger
只是包装了标准的Ruby ::Logger
。所以我的问题毕竟是关于Ruby而不是Rails。
答案 0 :(得分:30)
原来只需要打开底层IO对象的sync
属性:
def initialize(params = {})
$stdout.sync = true unless RAILS_ENV == 'production'
@logger = Logger.new $stdout
@logger.formatter = LogFormatter.new
@logger.level = params.include?(:log) ? params[:log] : Logger::INFO
end
答案 1 :(得分:3)
在您的环境中设置ActiveSupport::BufferedLogger.auto_flushing,如下所示:
Rails.logger.auto_flushing = 1
这应该会在每条消息后刷新。
答案 2 :(得分:0)
将“同步模式”设置为真或假。当同步模式为真时,所有 输出立即刷新到底层操作系统,并 不在内部缓冲。返回新状态。另见#fsync。
https://ruby-doc.org/core-2.7.1/IO.html#method-i-sync
我遇到了这个问题,日志被缓冲并且每小时只刷新一次。
require 'logger'
STDOUT.sync = true
logger = Logger.new(STDOUT, level: :info)
logger.info "Hello World"