Odpowiedzi:
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_logger
metodę bezpośrednio do ActiveRecord::Base
klasy (lub do jakiejś własnej nadklasy, jeśli nie lubisz zbytnio małpować poprawek), aby udostępnić kod między modelami aplikacji.
User.logger = Logger.new(STDOUT)
zmienił wszystkie dzienniki dla wszystkich modeli. Cóż, to się zmieniłoActiveRecord::Base.logger
my_logger
w application_controller.rb
.
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
#{$$}
?
Przyzwoitą opcją, która działa dla mnie, jest po prostu dodanie do twojego app/models
folderu 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"
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")
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
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.
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.
User.logger = Logger.new(STDOUT)
lub gdziekolwiek chcesz się zalogować. W ten sam sposóbActiveRecord::Base.logger = Logger.new(STDOUT)
zmieni wszystkie rejestracje dla wszystkich modeli.