Disable Rack::CommonLogger without monkey patching - ruby

So, I want to have completely custom logging for my sinatra application, but I can't seem to disable the Rack::CommonLogger.
As per the sinatra docs all I should need to do is add the following line (tried setting it to false as well):
set :logging, nil
to my configuration. This does not work however, and I still receive the Apache-like log messages in my terminal. So the only solution I've found so far is to monkey patch the damn thing.
module Rack
class CommonLogger
def call(env)
# do nothing
#app.call(env)
end
end
end
Anyone got any ideas if it's possible to disable this without restorting to such matters?

I monkey patched the log(env, status, header, began_at) function, which is what gets called by rack to produce the apache style logs. We use jruby with logback so we have no use for all the custom logging that seems to pervade the ruby ecosystem. I suspect fishwife is initalizing the CommonLogger, which might explain why all my attempts to disable it or to configure it with a custom logger fail. Probably puma does something similar. I actually had two instances at one point. One logging with my custom logger (yay) and another one still doing its silly puts statements on stderr. I must say, I'm pretty appalled with the logging hacks in the rack ecosystem. Seems somebody needs a big cluebat to their heads.
Anyway, putting this in our config.ru works for us:
module Rack
class CommonLogger
def log(env, status, header, began_at)
# make rack STFU; our logging middleware takes care of this
end
end
end
In addition to that, I wrote my own logging middleware that uses slf4j with a proper MDC so we get more meaningful request logging.

Puma adds logging middleware to your app if you are in development mode and haven’t set the --quiet option.
To stop Puma logging in development, pass the -q or --quiet option on the command line:
puma -p 3001 -q
or if you are using a Puma config file, add quiet to it.

Rack includes a few middlewares by default when you rackup your application. It is defined in this file.
By default, as you mention, the logging middleware is enabled.
To disable it, just pass the option --quiet to rackup:
rackup --quiet
And the default loggin middleware will not be enabled.
Then, you can enable your own logging middleware without pollution by the default logger (named CommonLogger).
You can also add #\ --quiet to the top of your config.ru file to avoir always typing --quiet, but this behaviour is now deprecated.

It's probably not Sinatra what is writing to STDOUT or STDERR, but your webserver. Puma can be started with -q (quiet) option as noted by #matt. When using webrick make sure the AccessLog configuration variable is an empty array, otherwise it will also be logged on your standard output.
Disabling echo from webrick

This is one of the top results. So this probably more of a message to my future self the next time I'm annoyed to death about sinatra/puma not shutting up. But to actually get a silent start up:
class MyApp < Sinatra::Base
configure do
set :server, :puma
set :quiet, true
set :server_settings, Silent: true
end
end

Related

How to write to stdout with Ruby on Bluemix?

I am using Bluemix Ruby buildpack out of the box.
I add some puts lines in my main *.rb file but nothing appears when tailing logs:
cf logs myapp
Searching the docs, I found this post at developerWorks where it is recommended to set runtime into development mode.
I have tried with:
cf set-env myapp RAILS_ENV development
and also adding to the code:
ENV['RAILS_ENV'] = 'development'
but nothing appears in the logs.
Also tried Sinatra options (after changing the code) with same results:
set :environment, :development
set :logging, true
An interesting thing, is that if I stop the app, then all my puts appears after the stacktrace of the FATAL SignalException: SIGTERM error. It seems like a buffer flush contention or anything like that?
Any advice? Thanks!
You can add the following line to your config.ru file. This will disable buffering to stdout and allows your puts commands to stdout to appear correctly in the log output.
$stdout.sync = true
See the answer at What STDOUT.sync = true means? for more details about how puts buffers.
Not Sure but have you tried the following links
https://developer.ibm.com/answers/questions/21548/debugging-a-ruby-app-in-bluemix-with-puts-or-print-statements-written-to-the-log-is-it-possible.html
http://www.ibm.com/developerworks/aix/library/au-unix-commandline/

Disable Sinatra standard output

For security reasons I don't wish to have Sinatra print every URL its requested in standard output, I've tried using set :logging, false as suggested in this answer using:
class SweetAppName< Sinatra::Base
set :show_exceptions, false
set :environment, :production
set :logging, false
However when I run the app using rackup and thin, I still see the request logged to the terminal:
127.0.0.1 - - [26/May/2015:09:32:34 -0700] "GET /not-a-real-url HTTP/1.0" 404 - 0.0452
How can I turn these off?
If you start your app with rackup, Rack will add some middleware, including logging. You can prevent this by using the quiet option (-q or --quiet) to rackup, i.e. from the command line:
$ rackup -q
You can include this option in your config.ru if you want, so you don’t have to remember typing it every time you start your app. The first line that starts with #\ is parsed as options, so you can have a config.ru like this:
#\ --quiet
# other middleware etc...
run SweetAppName
If you use the classic Sinatra app style you will need to add the set :logging, false line, otherwise Sinatra will add its own logging. With the modular style (like you are using in the question) this setting defaults to false so you shouldn’t need it.

Rails + Heroku + RSpec : How to control logging

I have a Ruby on Rails 3.2 application which runs on Heroku. I'm using RSpec for my test suite.
When I started, I just used statements such as
p "Order completed at #{Time.now.to_s}"
to generate logs. I did this because Heroku uses its magical jiggery-pokery to divert all logs to STDOUT anyways.
However, my test suite prints all kinds of logs to STDOUT now, and it is very distracting. I would like those logs to appear when the application is deployed to Heroku, but I don't want to see them on my STDOUT output along with my RSpec output.
Is there a way to divert STDOUT to a file such as log/test.log, or alternatively, use a logging API which will do what I want?
I'm not intimately familiar with the particularities of Heroku's implementation, but you should be able to choose your own file for logging without problem. If they made logging to a file impossible I would be incredibly surprised. You can define your logger in environment.rb differently for prod (ie Heroku) and dev with something like the following in the appropriate conditional:
Rails.logger = Logger.new(STDOUT)
Rails.logger = Log4r::Logger.new("Application Log")
or in your Initializer like so:
config.logger = Logger.new(STDOUT)
config.logger = Log4r::Logger.new("Application Log")
Note that you have lots of options for your logger, for example you can use Log4r instead of the built-in logger.
Check out the RoR Debugging Guide for more
Make sure you include the gem only in your production group to avoid this issue.
group :production do
gem 'rails_12factor'
end

Heroku logging not working

I've got a rails 3.1 app deployed on Heroku Cedar. I'm having a problem with the logging. The default rails logs are working just fine, but when I do something like:
logger.info "log this message"
In my controller, Heroku doesn't log anything. When I deploy my app I see the heroku message "Injecting rails_log_stdout" so I think calling the logger should work just fine. Puts statements end up in my logs. I've also tried other log levels like logger.error. Nothing works. Has anyone else seen this?
MBHNYC's answer works great, but it makes it difficult to change the log level in different environments without changing the code. You can use this code in your environments/production.rb to honor an environment variable as well as have a reasonable default:
# https://github.com/ryanb/cancan/issues/511
config.logger = Logger.new(STDOUT)
config.logger.level = Logger.const_get((ENV["LOG_LEVEL"] || "INFO").upcase)
Use this command to set a different log level:
heroku config:set LOG_LEVEL=error
I was just having the same issue, solved by using the technique here:
https://github.com/ryanb/cancan/issues/511
Basically, you need to specify the logger outputs to STDOUT, some gems interfere with the logger and seem to hijack the functionality (cancan in my case).
For the click lazy, just put this in environments/production.rb
config.logger = Logger.new(STDOUT)
config.log_level = :info
As of the moment, it looks like heroku injects these two plugins when building the slug:
rails_log_stdout - https://github.com/ddollar/rails_log_stdout
rails3_server_static_assets - https://github.com/pedro/rails3_serve_static_assets
Anything sent to the pre-existing Rails logger will be discarded and will not be visible in logs. Just adding this for completeness for anyone else who ends up here.
The problem, as #MBHNYC correctly addressed, is that your logs are not going to STDOUT.
Instead of configuring manually all that stuff, Heroku provides a gem that does this all for you.
Just put
gem 'rails_12factor', group: :production
in your Gemfile, bundle, and that's it!
NOTE: This works both for Rails 3 and 4.
Source: Rails 4 on Heroku

How to designate a Rack handler

Rackup is successfully running any Rack app via Rack's default handler. e.g.:
class RackApp
def call(environment)
[
'200',
{'Content-Type' => 'text/html'},
["Hello world"]
]
end
end
run RackApp.new
But rackup is giving "NoMethodError at / undefined method `call' for nil:NilClass" when the last line is changed to instead use Rack's built-in CGI handler:
Rack::Handler::CGI.run RackApp.new
The same objection is raised for Rack's other built-in handlers. e.g. Rack::Handler::Thin, Rack::Handler::FastCGI, even Rack::Handler::WEBrick (which is the handler Rack selects above in default mode).
What's the correct syntax here?
The rackup command reads the config file and starts a server. The Rack::Handler::XXX.run methods also start a server, independently of the rackup command (CGI is slightly different as it isn't actually a server as such).
What happens when you change the line
run RackApp.new
to
Rack::Handler::CGI.run RackApp.new
and run rackup is as follows. The server starts and parses the config file. When the Rack::Handler::CGI.run RackApp.new line is reached it is executed as any other Ruby code would be. In the case of the CGI handler this calls the app and writes the output to the standard output as it would if running as a CGI script (have a look at your terminal when you run rackup). Afterwards the 'rackup' server is started as normal, but without an app to run. When you try to access the page you'll get the NoMethodError, since the app is nil.
Using Rack::Handler::Thin is similar, but in this case, as Thin actually is a web server, it is started and will serve RackApp, but listens on Thin's default port of 8080 (not the rack default of 9292). After stopping Thin (e.g. with Ctrl-C) the default rackup server (Mongrel or Webrick) will start listening on port 9292, again with no app specified so you'll get the NoMethodError.
If you run your modified 'config.ru' as a plain Ruby script rather than using rackup you'll see the same behaviour, but without the rackup server being started. (You'll need to require rack first, so use ruby -rrack config.ru). In the CGI case the output of a single call to your app will be printed to the console, in the Thin case Thin will be started serving your app.
In order to specify the server to use with rackup, you can use the -s option, e.g. rackup -s thin will start the app using Thin (this time on the rackup default port of 9292). You can also do rackup -s cgi but this won't really work in any useful way - it just prints out the html of an error page to the console.
CGI
If you're trying to run your app as a CGI there are a couple of options. You need to create a CGI script that calls your app using the CGI handler. This could itself be a ruby script that calls Rack::Handler::CGI.run directly, in fact you could use your modified config.ru directly (you might want to rename it first and add an explicit require 'rack' line).
Alternatively you can use a shell script which then calls rackup config.ru. In this situation rackup detects that it's running as CGI and automatically uses the correct handler
http://guides.rubyonrails.org/rails_on_rack.html (see point 3.5)
also interesting:
http://railscasts.com/episodes/151-rack-middleware
http://railscasts.com/episodes/222-rack-in-rails-3

Resources