How to use file logger in Sinatra
When you do google search with "sinatra logging file", you may find a solution with Rack::CommonLogger
. However I was looking for a different approach because it does not respect interface of the logger
stdlib. Instead of calling the usual logger.info
, Rack::CommonLogger
forcefully inject output with logger.write
.
As a result, your log file will look like this. The first line is written by Rack::CommonLogger
, which has completely different format with the usual logger output on the second line. This may be a problem when you write a program to parse and analyze the logfile.
::1 - - [27/Sep/2016:02:44:42 +0900] "GET / HTTP/1.1" 200 2 0.0077
I, [2016-09-27T02:44:42.416430 #49814] INFO -- : hello world
Using your own logger
You can specify a logger by setting env["rack.logger"]
in the before hook. You can also log request information like Rack::CommonLogger
here (if you want).
require 'logger'
require 'sinatra/base'
class SomeApp < Sinatra::Base
set :mylogger, Logger.new(#{settings.root}/log/#{settings.environment}.log")
before do
env["rack.logger"] = settings.mylogger
query = env["QUERY_STRING"]
msg = format("%s %s for %s",
env["REQUEST_METHOD"],
env["PATH_INFO"] + (query.empty? ? "" : "?#{query}"),
(env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-"))
logger.info(msg)
end
get '/' do
logger.info("greet")
"hi"
end
end
Output of the logger:
I, [2016-09-27T02:50:07.824032 #50002] INFO -- : GET / for ::1
I, [2016-09-27T02:50:07.824511 #50002] INFO -- : greet
Note that this does not log status code of the response because it has not been decided in the before
hook. You can log response information by using after do ... end
hook, where you can use repsonse.status
.
Alternative solution
Another solution is overriding the logger
method to return your own logger. Actually this is mostly the same as the code above unless there is a library which writes something to env['rack.logger']
(I've never used such libraries though).
require 'logger'
require 'sinatra/base'
class SomeApp < Sinatra::Base
# Override the default 'logger' method
def logger
@logger ||= Logger.new(#{settings.root}/log/#{settings.environment}.log")
end
before do
query = env["QUERY_STRING"]
msg = format("%s %s for %s",
env["REQUEST_METHOD"],
env["PATH_INFO"] + (query.empty? ? "" : "?#{query}"),
(env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-"))
logger.info(msg)
end
get '/' do
logger.info("greet")
"hi"
end
end