Bagaimana cara log sesuatu di Rails di file log independen?

157

Dalam rails saya ingin mencatat beberapa informasi dalam file log yang berbeda dan bukan development.log standar atau production.log. Saya ingin melakukan logging ini dari kelas model.

akshat
sumber

Jawaban:

187

Anda dapat membuat objek Logger sendiri dari dalam model apa pun. Cukup berikan nama file ke konstruktor dan gunakan objek seperti Rails biasa 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

Di sini saya menggunakan atribut class untuk memoize the logger. Dengan cara ini tidak akan dibuat untuk setiap objek Pengguna tunggal yang akan dibuat, tetapi Anda tidak diharuskan untuk melakukannya. Ingat juga bahwa Anda dapat menyuntikkan my_loggermetode secara langsung ke dalam ActiveRecord::Basekelas (atau ke dalam superkelas Anda sendiri jika Anda tidak suka terlalu banyak menambal monyet) untuk membagikan kode di antara model aplikasi Anda.

Thiago Arrais
sumber
5
Jika Anda ingin mengubah semua pencatatan standar untuk model spesifik itu, Anda bisa menggunakan User.logger = Logger.new(STDOUT)atau ke mana pun Anda ingin masuk. Dengan cara yang sama, ActiveRecord::Base.logger = Logger.new(STDOUT)akan mengubah semua pencatatan untuk semua model.
Dave
Adakah yang tahu cara membuat folder untuk setiap log?
Mauro Dias
2
@Dave Saya sudah mencoba saran Anda dan gagal. User.logger = Logger.new(STDOUT)mengubah semua pencatatan untuk semua model. Yah, itu berubahActiveRecord::Base.logger
fetsh
@ilzoff Yap, sangat mungkin perilaku ini telah berubah di Rails sejak 3 tahun yang lalu. Terima kasih telah memanggil ini.
Dave
Terima kasih. Apakah hampir sama untuk pengendali saya dengan menempatkan my_loggerdi application_controller.rb.
kstratis
40

Memperbarui

Saya membuat permata berdasarkan solusi di bawah ini, yang disebut multi_logger . Lakukan ini di penginisialisasi:

MultiLogger.add_logger('post')

dan telepon

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

dan kamu selesai.

Jika Anda ingin membuat kode sendiri, lihat di bawah:


Solusi yang lebih lengkap adalah dengan menempatkan yang berikut ini di direktori lib/atau Anda config/initializers/.

Keuntungannya adalah Anda dapat mengatur formatter untuk membuat awalan cap waktu atau tingkat keparahan ke log secara otomatis. Ini dapat diakses dari mana saja di Rails, dan terlihat lebih rapi dengan menggunakan pola tunggal.

# 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
lalalala
sumber
1
Untuk apa #{$$}?
Daniel Costa
1
@DanielCosta stackoverflow.com/questions/2177008/…
lulalala
37

Opsi yang layak yang berfungsi untuk saya adalah menambahkan kelas yang cukup sederhana ke app/modelsfolder Anda sepertiapp/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

kemudian di controller Anda, atau benar-benar hampir di mana saja Anda bisa mereferensikan kelas model dari dalam aplikasi rails Anda, yaitu di mana pun Anda bisa melakukan Post.create(:title => "Hello world", :contents => "Lorum ipsum");atau sesuatu yang serupa Anda dapat masuk ke file kustom Anda seperti ini

MyLog.debug "Hello world"
Vaughn Draughon
sumber
2
Solusi cerdas dan sederhana!
Anwar
9

Tentukan kelas logger di (katakanlah) 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

inisialisasi logger di (katakanlah) config / initializers / special_log.rb:

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

Di mana saja di aplikasi Anda, Anda dapat masuk dengan:

SpecialLog.debug("something went wrong")
# or
SpecialLog.info("life is good")
Les Nightingill
sumber
4

Berikut ini logger khusus saya:

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
Dorian
sumber
2
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  
Tony
sumber
1

Saya akan menyarankan menggunakan permata Log4r untuk penebangan kustom. Mengutip deskripsi dari halamannya:

Log4r adalah perpustakaan logging komprehensif dan fleksibel yang ditulis dalam Ruby untuk digunakan dalam program Ruby. Ini fitur sistem pencatatan hierarkis sejumlah tingkat, nama tingkat kustom, warisan logger, beberapa tujuan output per peristiwa log, pelacakan eksekusi, pemformatan kustom, keselamatan thread, konfigurasi XML dan YAML, dan banyak lagi.

Kangur
sumber
1
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')
hlcs
sumber
0

Kerangka Penebangan, dengan nama yang tampak sederhana, memiliki kecanggihan yang Anda idamkan!

Ikuti instruksi sangat singkat dari logging-rails untuk memulai menyaring kebisingan, mendapatkan peringatan, dan memilih output dengan cara yang halus dan tingkat tinggi.

Tepuk-tepuk diri Anda sendiri ketika Anda selesai. Log-rolling, setiap hari. Layak untuk itu saja.

olleolleolle
sumber