Logging in Sinatra?

前端 未结 4 1619
囚心锁ツ
囚心锁ツ 2020-12-02 10:49

I\'m having trouble figuring out how to log messages with Sinatra. I\'m not looking to log requests, but rather custom messages at certain points in my app. For example, whe

相关标签:
4条回答
  • 2020-12-02 10:50

    If you are using something like unicorn logging or other middleware that tails IO streams, you can easily set up a logger to STDOUT or 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
    

    this allows you to intercept messages at application scope, rather than just having access to logger as request helper

    0 讨论(0)
  • 2020-12-02 10:56

    I personally log in Sinatra via:

    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
    
    0 讨论(0)
  • 2020-12-02 11:02

    Here's another solution:

    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
    

    Of course, you can do it without ActiveSupport::Concern by putting the configure and before blocks straight into MySinatraApp, but what I like about this approach is that it's very clean--all logging configuration is totally abstracted out of the main app class.

    It's also very easy to spot where you can change it. For instance, the SO asked about making it log to console in development. It's pretty obvious here that all you need to do is a little if-then logic in the log_file method.

    0 讨论(0)
  • 2020-12-02 11:09

    Sinatra 1.3 will ship with such a logger object, exactly usable as above. You can use edge Sinatra as described in "The Bleeding Edge". Won't be that long until we'll release 1.3, I guess.

    To use it with Sinatra 1.2, do something like this:

    require 'sinatra'
    use Rack::Logger
    
    helpers do
      def logger
        request.logger
      end
    end
    
    0 讨论(0)
提交回复
热议问题