开发者

Can I disable the log header for ruby logger?

I'm currently running into kind of a problem.

As you might know, the ruby logger adds a logging header at the top of every newly created logfile.

"# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]

I am logging CSV files to import them in a warehouse later, usually I just skip the first line with the header. It's seems like there is a bug in the logger, because sometimes the logging header appears more than once, right in the middle of a log file.

So I decided to simply leave that header out. To my surprise I didn't find any argument one could pass at the creation of a logger. I thought of something like this:

Logger.new "info.log", :skip_header => true

But it's just not there. I searched in the ruby core sources and surprisingly there really is nothing that could prevent the logger from adding the log header:

def creat开发者_StackOverflow中文版e_logfile(filename)
  logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT))
  logdev.sync = true
  add_log_header(logdev)
  logdev
end

def add_log_header(file)
  file.write(
    "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
)
end

Does anyone have an idea what I could do, to prevent the log header? I'm using Ruby 1.8.7 302 with Rails 2.3.5 here. Simply ignoring the comments on the warehouse side is not possible because I have no control over the code there, and it seems to be to risky to simply ignore it, if something goes wrong with a a logging line.

Does someone know a logger that allows this? Do you think it would be a good idea to use and write plain to a file?

Thanks in advance, Tommy


Ideally the method add_log_header on the Logger instance should be overwritten, but since add_log_header is called on initialize, you're too late by the time you get your hands on it. Well, you could just overwrite the add_log_header method on the Class.

class Logger::LogDevice
  def add_log_header(file)
  end
end

log1 = Logger.new('info1.log')

But if your app needs more instances of Logger after this, they will behave the same: no header. To prevent this:

# dismantle the header and save it under another name
class Logger::LogDevice
  alias orig_add_log_header add_log_header

  def add_log_header(file)
  end
end

# Quick,create an instance 
log1 = Logger.new('test_log1file.log')

# restore the old method:
class Logger::LogDevice  
  alias add_log_header orig_add_log_header 
end


Here's a solution that involves subclassing Logger. We have to be sneaky with initialize and super to keep it from creating a standard Logger::LogDevice too early.

class HeadlessLogger < Logger
  def initialize(logdev, shift_age = 0, shift_size = 1048576)
    super(nil) # this prevents it from initializing a LogDevice
    if logdev
      @logdev = HeadlessLogger::LogDevice.new(logdev, shift_age: shift_age, shift_size: shift_size)
    end
  end

  class LogDevice < ::Logger::LogDevice
    def add_log_header(file) ; end
  end
end


As an alternative to patching the logger class, simply do not let it create the log file by touching it upfront:

FileUtils.touch logfile_path
Logger.new logfile_path

In plain Ruby you will need to require 'fileutils' from stdlib obviously.

Edit: This will not work if you use the built-in logrotation though, or the file is deleted, as there is no on-rotate hook and it will then write the header yet again.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜