Как записать что-то в Rails в отдельный файл журнала?

157

В rails я хочу записать некоторую информацию в другой файл журнала, а не в стандартный файл development.log или production.log. Я хочу сделать эту запись из модельного класса.

Akshat
источник

Ответы:

187

Вы можете создать объект Logger самостоятельно из любой модели. Просто передайте имя файла конструктору и используйте объект как обычный 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

Здесь я использовал атрибут класса, чтобы запоминать регистратор. Таким образом, он не будет создан для каждого отдельного объекта User, который создается, но вы не обязаны это делать. Помните также, что вы можете внедрить my_loggerметод непосредственно в ActiveRecord::Baseкласс (или в какой-то собственный суперкласс, если вам не нравится слишком много патчить обезьяны), чтобы поделиться кодом между моделями вашего приложения.

Тьяго Арраис
источник
5
Если вы хотите изменить все журналы по умолчанию для этой конкретной модели, вы можете просто использовать User.logger = Logger.new(STDOUT)или куда вы хотите войти. Таким же образом ActiveRecord::Base.logger = Logger.new(STDOUT)будут меняться все журналы для всех моделей.
Дэйв
Кто-нибудь знает, как создавать папки для каждого журнала?
Мауро Диас
2
@ Дейв Я попробовал ваше предложение, но оно провалилось. User.logger = Logger.new(STDOUT)поменял все логи для всех моделей. Ну, это изменилосьActiveRecord::Base.logger
fetsh
@ilzoff Да, вполне возможно, что это поведение изменилось в Rails с 3 лет назад. Спасибо за это.
Дэйв
Спасибо. Сделал почти то же самое для моих контроллеров, вставив my_loggerв application_controller.rb.
Кстратис
40

Обновить

Я сделал драгоценный камень, основанный на решении ниже, названный multi_logger . Просто сделайте это в инициализаторе:

MultiLogger.add_logger('post')

и позвонить

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

и вы сделали.

Если вы хотите написать код самостоятельно, см. Ниже:


Более полное решение было бы разместить следующее в вашем каталоге lib/или config/initializers/.

Преимущество заключается в том, что вы можете настроить форматирование так, чтобы оно автоматически добавляло метки времени или серьезность в журналы. Это доступно из любой точки Rails и выглядит более аккуратно, если использовать шаблон синглтона.

# 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
источник
1
Для чего #{$$}?
Даниэль Коста
1
@DanielCosta stackoverflow.com/questions/2177008/…
lulalala
37

Приличный вариант, который мне подходит, это просто добавить довольно простой класс в вашу app/modelsпапку, такой как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

затем в вашем контроллере, или практически в любом месте, где вы можете ссылаться на класс модели из вашего приложения rails, то есть где бы вы Post.create(:title => "Hello world", :contents => "Lorum ipsum");ни делали или что-то подобное, вы можете войти в свой пользовательский файл, например так

MyLog.debug "Hello world"
Вон Драугон
источник
2
Умное и простое решение!
Анвар
9

Определите класс логгера в (скажем) 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

инициализировать регистратор в (скажем) config / initializers / special_log.rb:

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

В любом месте вашего приложения вы можете войти с помощью:

SpecialLog.debug("something went wrong")
# or
SpecialLog.info("life is good")
Les Nightingill
источник
4

Вот мой пользовательский логгер:

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
Дориан
источник
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  
Тони
источник
1

Я бы предложил использовать Gem Log4r для пользовательских журналов. Цитирую описание со своей страницы:

Log4r - это всеобъемлющая и гибкая библиотека журналов, написанная на Ruby для использования в программах на Ruby. Он имеет иерархическую систему ведения журналов любого количества уровней, имен пользовательских уровней, наследования регистратора, нескольких выходных назначений для каждого события журнала, трассировки выполнения, настраиваемого форматирования, безопасности потоков, конфигурации XML и YAML и многого другого.

Kangur
источник
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')
КГ
источник
0

Фреймворк Logging, с его обманчиво простым именем, обладает утонченностью, которой вы жаждете!

Следуйте очень коротким инструкциям рельсов регистрации, чтобы начать отфильтровывать шум, получать оповещения и выбирать выходные данные детальным и высокоуровневым способом.

По окончании погладьте себя по спине. Бревно, ежедневно. Стоит только этого.

olleolleolle
источник