6

I'm writing a rake, just wondering if I can configure Ruby logger, to log to different files based on different logging level.

E.g.

# log to info.log
logger.info "processing: 1/10"
logger.info "processing: 2/10"
logger.info "processing: 3/10"
...

# log to error.log
logger.error "Validation failed on :email"
logger.error "Validation failed on :name"

Update

I was gonna find an inherent solution, and looks like there is none. Thanks for @spickermann's quick answer, and I'll flow his thought to tweak my own version.

Here is the final code, if someone need it.

require 'logger'

class DistinctFileLogger
  LOG_LEVEL = [:debug , :info , :warn , :error , :fatal , :unknown]

  def initialize(path)
    @loggers = {}
    LOG_LEVEL.each do |level|
      @loggers[level] = Logger.new(path)
    end
  end

  LOG_LEVEL.each do |level|
    define_method(level) do |message|
      @loggers[level].send(level, message)
    end

    define_method("set_#{level}_path") do |path|
      @loggers[level] = Logger.new(path)
    end
  end
end

logger = DistinctFileLogger.new(STDOUT)
logger.set_error_path("{path_to}/error.log")

logger.info "processing: 1/10"
logger.info "processing: 2/10"
logger.info "processing: 3/10"

# STDOUT
# I, [2015-12-10T22:30:06.749612 #63303]  INFO -- : processing: 1/10
# I, [2015-12-10T22:30:06.749672 #63303]  INFO -- : processing: 2/10
# I, [2015-12-10T22:30:06.749692 #63303]  INFO -- : processing: 3/10

logger.error "Validation failed on :email"
logger.error "Validation failed on :name"

# error.log
# # Logfile created on 2015-12-10 22:30:06 +0800 by logger.rb/47272
# E, [2015-12-10T22:30:06.749708 #63303] ERROR -- : Validation failed on :email
# E, [2015-12-10T22:30:06.749729 #63303] ERROR -- : Validation failed on :name

1 Answer 1

6

Define your own custom logger class:

require 'logger'

class DistinctFileLogger
  LOG_LEVEL = [:debug , :info , :warn , :error , :fatal , :unknown]

  def initialize(path)
    @loggers = {}

    LOG_LEVEL.each do |level|
      @loggers[level] = Logger.new("#{path}/#{level}.log")
    end
  end

  LOG_LEVEL.each do |level|
    define_method(level) do |message|
      @loggers[level].send(level, message)
    end
  end
end

Then configure your app to use this custom logger instead of the original. In Rails – for example - this– can be done in your environment config:

Rails.logger = DistinctFileLogger.new(Rails.root.join('log'))
Sign up to request clarification or add additional context in comments.

3 Comments

Typo: LOG_LEVEL.each do do |level| (first occurence) has a redundant do.
Thanks for the quick answer, please update code @loggers[level].send(level, message) and initialize. Maybe also require 'logger' to make it run.
Last typo: @logger :P

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.