Jak zarejestrować coś w Railsach w niezależnym pliku dziennika?

157

W railsach chcę zapisywać pewne informacje w innym pliku dziennika, a nie w standardowym dzienniku development.log czy production.log. Chcę zrobić to rejestrowanie z klasy modelu.

akszat
źródło

Odpowiedzi:

187

Możesz samodzielnie utworzyć obiekt Loggera z wnętrza dowolnego modelu. Po prostu przekaż nazwę pliku do konstruktora i użyj obiektu jak zwykłe Railsy 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

Tutaj użyłem atrybutu klasy, aby zapamiętać rejestrator. W ten sposób nie zostanie utworzony dla każdego pojedynczego obiektu użytkownika, który zostanie utworzony, ale nie jest to wymagane. Pamiętaj również, że możesz wstrzyknąć my_loggermetodę bezpośrednio do ActiveRecord::Baseklasy (lub do jakiejś własnej nadklasy, jeśli nie lubisz zbytnio małpować poprawek), aby udostępnić kod między modelami aplikacji.

Thiago Arrais
źródło
5
Jeśli chcesz zmienić wszystkie domyślne rejestrowanie dla tego konkretnego modelu, możesz po prostu użyć User.logger = Logger.new(STDOUT)lub gdziekolwiek chcesz się zalogować. W ten sam sposób ActiveRecord::Base.logger = Logger.new(STDOUT)zmieni wszystkie rejestracje dla wszystkich modeli.
Dave
Czy ktoś wie, jak tworzyć foldery w każdym dzienniku?
Mauro Dias
2
@Dave Wypróbowałem twoją sugestię i nie udało się. User.logger = Logger.new(STDOUT)zmienił wszystkie dzienniki dla wszystkich modeli. Cóż, to się zmieniłoActiveRecord::Base.logger
fetsh
@ilzoff Tak, całkiem możliwe, że to zachowanie zmieniło się w Railsach od 3 lat. Dzięki za wezwanie tego.
Dave
Dzięki. Czy bardzo podobne do moich kontrolerami poprzez umieszczenie my_loggerw application_controller.rb.
kstratis
40

Aktualizacja

Klejnot wykonałem w oparciu o poniższe rozwiązanie o nazwie multi_logger . Po prostu zrób to w inicjatorze:

MultiLogger.add_logger('post')

i zadzwoń

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

i gotowe.

Jeśli chcesz to samodzielnie zakodować, zobacz poniżej:


Bardziej kompletnym rozwiązaniem byłoby umieszczenie następujących elementów w katalogu lib/lub config/initializers/.

Zaletą jest to, że można skonfigurować program formatujący, aby automatycznie poprzedzał sygnatury czasowe lub ważność w dziennikach. Jest to dostępne z dowolnego miejsca w Railsach i wygląda ładniej dzięki zastosowaniu wzorca 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
źródło
1
Do czego służy #{$$}?
Daniel Costa
1
@DanielCosta stackoverflow.com/questions/2177008/…
lulalala
37

Przyzwoitą opcją, która działa dla mnie, jest po prostu dodanie do twojego app/modelsfolderu dość prostej klasy, takiej jakapp/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

wtedy w twoim kontrolerze lub prawie wszędzie, gdzie możesz odwołać się do klasy modelu z poziomu aplikacji railsowej, tj. gdziekolwiek możesz zrobić Post.create(:title => "Hello world", :contents => "Lorum ipsum");lub coś podobnego możesz zalogować się do swojego niestandardowego pliku w ten sposób

MyLog.debug "Hello world"
Vaughn Draughon
źródło
2
Sprytne i proste rozwiązanie!
Anwar
9

Zdefiniuj klasę rejestratora w (powiedzmy) 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

zainicjuj rejestrator w (powiedzmy) config / initializers / special_log.rb:

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

W dowolnym miejscu aplikacji możesz zalogować się za pomocą:

SpecialLog.debug("something went wrong")
# or
SpecialLog.info("life is good")
Les Nightingill
źródło
4

Oto mój niestandardowy rejestrator:

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
dorycki
źródło
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
źródło
1

Sugerowałbym użycie klejnotu Log4r do niestandardowego logowania. Cytując opis z jego strony:

Log4r to wszechstronna i elastyczna biblioteka logowania napisana w języku Ruby do użytku w programach Ruby. Zawiera hierarchiczny system rejestrowania o dowolnej liczbie poziomów, niestandardowe nazwy poziomów, dziedziczenie rejestratorów, wiele miejsc docelowych danych wyjściowych na zdarzenie dziennika, śledzenie wykonywania, niestandardowe formatowanie, bezpieczeństwo wątków, konfigurację XML i YAML i nie tylko.

Kangur
źródło
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
źródło
0

Framework Logging, ze swoją zwodniczo prostą nazwą, ma wyrafinowanie, którego pragniesz!

Postępuj zgodnie z bardzo krótkimi instrukcjami logowania do szyn, aby rozpocząć odfiltrowywanie szumów, otrzymywanie alertów i wybieranie wyników w drobnoziarnisty i wysokopoziomowy sposób.

Gdy skończysz, poklep się po plecach. Codzienne przewijanie dziennika. Warto tylko za to.

olleolleolle
źródło