Comment enregistrer quelque chose dans Rails dans un fichier journal indépendant?

157

Dans les rails, je souhaite enregistrer certaines informations dans un fichier journal différent et non dans le fichier standard development.log ou production.log. Je veux faire cette journalisation à partir d'une classe de modèle.

akshat
la source

Réponses:

187

Vous pouvez créer vous-même un objet Logger à partir de n'importe quel modèle. Passez simplement le nom du fichier au constructeur et utilisez l'objet comme les Rails habituels 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

Ici, j'ai utilisé un attribut de classe pour mémoriser l'enregistreur. De cette façon, il ne sera pas créé pour chaque objet User qui est créé, mais vous n'êtes pas obligé de le faire. Rappelez-vous également que vous pouvez injecter la my_loggerméthode directement dans la ActiveRecord::Baseclasse (ou dans une superclasse de votre choix si vous n'aimez pas trop les patchs de singe) pour partager le code entre les modèles de votre application.

Thiago Arrais
la source
5
Si vous souhaitez modifier toute la journalisation par défaut pour ce modèle spécifique, vous pouvez simplement utiliser User.logger = Logger.new(STDOUT)ou où vous souhaitez vous connecter. De la même manière, ActiveRecord::Base.logger = Logger.new(STDOUT)changera toute la journalisation pour tous les modèles.
Dave
Quelqu'un sait comment créer des dossiers pour chaque journal?
Mauro Dias
2
@Dave J'ai essayé votre suggestion et elle a échoué. User.logger = Logger.new(STDOUT)changé toute la journalisation pour tous les modèles. Eh bien, ça a changéActiveRecord::Base.logger
fetsh
@ilzoff Oui, il est fort possible que ce comportement ait changé dans Rails depuis 3 ans. Merci d'avoir appelé cela.
Dave
Merci. Est - ce à peu près la même chose pour mes contrôleurs en plaçant my_loggerdans application_controller.rb.
kstratis
40

Mettre à jour

J'ai créé un bijou basé sur la solution ci-dessous, appelé multi_logger . Faites simplement ceci dans l'initialiseur:

MultiLogger.add_logger('post')

et appeler

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

et vous avez terminé.

Si vous souhaitez le coder vous-même, voir ci-dessous:


Une solution plus complète serait de placer les éléments suivants dans votre répertoire lib/ou config/initializers/.

L'avantage est que vous pouvez configurer le formateur pour qu'il préfixe automatiquement les horodatages ou la gravité aux journaux. Ceci est accessible de n'importe où dans Rails et semble plus net en utilisant le modèle 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
la source
1
Quel est le #{$$}pour?
Daniel Costa
1
@DanielCosta stackoverflow.com/questions/2177008/…
lulalala
37

Une option décente qui fonctionne pour moi consiste simplement à ajouter une classe assez simple à votre app/modelsdossier, telle queapp/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

puis dans votre contrôleur, ou vraiment presque partout où vous pouvez référencer la classe d'un modèle à partir de votre application de rails, c'est-à-dire partout où vous pouvez faire Post.create(:title => "Hello world", :contents => "Lorum ipsum");ou quelque chose de similaire, vous pouvez vous connecter à votre fichier personnalisé comme celui-ci

MyLog.debug "Hello world"
Vaughn Draughon
la source
2
Solution intelligente et simple!
Anwar
9

Définissez une classe de journalisation dans (par exemple) 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

initialisez le logger dans (disons) config / initializers / special_log.rb:

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

N'importe où dans votre application, vous pouvez vous connecter avec:

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

Voici mon enregistreur personnalisé:

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
la source
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
la source
1

Je suggérerais d'utiliser la gemme Log4r pour la journalisation personnalisée. Citant la description de sa page:

Log4r est une bibliothèque de journalisation complète et flexible écrite en Ruby pour une utilisation dans les programmes Ruby. Il comprend un système de journalisation hiérarchique de n'importe quel nombre de niveaux, des noms de niveau personnalisés, l'héritage de l'enregistreur, plusieurs destinations de sortie par événement de journal, le suivi de l'exécution, le formatage personnalisé, la sécurité des threads, la configuration XML et YAML, etc.

Kangur
la source
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
la source
0

Le framework Logging, avec son nom trompeusement simple, a la sophistication dont vous rêvez!

Suivez les instructions très courtes des rails de journalisation pour commencer à filtrer le bruit, à recevoir des alertes et à choisir la sortie d'une manière fine et de haut niveau.

Tapotez-vous dans le dos lorsque vous avez terminé. Journal de roulement, tous les jours. Ça vaut le coup pour ça seul.

Olleolleolle
la source