26

我有一个用 Sinatra 编写的小型网络服务器。我希望能够将消息记录到日志文件中。我已经阅读了http://www.sinatrarb.com/api/index.html和 www.sinatrarb.com/intro.html,我看到 Rack 有一个叫做 Rack::CommonLogger 的东西,但我找不到有关如何访问和使用它来记录消息的任何示例。我的应用程序很简单,因此我将其编写为顶级 DSL,但如果需要,我可以切换到从 SinatraBase 对其进行子类化。

4

5 回答 5

41

Rack::CommonLogger不会为您的主应用程序提供记录器,它只会像 Apache 那样记录请求。

自行查看代码:https ://github.com/rack/rack/blob/master/lib/rack/common_logger.rb

所有Rack应用程序都有使用 HTTP 请求 env 调用的 call 方法,如果您检查此中间件的 call 方法,会发生以下情况:

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这种情况下是主应用程序,中间件只是注册请求开始的时间,然后它对你的中间件进行分类,获取 [status, header, body] 三元组,然后使用这些参数调用私有日志方法,返回与您的应用首先返回的三倍相同。

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方法只是从请求环境中获取一些信息,并登录到构造函数调用中指定的记录器,如果没有记录器实例,那么它会转到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

希望这可以帮助。

于 2010-02-10T22:34:57.110 回答
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
于 2010-11-17T00:02:28.157 回答
2

我遵循了我在这篇文中找到的内容——摘录如下

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

然后使用putsor print。它对我有用。

于 2010-02-10T19:32:01.693 回答
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
于 2014-11-14T15:10:21.587 回答
0

如果您使用Passenger,重新打开STDOUT 并将其重定向到文件不是一个好主意。在我的情况下,它导致乘客没有启动。阅读https://github.com/phusion/passenger/wiki/Debugging-application-startup-problems#stdout-redirection了解此问题。

这将是正确的方法:

logger = ::File.open('log/sinatra.log', 'a+')
Sinatra::Application.use Rack::CommonLogger, logger
于 2016-05-25T08:18:50.513 回答