如何在独立的日志文件中记录 Rails 中的某些内容?

Posted

技术标签:

【中文标题】如何在独立的日志文件中记录 Rails 中的某些内容?【英文标题】:How to log something in Rails in an independent log file? 【发布时间】:2010-09-25 03:54:37 【问题描述】:

在 Rails 中,我想在不同的日志文件中记录一些信息,而不是标准的 development.log 或 production.log。我想从模型类中进行此日志记录。

【问题讨论】:

【参考方案1】:

在(比如说)app/models/special_log.rb 中定义一个记录器类:

class SpecialLog
  LogFile = Rails.root.join('log', 'special.log')
  class << self
    cattr_accessor :logger
    delegate :debug, :info, :warn, :error, :fatal, :to => :logger
  end
end

在(比如)config/initializers/special_log.rb 中初始化记录器:

SpecialLog.logger = Logger.new(SpecialLog::LogFile)
SpecialLog.logger.level = 'debug' # could be debug, info, warn, error or fatal

您可以在应用中的任何位置登录:

SpecialLog.debug("something went wrong")
# or
SpecialLog.info("life is good")

【讨论】:

【参考方案2】:

这是我的自定义记录器:

class DebugLog
  def self.debug(message=nil)
    return unless Rails.env.development? and message.present?
    @logger ||= Logger.new(File.join(Rails.root, 'log', 'debug.log'))
    @logger.debug(message) 
  end
end

【讨论】:

【参考方案3】:
class Post < ActiveRecord::Base
    def initialize(attributes)
        super(attributes)
        @logger = Logger.new("#Rails.root/log/post.log")
    end

    def logger
        @logger
    end

    def some_method
        logger.info('Test 1')
    end
end

ps = Post.new
ps.some_method
ps.logger.info('Test 2')
Post.new.logger.info('Test 3')

【讨论】:

【参考方案4】:

对我有用的一个不错的选择是在您的app/models 文件夹中添加一个相当简单的类,例如app/models/my_log.rb

class MyLog
  def self.debug(message=nil)
    @my_log ||= Logger.new("#Rails.root/log/my.log")
    @my_log.debug(message) unless message.nil?
  end
end

然后在您的控制器中,或者实际上几乎任何您可以从您的 rails 应用程序中引用模型类的地方,即您可以执行Post.create(:title =&gt; "Hello world", :contents =&gt; "Lorum ipsum"); 或类似操作的任何地方,您都可以像这样登录到您的自定义文件

MyLog.debug "Hello world"

【讨论】:

【参考方案5】:

我建议使用Log4r gem 进行自定义日志记录。从其页面引用描述:

Log4r 是一个全面而灵活的日志库,用 Ruby 编写,供使用 在 Ruby 程序中。它具有任意数量的分层日志记录系统 级别、自定义级别名称、记录器继承、多个输出目的地 每个日志事件、执行跟踪、自定义格式、线程安全性、XML 和 YAML 配置等等。

【讨论】:

【参考方案6】:

Logging 框架,其名称看似简单,却拥有您所渴望的复杂性!

按照logging-rails 的简短说明开始过滤噪音、获取警报并以细粒度和高级方式选择输出。

完成后拍拍自己的后背。日志滚动,每天。单凭这一点就值得。

【讨论】:

【参考方案7】:

更新

我根据以下解决方案制作了一个 gem,名为 multi_logger。只需在初始化程序中执行此操作:

MultiLogger.add_logger('post')

然后打电话

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

你就完成了。

如果您想自己编写代码,请参见下文:


更完整的解决方案是将以下内容放在您的 lib/config/initializers/ 目录中。

好处是您可以设置格式化程序以自动为日志添加时间戳或严重性前缀。这可以从 Rails 中的任何地方访问,并且使用单例模式看起来更整洁。

# 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

【讨论】:

#$$ 是干什么用的? @DanielCosta ***.com/questions/2177008/…【参考方案8】:

您可以从任何模型中自己创建一个 Logger 对象。只需将文件名传递给构造函数并像通常的 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

这里我使用了一个类属性来记忆记录器。这样就不会为创建的每个用户对象创建它,但您不需要这样做。还请记住,您可以将 my_logger 方法直接注入到 ActiveRecord::Base 类中(或者如果您不喜欢过多的猴子补丁,也可以注入到您自己的某个超类中)以在您的应用程序模型之间共享代码。

【讨论】:

如果您想更改该特定型号的所有默认日志记录,您可以简单地使用User.logger = Logger.new(STDOUT) 或任何您想登录的位置。同样,ActiveRecord::Base.logger = Logger.new(STDOUT) 将更改所有模型的所有日志记录。 有人知道如何为每个日志创建文件夹吗? @Dave 我试过你的建议,但失败了。 User.logger = Logger.new(STDOUT) 更改了所有模型的所有日志记录。嗯,改了ActiveRecord::Base.logger @ilzoff 是的,这种行为很可能自 3 年前以来在 Rails 中已经发生了变化。感谢您提出这个问题。 谢谢。通过将my_logger 放入application_controller.rb,对我的控制器做了几乎相同的操作。【参考方案9】:
class Article < ActiveRecord::Base  

      LOGFILE = File.join(RAILS_ROOT, '/log/', "article_#RAILS_ENV.log")  

      def validate  
        log "was validated!"  
      end   

      def log(*args)  
       args.size == 1 ? (message = args; severity = :info) : (severity, message = args)  
       Article.logger severity, "Article##self.id: #message"  
     end  

     def self.logger(severity = nil, message = nil)  
       @article_logger ||= Article.open_log  
       if !severity.nil? && !message.nil? && @article_logger.respond_to?(severity)  
         @article_logger.send severity, "[#Time.now.to_s(:db)] [#severity.to_s.capitalize] #message\n"  
       end  
       message or @article_logger  
     end  

     def self.open_log  
       ActiveSupport::BufferedLogger.new(LOGFILE)  
     end  

   end  

【讨论】:

以上是关于如何在独立的日志文件中记录 Rails 中的某些内容?的主要内容,如果未能解决你的问题,请参考以下文章

在控制台中禁用 Rails SQL 日志记录

如何在 Rails 开发中忽略延迟作业查询日志记录

Rails:在 lib 目录中记录代码?

如何过滤rails中的参数?

如何禁用某个列的 ActiveRecord 日志记录?

在 rails 3 中设置记录器