2010-02-10 59 views
26

我有我與西納特拉寫了一個小的網絡服務器。我希望能夠將消息記錄到日誌文件中。我已經通過http://www.sinatrarb.com/api/index.html和www.sinatrarb.com/intro.html閱讀,我看到機架有一些所謂的機架:: CommonLogger,但我找不到它如何可以訪問和使用記錄消息的任何實例。我的應用程序很簡單,所以我寫了它作爲一個頂級DSL,但我可以切換到從SinatraBase繼承它,如果這是真實需要什麼樣的一部分。使用機架:: CommonLogger在西納特拉

回答

41

Rack::CommonLogger將不會對你的主要的應用程序提供了一個記錄器,它只會記錄,如Apache的要求會做。

檢查代碼自己:https://github.com/rack/rack/blob/master/lib/rack/common_logger.rb

所有Rack應用有獲得與HTTP請求ENV此調用的方法,如果您選中此中間件這個號召方法是發生了什麼:

def call(env) 
    began_at = Time.now 
    status, header, body = @app.call(env) 
    header = Utils::HeaderHash.new(header) 
    log(env, status, header, began_at) 
    [status, header, body] 
end 

@app在這種情況下是主要的應用程序,中間件是剛剛註冊的請求開始的時候,那麼它的類中間件獲得[狀態,頭部,身軀]三聯,然後調用專用日誌方法與參數,返回相同的三倍,你的a pp首先返回。

logger方法是這樣:

def log(env, status, header, began_at) 
    now = Time.now 
    length = extract_content_length(header) 

    logger = @logger || env['rack.errors'] 
    logger.write FORMAT % [ 
    env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-", 
    env["REMOTE_USER"] || "-", 
    now.strftime("%d/%b/%Y %H:%M:%S"), 
    env["REQUEST_METHOD"], 
    env["PATH_INFO"], 
    env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"], 
    env["HTTP_VERSION"], 
    status.to_s[0..3], 
    length, 
    now - began_at ] 
end 

正如你所知道的,log方法只抓住從請求ENV一些信息,並記錄在其上構造函數調用指定的記錄,如果有沒有記錄器實例,然後它去rack.errors記錄器(它似乎有一個默認情況下)

使用它(在你的config.ru)方式:

logger = Logger.new('log/app.log') 

use Rack::CommonLogger, logger 
run YourApp 

如果你想在所有的應用程序共同記錄器,你可以創建一個簡單的記錄器中間件:

class MyLoggerMiddleware 

    def initialize(app, logger) 
    @app, @logger = app, logger 
    end 

    def call(env) 
    env['mylogger'] = @logger 
    @app.call(env) 
    end 

end 

要使用它,在你的config.ru

logger = Logger.new('log/app.log') 
use Rack::CommonLogger, logger 
use MyLoggerMiddleware, logger 
run MyApp 

希望這有助於。

+4

MyLoggerMiddleware#call(env)的第一行不應該是: env ['rack.errors'] = @logger ? – 2010-02-12 19:49:59

+0

另外,我不想記錄每個請求,只是警告和錯誤消息。但我希望它是可配置的,以便我可以設置日誌級別,如在「調試」,「信息」,「警告」,「錯誤」,... BTW - 我的應用程序不是一個Rails應用程序。沒有config.ru文件。這是一個簡單的Sinatra應用程序。 我希望能夠使用現有的標準,但無法弄清楚是什麼。也許我必須拿着你給我看的CommonLogger,並且自己動手呢? – 2010-02-12 19:55:56

+0

'config.ru'是Rack的配置文件,不適用於Rails。 Sinatra和Rails都是基於機架的,所以你可以在Sinatra應用程序中使用'config.ru'。 – jafrog 2012-09-30 11:29:17

2

我跟我對這個blog後發現 - 摘錄如下

require 'rubygems' 
require 'sinatra' 

disable :run 
set :env, :production 
set :raise_errors, true 
set :views, File.dirname(__FILE__) + '/views' 
set :public, File.dirname(__FILE__) + '/public' 
set :app_file, __FILE__ 

log = File.new("log/sinatra.log", "a") 
STDOUT.reopen(log) 
STDERR.reopen(log) 

require 'app' 
run Sinatra.application 

然後用putsprint。它爲我工作。

+1

這一工程,但我真的很想了解如何使用機架:: CommonLogger發送帶有時間戳格式的郵件。 – 2010-02-10 21:53:45

15

在你config.ru

root = ::File.dirname(__FILE__) 
logfile = ::File.join(root,'logs','requests.log') 

require 'logger' 
class ::Logger; alias_method :write, :<<; end 
logger = ::Logger.new(logfile,'weekly') 

use Rack::CommonLogger, logger 

require ::File.join(root,'myapp') 
run MySinatraApp.new # Subclassed from Sinatra::Application 
+0

我嘗試你的解決方案,它的工作原理。我不知道爲什麼它必須在config.ru? – Chamnap 2011-05-10 04:13:38

+0

一個文件的事情我不是100%在那裏,你會介意評論什麼/爲什麼一些線路在那裏請嗎? – 2013-06-02 18:27:29

1
class ErrorLogger 
    def initialize(file) 
    @file = ::File.new(file, "a+") 
    @file.sync = true 
    end 

    def puts(msg) 
    @file.puts 
    @file.write("-- ERROR -- #{Time.now.strftime("%d %b %Y %H:%M:%S %z")}: ") 
    @file.puts(msg) 
    end 
end 


class App < Sinatra::Base 

    if production? 
    error_logger = ErrorLogger.new('log/error.log') 

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

    ... 

end