¿Cómo registrar algo en Rails en un archivo de registro independiente?

157

En rails, quiero registrar cierta información en un archivo de registro diferente y no en el desarrollo estándar .log o production.log. Quiero hacer este registro desde una clase de modelo.

akshat
fuente

Respuestas:

187

Puede crear un objeto Logger usted mismo desde cualquier modelo. Simplemente pase el nombre del archivo al constructor y use el objeto como los Rails habituales 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

Aquí utilicé un atributo de clase para memorizar el registrador. De esta manera, no se creará para cada objeto de usuario que se cree, pero no es necesario que lo haga. Recuerde también que puede inyectar el my_loggermétodo directamente en la ActiveRecord::Baseclase (o en alguna superclase propia si no le gusta demasiado el parche de mono) para compartir el código entre los modelos de su aplicación.

Thiago Arrais
fuente
55
Si desea cambiar todos los registros predeterminados para ese modelo específico, simplemente puede usar User.logger = Logger.new(STDOUT)o donde quiera iniciar sesión. Del mismo modo, ActiveRecord::Base.logger = Logger.new(STDOUT)cambiará todo el registro de todos los modelos.
Dave
¿Alguien sabe cómo crear carpetas para cada registro?
Mauro Dias
2
@Dave He probado tu sugerencia y falló. User.logger = Logger.new(STDOUT)cambió todo el registro para todos los modelos. Bueno, cambióActiveRecord::Base.logger
fetsh
@ilzoff Sí, es muy posible que este comportamiento haya cambiado en Rails desde hace 3 años. Gracias por llamar esto.
Dave
Gracias. Hizo más o menos lo mismo para mis controladores colocando my_loggeren application_controller.rb.
kstratis
40

Actualizar

Hice una gema basada en la solución a continuación, llamada multi_logger . Solo haz esto en el inicializador:

MultiLogger.add_logger('post')

y llama

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

y listo

Si desea codificarlo usted mismo, consulte a continuación:


Una solución más completa sería colocar lo siguiente en su lib/o config/initializers/directorio.

El beneficio es que puede configurar el formateador para prefijar las marcas de tiempo o la gravedad de los registros automáticamente. Esto es accesible desde cualquier lugar en Rails, y se ve más ordenado usando el patrón 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
lulalala
fuente
1
¿Para qué sirve #{$$}?
Daniel Costa
1
@DanielCosta stackoverflow.com/questions/2177008/…
lulalala
37

Una opción decente que funciona para mí es agregar una clase bastante simple a su app/modelscarpeta, comoapp/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

luego en su controlador, o realmente en casi cualquier lugar donde pueda hacer referencia a la clase de un modelo desde su aplicación rails, es decir, en cualquier lugar que pueda hacer Post.create(:title => "Hello world", :contents => "Lorum ipsum");o algo similar, puede iniciar sesión en su archivo personalizado de esta manera

MyLog.debug "Hello world"
Vaughn Draughon
fuente
2
¡Solución inteligente y simple!
Anwar
9

Defina una clase de registrador en (digamos) 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

Inicialice el registrador en (digamos) config / initializers / special_log.rb:

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

En cualquier lugar de su aplicación, puede iniciar sesión con:

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

Aquí está mi registrador personalizado:

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
dorio
fuente
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
fuente
1

Sugeriría usar la gema Log4r para el registro personalizado. Descripción de la cita de su página:

Log4r es una biblioteca de registro completa y flexible escrita en Ruby para usar en programas Ruby. Cuenta con un sistema de registro jerárquico de cualquier número de niveles, nombres de nivel personalizados, herencia del registrador, múltiples destinos de salida por evento de registro, seguimiento de ejecución, formato personalizado, seguridad de subprocesos, configuración XML y YAML, y más.

Kangur
fuente
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
fuente
0

¡El marco de registro, con su nombre engañosamente simple, tiene la sofisticación que anhelas!

Siga las instrucciones breves de los rieles de inicio de sesión para comenzar a filtrar el ruido, recibir alertas y elegir la salida de una manera fina y de alto nivel.

Date una palmadita en la espalda cuando hayas terminado. Rollo de registro, todos los días. Vale la pena por eso solo.

olleolleolle
fuente