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

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

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

4b9b3361

Ответ 1

Вы можете создать объект 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

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

Ответ 2

Обновление

Я сделал камень, основанный на нижеприведенном решении, называемом 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 и выглядит более аккуратно, используя шаблон 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

Ответ 3

Пригодный для меня вариант - просто добавить довольно простой класс в вашу папку 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"

Ответ 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

Ответ 5

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  

Ответ 6

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

Ответ 7

Я бы предложил использовать Log4r gem для пользовательского ведения журнала. Описание предложения со своей страницы:

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

Ответ 8

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')

Ответ 9

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

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

Постарайтесь на спине, когда закончите. Лог-прокат, ежедневно. Стоит только этого.