Come registrare qualcosa in Rails in un file di registro indipendente?


157

In rails voglio registrare alcune informazioni in un diverso file di log e non nello standard development.log o production.log. Voglio fare questo logging da una classe di modello.

Risposte:


187

È possibile creare un oggetto Logger da soli all'interno di qualsiasi modello. Basta passare il nome del file al costruttore e usare l'oggetto come i soliti 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

Qui ho usato un attributo di classe per memorizzare il logger. In questo modo non verrà creato per ogni singolo oggetto utente che viene creato, ma non è necessario farlo. Ricorda anche che puoi inserire il my_loggermetodo direttamente nella ActiveRecord::Baseclasse (o in una tua superclasse se non ti piace scimmiottare troppo la patch) per condividere il codice tra i modelli della tua app.


5
Se si desidera modificare tutta la registrazione predefinita per quel modello specifico, è possibile utilizzare semplicemente User.logger = Logger.new(STDOUT)o ovunque si desidera accedere. Allo stesso modo, ActiveRecord::Base.logger = Logger.new(STDOUT)cambierà tutta la registrazione per tutti i modelli.
Dave,

Qualcuno sa come creare cartelle per ogni registro?
Mauro Dias,

2
@Dave Ho provato il tuo suggerimento e non è riuscito. User.logger = Logger.new(STDOUT)ha cambiato tutta la registrazione per tutti i modelli. Bene, è cambiatoActiveRecord::Base.logger
fetsh

@ilzoff Sì, è possibile che questo comportamento sia cambiato in Rails da 3 anni fa. Grazie per averlo chiamato.
Dave,

Grazie. Ha fatto più o meno lo stesso per i miei controllori mettendo my_loggerin application_controller.rb.
kstratis,

40

Aggiornare

Ho creato un gioiello basato sulla soluzione di seguito, chiamata multi_logger . Basta fare questo nell'inizializzatore:

MultiLogger.add_logger('post')

e chiama

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

e il gioco è fatto.

Se vuoi codificarlo tu stesso, vedi sotto:


Una soluzione più completa sarebbe quella di inserire quanto segue nel tuo lib/ o config/initializers/directory.

Il vantaggio è che è possibile impostare il formattatore in modo da aggiungere automaticamente il prefisso ai timestamp o alla gravità. Questo è accessibile da qualsiasi punto di Rails e sembra più ordinato usando il modello singleton.

# 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

1
A cosa serve #{$$}?
Daniel Costa,


37

Un'opzione decente che funziona per me è semplicemente aggiungere una classe abbastanza semplice alla tua app/modelscartella comeapp/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

quindi nel tuo controller o quasi ovunque tu possa fare riferimento alla classe di un modello dall'app Rails, ovvero ovunque tu possa fare Post.create(:title => "Hello world", :contents => "Lorum ipsum");o qualcosa di simile puoi accedere al tuo file personalizzato come questo

MyLog.debug "Hello world"

2
Soluzione intelligente e semplice!
Anwar,

9

Definire una classe logger in (diciamo) 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

inizializza il logger in (diciamo) config / initializer / special_log.rb:

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

Ovunque nella tua app, puoi accedere con:

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

4

Ecco il mio logger personalizzato:

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

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  

1

Suggerirei di utilizzare Log4r gem per la registrazione personalizzata. Citando la descrizione dalla sua pagina:

Log4r è una libreria di registrazione completa e flessibile scritta in Ruby per l'uso nei programmi Ruby. È dotato di un sistema di registrazione gerarchico di qualsiasi numero di livelli, nomi di livello personalizzati, eredità del logger, destinazioni di output multiple per evento di registro, traccia di esecuzione, formattazione personalizzata, sicurezza dei thread, configurazione XML e YAML e altro ancora.


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')

0

Il framework di registrazione, con il suo nome ingannevolmente semplice, ha la raffinatezza che brami!

Seguire le istruzioni molto brevi delle guide di accesso per iniziare a filtrare il rumore, ricevere avvisi e scegliere l'output in modo dettagliato e di alto livello.

Pat te sulla schiena quando hai finito. Log-rolling, tutti i giorni. Ne vale la pena da solo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.