2011-05-13 71 views
51

我無法弄清楚如何使用Sinatra記錄消息。我不想記錄請求,而是在我的應用中的某些點上定製消息。例如,在提取URL時,我想登錄"Fetching #{url}"登錄Sinatra?

這裏是想什麼我:

  • 指定日誌級別(例如:logger.info("Fetching #{url}"))的能力
  • 在開發和測試環境,該消息將被寫入控制檯。
  • 在生產中,只寫出符合當前日誌級別的消息。

我猜這可以很容易地在config.ru做,但我不知道我想啓用該設置100%,而如果我必須手動創建一個Logger對象本人(進而哪一類的Logger使用:Logger,Rack::LoggerRack::CommonLogger)。 (我知道在StackOverflow上有類似的問題,但是沒有人能夠直接回答我的問題,如果你能指出我現在的問題,我會把它標記爲重複的)。

回答

41

Sinatra 1.3將附帶這樣一個記錄器對象,與上面完全一樣。您可以按照「The Bleeding Edge」中所述使用邊緣Sinatra。我猜,在我們釋放1.3之前不會那麼久。

要與西納特拉1.2使用它,做這樣的事情:

require 'sinatra' 
use Rack::Logger 

helpers do 
    def logger 
    request.logger 
    end 
end 
+8

如果您包含有關如何設置記錄器目標(文件/ STDOUT)以及如何實際記錄('logger.info「foo」'?)的信息,這個答案會更有幫助。 ) – Phrogz 2011-05-13 19:51:25

+9

在github的Sinatra README中描述了用法:'logger.inf O( 「foo」 的)'。目的地由Web服務器設置(它使用機架錯誤流),你可以通過改變'env ['rack.errors']'來設置它。 – 2011-05-13 21:18:38

+2

因爲使用助手,這似乎只適用於請求上下文。它不適用於在應用程序的早期部分發生的事情(預先請求,應用程序設置等) – lfender6445 2016-03-15 15:08:13

15

我個人登錄西納特拉通過:

require 'sinatra' 
require 'sequel' 
require 'logger' 
class MyApp < Sinatra::Application 
    configure :production do 
    set :haml, { :ugly=>true } 
    set :clean_trace, true 

    Dir.mkdir('logs') unless File.exist?('logs') 

    $logger = Logger.new('logs/common.log','weekly') 
    $logger.level = Logger::WARN 

    # Spit stdout and stderr to a file during production 
    # in case something goes wrong 
    $stdout.reopen("logs/output.log", "w") 
    $stdout.sync = true 
    $stderr.reopen($stdout) 
    end 

    configure :development do 
    $logger = Logger.new(STDOUT) 
    end 
end 

# Log all DB commands that take more than 0.2s 
DB = Sequel.postgres 'mydb', user:'dbuser', password:'dbpass', host:'localhost' 
DB << "SET CLIENT_ENCODING TO 'UTF8';" 
DB.loggers << $logger if $logger 
DB.log_warn_duration = 0.2 
+8

爲什麼你一方面使用模塊化應用程序,另一方面使用全局變量來存儲記錄器? – 2011-05-13 21:22:08

+1

@Konstantin好問題。我爲簡單的config.ru MyApp.run做前者,但是我從來沒有在同一個進程中運行多個應用程序,所以醜陋的全局變量到目前爲止只是方便的懶惰。 – Phrogz 2011-05-13 22:09:03

+1

重新打開STDOUT會使乘客無法啓動:https://github.com/phusion/passenger/wiki/Debugging-application-startup-problems – fguillen 2013-12-11 19:30:54

3

這裏的另一種解決方案:

module MySinatraAppLogger 
    extend ActiveSupport::Concern 

    class << self 
    def logger_instance 
     @logger_instance ||= ::Logger.new(log_file).tap do |logger| 
     ::Logger.class_eval { alias :write :'<<' } 
     logger.level = ::Logger::INFO 
     end 
    end 

    def log_file 
     @log_file ||= File.new("#{MySinatraApp.settings.root}/log/#{MySinatraApp.settings.environment}.log", 'a+').tap do |log_file| 
     log_file.sync = true 
     end 
    end 
    end 

    included do 
    configure do 
     enable :logging 
     use Rack::CommonLogger, MySinatraAppLogger.logger_instance 
    end 

    before { env["rack.errors"] = MySinatraAppLogger.log_file } 
    end 

    def logger 
    MySinatraAppLogger.logger_instance 
    end 
end 

class MySinatraApp < Sinatra::Base 
    include MySinatraAppLogger 
    get '/' do 
    logger.info params.inspect 
    end 
end 

當然,你可以在沒有ActiveSupport :: Concern的情況下做到這一點將configurebefore塊直接插入到MySinatraApp中,但我喜歡這種方法是非常乾淨 - 所有日誌記錄配置完全從主應用程序類中抽象出來。

這也很容易找到你可以改變它。例如,SO詢問了如何在開發中登錄到控制檯。這裏很明顯,你需要做的只是在log_file方法中的一個if-then邏輯。

+0

Rack :: Logger流到'env ['rack.errors']' ,在先前的過濾器中覆蓋它的內容似乎是一個糟糕的主意。http://www.rubydoc.info/github/rack/rack/Rack/Loggerhttp://www.rubydoc.info/github/rack/rack/Rack/Logger – lfender6445 2016-03-15 15:50:34

+0

請修復鏈接 – 2016-03-16 15:40:57

+0

我不確定爲什麼這使得這是一個壞主意。你能提供更多的細節嗎? – 2016-03-16 15:41:15

2

如果你正在使用類似麒麟記錄或其他中間件尾部IO流,你可以輕鬆地設置一個記錄器stdout或stderr

# unicorn.rb 
stderr_path "#{app_root}/shared/log/unicorn.stderr.log" 
stdout_path "#{app_root}/shared/log/unicorn.stdout.log" 

# sinatra_app.rb 
set :logger, Logger.new(STDOUT) # STDOUT & STDERR is captured by unicorn 
logger.info('some info') # also accessible as App.settings.logger 

這可以讓你在應用範圍截取郵件,而不僅僅是作爲請求幫助程序訪問記錄器