2010-02-10 50 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