How do I access Sinatra's Logger outside the Request Scope

后端 未结 2 777
悲&欢浪女
悲&欢浪女 2021-02-20 18:12

It seems that Sinatra\'s logger is only available inside request handlers (See https://github.com/sinatra/sinatra#logging), but what if I want to use a logger in other places, f

相关标签:
2条回答
  • 2021-02-20 18:52

    The accepted answer didn't quite work for me, so I came up with the following:

    class AppLogger
      extend SingleForwardable
    
      def_delegators :logger, :info, :error, :warn, :level
    
      class << self
        def logger
          return @_logger if @_logger
    
          @_logger = Logger.new STDOUT
          @_logger.level = Logger::INFO
        end
    
        def suppress_logging
          logger.level = Logger::FATAL
        end
      end
    end
    

    suppress_logging is useful for keeping specs quiet.

    In the app init:

    set :logging, AppLogger.logger
    

    From a request:

    logger.info "Can't touch this."
    

    From a class that does not have access to the logger:

    AppLogger.info "You've got mail."
    

    And, RSpec mock:

    let( :logger ){ double 'logger' }
    
    before do
      allow( AppLogger ).to receive( :logger ).and_return logger
      allow( logger ).to receive :error
    end
    
    specify 'logs error' do
      post '/raise/error'
    
      expect( logger ).to have_received( :error ).with 'An error has occured.'
    end
    
    0 讨论(0)
  • 2021-02-20 19:12

    The docs give some examples on scope, but you can see the logger helper within methods defined in the helper block, as the helper block has Application scope. Within configure it's not available, but what I tend to do is set up my own logging anyway, within the rackup file as a constant or class instance variable, and then it's available within configure (and anywhere else). As an example for just a single application:

    require 'sinatra'
    require 'logger'
    
    configure do
      set :logging, nil
      logger = Logger.new STDOUT
      logger.level = Logger::INFO
      logger.datetime_format = '%a %d-%m-%Y %H%M '
      set :logger, logger
    end
    
    helpers do
      def check
        settings.logger.info "I'm inside a helper"
        # if you were using Sinatra's logger, you could just call
        # logger.info "I'm inside a helper"
        # and it would work, but only if you've not done the stuff above
        # in the configure block
      end
    end
    
    get "/" do
      check # this would work for the way above, or with the Sinatra logger
      "Hello, World!"
    end
    
    get "/another" do
      settings.logger.info "Using the settings helper this time" # this only works
      # when you've defined your own logger
      "Hello again"
    end
    

    An example as a class instance variable as a better "global":

    class MyLogger
      def self.logger
        if @_logger.nil?
          @_logger = Logger.new STDOUT
          @_logger.level = Logger::INFO
          @_logger.datetime_format = '%a %d-%m-%Y %H%M '
        end
        @_logger
      end
    end
    

    and then use wherever needed:

    configure do
      set :logging, nil
      logger = MyLogger.logger
      set :logger, logger
    end
    

    or in a class:

    class AnotherClass
    
      def some_method
        MyLogger.logger.warn "I'm in some method"
      end
    

    Sinatra also comes (since 1.3) with a helper for logging, and here is a recipe for logging to STDOUT and a file that you may find useful too.

    0 讨论(0)
提交回复
热议问题