2011-05-13 72 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 

这可以让你在应用范围截取邮件,而不仅仅是作为请求帮助程序访问记录器