2

I have a Sinatra application which outputs a steady stream of information to STDOUT via an instance of Logger. I have also turned on Sinatra logging, and Rack logging. For argument's sake lets say that this is a good idea.

Here's what the output looks like at the moment:

[2016-03-03 11:32:38] INFO  WEBrick 1.3.1
[2016-03-03 11:32:38] INFO  ruby 2.3.0 (2015-12-25) [x86_64-linux]
[2016-03-03 11:32:38] INFO  WEBrick::HTTPServer#start: pid=12303 port=4567
[03/03/16 11:32:45] core/lib/registry.rb     INFO Resolving request for u:/swingshift/registry a:GET
[03/03/16 11:32:45] core/lib/registry.rb     INFO SwingShift::RegistryController has been selected...
10.192.0.136 - - [03/Mar/2016:11:32:45 +0000] "GET /swingshift/registry HTTP/1.1" 200 10227 0.0557
10.192.0.136 - - [03/Mar/2016:11:32:46 +0000] "GET /css/bootstrap.min.css HTTP/1.1" 304 - 0.0023

As you can see, it's a bit of a mess. What I would like is to tell Sinatra and Rack to use my instance of Logger, rather than their own.

  • How do I get Sinatra to use my logger?
  • How do I get Rack to use my logger?

(Alternatively, can I pass a proc to their loggers to format them the same? That's not as good, but it would be something.)

Here's the my Sinatra settings block. At this point $logger already points to my Logger instance:

configure do                                                
  $logger.info(__FILE__){"Starting..."}                     
  set :bind, '0.0.0.0'                                      
  enable :sessions                                          
  set :session_secret, 'whatever'

  set :views, BASEDIR
  set :haml, :layout_options => { :views => 'core/views' }  

  enable :logging                                           
  set :dump_errors, true                                    
end                     

I've also got a

use Rack::CommonLogger, $logger

...but it doesn't seem to do anything.

Update:: I'm aware of https://stackoverflow.com/questions/2239240A/use-rackcommonlogger-in-sinatra, but:

  • It doesn't address Sinatra logging, just Rack
  • The accepted answer seems extremely complex and there are a number of unanswered points raised in the comments to it. (Do I really need to set a logger in config.ru AND add a middleware logging layer? Is the syntax for the logging layer wrong, as >=4 people seem to think?)

According to Sinatra I'm supposed to be able to control Rack from its settings block. Is this not true?

Update 2: I've now had a proper go at the solution to the other question. Implementing it as is does ... absolutely nothing to the log here.

Community
  • 1
  • 1
Andy Jones
  • 1,074
  • 1
  • 10
  • 21
  • Possible duplicate of [Use Rack::CommonLogger in Sinatra](http://stackoverflow.com/questions/2239240/use-rackcommonlogger-in-sinatra) – Anthony Mar 03 '16 at 13:05

2 Answers2

0

I'm not using WEBrick but Thin (set :server, 'thin') Anyway according to Sinatra configuration I redirect rack.errors to my $logger:

class IOToLog < IO
  def initialize(logger)
    @logger = logger
  end
  def write(string)
    @logger.debug {"SINATRA #{string.strip}"}
  end
end
IOTOLOG = IOToLog.new($logger)

before {
  env["rack.errors"] =  IOTOLOG
}

and the output is:

2017-06-21 15:44:46.166 DEBUG SINATRA 127.0.0.1 - - [21/Jun/2017:15:44:46 +0200] "GET /wd/hub/status HTTP/1.1" 200 83 0.0004
2017-06-21 15:44:51.167 DEBUG SINATRA 127.0.0.1 - - [21/Jun/2017:15:44:51 +0200] "GET /wd/hub/status HTTP/1.1" 200 83 0.0004

BTW I've tried env["rack.logger"] = $logger but with no luck.

lojza
  • 1,823
  • 2
  • 13
  • 23
  • Nice! Unfortunately all that IOToLog gets is the preformatted string from the Rack logger. I can't reformat it to make it the same as my other log messages. But this is the closest to an answer I've ever got. Many thanks. Tick. – Andy Jones Jun 22 '17 at 08:01
0

I can't comment yet so posting answer. You can format the messages going to IOToLog. You need to set the format in before block. Maybe something like

before {
   env["rack.errors"] =  IOTOLOG
   IOTOLOG.format
}

And in IOToLog add something like:

class IOToLog < IO
    def format
      @logger.formatter = proc do |severity, datetime, progname, msg|
      "#{severity}: #{msg}\n"
    end
end
loafdog
  • 101
  • 7
  • Well, I shouldn't have to do that if I am passing it an existing, already formatted, logger instance. But, I'll add it to the list of things to try, thanks. – Andy Jones Aug 14 '17 at 07:33