How to log something in Rails in an independent log file?

前端 未结 9 1246
栀梦
栀梦 2020-11-30 17:12

In rails I want to log some information in a different log file and not the standard development.log or production.log. I want to do this logging from a model class.

相关标签:
9条回答
  • 2020-11-30 17:39

    You can create a Logger object yourself from inside any model. Just pass the file name to the constructor and use the object like the usual Rails logger:

    class User < ActiveRecord::Base
      def my_logger
        @@my_logger ||= Logger.new("#{Rails.root}/log/my.log")
      end
    
      def before_save
        my_logger.info("Creating user with name #{self.name}")
      end
    end
    

    Here I used a class attribute to memoize the logger. This way it won't be created for every single User object that gets created, but you aren't required to do that. Remember also that you can inject the my_logger method directly into the ActiveRecord::Base class (or into some superclass of your own if you don't like to monkey patch too much) to share the code between your app's models.

    0 讨论(0)
  • 2020-11-30 17:41

    Update

    I made a gem based on the solution below, called multi_logger. Just do this in the initializer:

    MultiLogger.add_logger('post')
    

    and call

    Rails.logger.post.error('hi')
    # or call logger.post.error('hi') if it is accessible.
    

    and you are done.

    If you want to code it yourself, see below:


    A more complete solution would be to place the following in your lib/ or config/initializers/ directory.

    The benefit is that you can setup formatter to prefix timestamps or severity to the logs automatically. This is accessible from anywhere in Rails, and looks neater by using the singleton pattern.

    # Custom Post logger
    require 'singleton'
    class PostLogger < Logger
      include Singleton
    
      def initialize
        super(Rails.root.join('log/post_error.log'))
        self.formatter = formatter()
        self
      end
    
      # Optional, but good for prefixing timestamps automatically
      def formatter
        Proc.new{|severity, time, progname, msg|
          formatted_severity = sprintf("%-5s",severity.to_s)
          formatted_time = time.strftime("%Y-%m-%d %H:%M:%S")
          "[#{formatted_severity} #{formatted_time} #{$$}] #{msg.to_s.strip}\n"
        }
      end
    
      class << self
        delegate :error, :debug, :fatal, :info, :warn, :add, :log, :to => :instance
      end
    end
    
    PostLogger.error('hi')
    # [ERROR 2012-09-12 10:40:15] hi
    
    0 讨论(0)
  • 2020-11-30 17:46

    I would suggest using Log4r gem for custom logging. Quoting description from its page:

    Log4r is a comprehensive and flexible logging library written in Ruby for use in Ruby programs. It features a hierarchical logging system of any number of levels, custom level names, logger inheritance, multiple output destinations per log event, execution tracing, custom formatting, thread safteyness, XML and YAML configuration, and more.

    0 讨论(0)
提交回复
热议问题