web-dev-qa-db-fra.com

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

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

145
akshat

Vous pouvez créer vous-même un objet Logger à partir de n'importe quel modèle. Il suffit de transmettre le nom du fichier au constructeur et d'utiliser l'objet comme d'habitude 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

Ici, j'ai utilisé un attribut de classe pour mémoriser l'enregistreur. Ainsi, il ne sera pas créé pour chaque objet utilisateur créé, mais vous n'êtes pas obligé de le faire. Rappelez-vous aussi que vous pouvez injecter le my_logger méthode directement dans le ActiveRecord::Base classe (ou dans une super-classe de votre propre si vous n'aimez pas trop singe patch) pour partager le code entre les modèles de votre application.

173
Thiago Arrais

Mettre à jour

J'ai créé une gemme basée sur la solution ci-dessous, appelée multi_logger . Faites 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 voulez le coder vous-même, voir ci-dessous:


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

L'avantage est que vous pouvez configurer le formateur pour préfixer les horodatages ou la gravité des journaux automatiquement. Ceci est accessible de n’importe où dans Rails et semble plus net en utilisant le motif 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
39
lulalala

Une option décente qui fonctionne pour moi est d’ajouter une classe assez simple à votre dossier app/models Telle que 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

puis dans votre contrôleur, ou à peu près partout où vous pourriez référencer la classe d'un modèle depuis votre Rails, c'est-à-dire n'importe où vous pouvez faire Post.create(:title => "Hello world", :contents => "Lorum ipsum"); ou quelque chose de similaire auquel vous pouvez vous connecter votre fichier personnalisé comme ça

MyLog.debug "Hello world"
37
Vaughn Draughon

Définissez une classe de consignateurs 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

initialiser le logger dans (par exemple) 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")
9
Les Nightingill

Voici mon logger 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
4
Dorian
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  
2
Tony

Je suggérerais d'utiliser Log4r gem 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 utilisation dans les programmes Ruby. Elle comporte un système de journalisation hiérarchique comprenant un nombre quelconque de niveaux, des noms de niveaux personnalisés). , héritage de journal, plusieurs destinations de sortie par événement de journal, suivi de l'exécution, formatage personnalisé, sécurité des threads, configuration XML et YAML, etc.

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

Le cadre de journalisation, avec son nom trompeusement simple, a la sophistication dont vous rêvez!

Suivez les instructions très courtes de logging-Rails pour commencer à filtrer le bruit, à recevoir des alertes et à choisir le résultat de manière fine et détaillée.

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

0
olleolleolle