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, for example in helper methods or in the configure hook? Is the Sinatra logger available through other means?
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With