In our application we may occasionally have a heavy usage of logger.debug calls. It appears to be helpful to examine the fails, especially in multithreading environment. That’s why we do not want to get rid of these calls. We set the logger.level = Logger::INFO in production instead.

But what if we need to print debug messages for only one or two of over 9000 files? There is no elegant solution on hand, as far as I know. Let me show an ugly hack to provide such a functionality.

First of all, let’s prepare the function to retrieve the caller’s filename and/or method. This would be a static function somewhere in top-level of our module:

module MyModule
  def parse_caller
    # magic number 7 below is the amount of calls 
    #   on stack to unwind to get your caller
    if /^(?<file>.+?):(?<line>\d+)(?::in `(?<method>.*)')?/ =~ caller(7).first
      file      = Regexp.last_match[:file]
      line      = Regexp.last_match[:line].to_i
      method    = Regexp.last_match[:method]
      [file, line, method]
    end
  end
end

The magic number “7” there states for an amount of subcalls between our call and resulting Logger#add. We will examine the original caller of logger.debug method and reject all calls except of interesting ones.

The other thing we need is to override the formatter of our logger:

# put this after logger initialization
logger.level = Logger::DEBUG
logger.formatter = lambda do |sev, dt, prog, msg|
  f,l,m = parse_caller
  #↓↓↓↓↓↓↓↓↓↓↓↓ here goes the check ↓↓↓↓↓↓↓↓↓↓↓↓↓
  if (f =~ /newclass/i) && (m =~ /failed_method/)
    original_formatter.call(sev, dt, prog, msg) 
  end
end

I know it looks a weird hack, but it works fine. As soon as we don’t need debug logging at all, simply turn back to INFO level (and don’t forget to switch back to regular Logger#formatter):

logger.level = Logger::INFO
logger.formatter = Logger::Formatter.new