2010-11-04 34 views
8

Je suis en train de rencontrer un problème.Puis-je désactiver l'en-tête du journal pour ruby ​​logger?

Comme vous le savez peut-être, le logger ruby ​​ajoute un en-tête de journalisation en haut de chaque nouveau fichier journal.

"# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName] 

Je Logging des fichiers CSV pour les importer dans un entrepôt plus tard, habituellement je saute juste la première ligne avec l'en-tête. Il semble qu'il y ait un bogue dans l'enregistreur, car parfois l'en-tête de journalisation apparaît plus d'une fois, au beau milieu d'un fichier journal. J'ai donc décidé de laisser simplement cette tête dehors. À ma grande surprise, je n'ai trouvé aucun argument que l'on puisse passer à la création d'un enregistreur. J'ai pensé à quelque chose comme ceci:

Logger.new "info.log", :skip_header => true 

Mais ce n'est tout simplement pas là. Je cherchai dans les sources principales de rubis et étonnamment il n'y a vraiment rien qui pourrait empêcher l'enregistreur d'ajouter l'en-tête du journal:

def create_logfile(filename) 
    logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT)) 
    logdev.sync = true 
    add_log_header(logdev) 
    logdev 
end 

def add_log_header(file) 
    file.write(
    "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName] 
) 
end 

Est-ce que quelqu'un a une idée de ce que je pouvais faire, pour empêcher l'en-tête du journal? J'utilise Ruby 1.8.7 302 avec Rails 2.3.5 ici. Ignorer simplement les commentaires du côté de l'entrepôt n'est pas possible parce que je n'ai aucun contrôle sur le code, et il semble risqué de simplement l'ignorer, si quelque chose ne va pas avec une ligne d'enregistrement.

Est-ce que quelqu'un connaît un enregistreur qui le permet? Pensez-vous que ce serait une bonne idée d'utiliser et d'écrire simplement dans un fichier?

Merci à l'avance, Tommy

Répondre

7

Idéalement la méthode add_log_header sur l'instance Logger doivent être remplacées, mais depuis add_log_header est appelé initialize, vous êtes trop tard au moment où vous obtenez vos mains sur elle. Eh bien, vous pourriez juste remplacer la méthode add_log_header sur la classe.

class Logger::LogDevice 
    def add_log_header(file) 
    end 
end 

log1 = Logger.new('info1.log') 

Mais si votre application a besoin de plus de cas Logger après cela, ils se comporteront les mêmes: aucun en-tête. Pour éviter cela:

# dismantle the header and save it under another name 
class Logger::LogDevice 
    alias orig_add_log_header add_log_header 

    def add_log_header(file) 
    end 
end 

# Quick,create an instance 
log1 = Logger.new('test_log1file.log') 

# restore the old method: 
class Logger::LogDevice 
    alias add_log_header orig_add_log_header 
end 
+0

C'est génial, merci! Je n'ai pas pensé à "patcher monkey" l'enregistreur parce que c'est considéré comme sale. Mais avec votre approche, rien ne change pour les appels précédents et ultérieurs. Génial! –

2

Voici une solution qui implique le sous-classement Logger. Nous devons être sournois avec initialize et super pour l'empêcher de créer un standard Logger::LogDevice trop tôt.

class HeadlessLogger < Logger 
    def initialize(logdev, shift_age = 0, shift_size = 1048576) 
    super(nil) # this prevents it from initializing a LogDevice 
    if logdev 
     @logdev = HeadlessLogger::LogDevice.new(logdev, shift_age: shift_age, shift_size: shift_size) 
    end 
    end 

    class LogDevice < ::Logger::LogDevice 
    def add_log_header(file) ; end 
    end 
end 
2

Comme alternative à la correction de la classe de l'enregistreur, il suffit de ne le laissez pas créer le fichier journal en le touchant dès le départ:

FileUtils.touch logfile_path 
Logger.new logfile_path 

vous aurez besoin de require 'fileutils' de stdlib évidemment Ruby plaine.

Editer: Cela ne fonctionnera pas si vous utilisez la logrotation intégrée, ou le fichier est supprimé, car il n'y a pas de crochet sur rotation et il écrira alors encore l'en-tête.