puts statements for debug - ruby-on-rails

When I code, I make quite intense use of "puts" statements for debugging. It allows me to see what happens in the server.
When the code is debugged, I use to remove these "puts" statements for I don't know what reason.
Is it a good idea or should I leave them instead to give more clarity to my server logs?

You should use the logger instead of puts. Use this kind of statements:
Rails.logger.debug "DEBUG: #{self.inspect} #{caller(0).first}" if Rails.logger.debug?
If you want to see the debugging in the real-time (almost), just use the tail command in another terminal window:
tail -F log/development.log | grep DEBUG
Then you do not need to remove these statements in production, and they will not degrade performance too much, because if logger.debug? will prevent the (possibly expensive) construction of the message string.
Using standard output for debugging is usually a bad practice. In cases you need such debug, use the diagnostic STDERR, as in:
STDERR.puts "DEBUG: xyzzy"
Most of the classes in Rails (models, controllers and views) have the method logger, so if possible use it instead of the full Rails.logger.
If you are using older versions of Rails, use the constant RAILS_DEFAULT_LOGGER instead of Rails.logger.

use the logger : http://guides.rubyonrails.org/debugging_rails_applications.html#the-logger

I use the rails_dt gem designed specifically to make such kind of debugging easier.
Using Rails.logger or puts directly is somewhat cumbersome, since it requires you to put a lot of decorative stuff (DEBUG, *** etc.) around debug messages to make them different from regular, useful messages.
Also, it's often difficult to find and defuse the debug output generated by Rails.logger or puts if the message doesn't appear to contain enough searchable characters.
rails_dt prints the origin (file, line), so finding the position in code is easy. Also, you will never confuse DT.p with anything, it clearly does debug output and nothing else.
Example:
DT.p "Hello, world!"
# Sent to console, Rails log, dedicated log and Web page, if configured.
[DT app/controllers/root_controller.rb:3] Hello, world!
Gem is available here.

Related

Showing only specific test case in test.log

I am writing Rails tests using the standard Test::Unit/TestCase.
Is there any way to somehow filter what gets printed to the log, so that you only print the stack for specific test cases.
I have a functional test file with many test cases in it, and I'm really only interested in debugging one test case. Printing my own log statements still requires searching through a few thousand lines of generated log. Or something similar to the RSpec 'pending' functionality.
Run from a command line ruby test/unit/my_model.rb to run one test suite. You can also use a debugger, such as (wrapped by) RubyMine or pry, to stop on a specific test case and look at the log.
But if a sledge-hammer does not solve the problem, you can use tweezers: config.logger.level = Logger::WARN in your test.rb, from Set logging levels in Ruby on Rails
It is probably better if instead of strangling the output to log/test.log, you become familiar with a command such as grep. Grep allows you to run very advanced search queries through files or directories, as long as your running on some flavor of *nix. The simplest use would be
grep search_term file_name
The reason I say you shouldn't constrict the log output is because someday that could bit you in the **s. Hope this helps.

Logging all method calls in a Rails app

Is there an easy way to log all method calls in a Rails app?
My main use for this would be in testing (and in debugging tests). I want to have more of a history than a stacktrace provides (for instance, when running rspec with the '-b' option).
It's easy to do. Just add 5 lines of code into your script/server:
#!/usr/bin/env ruby
set_trace_func proc {
|event, file, line, id, binding, classname|
if event == "call" or event == "return"
printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
end
}
require File.expand_path('../../config/boot', __FILE__)
require 'commands/server'
It's described at http://phrogz.net/ProgrammingRuby/ospace.html#tracingyourprogramsexecution
Your application will become quite slow and you might get more output than you want. You can easily add more conditions on file/class/function names to avoid printing unwanted stuff.
Perftools might give you what you're looking for. It analyzes the entire process and can give you a graphical view that looks something like this. Rack perftools profiler is a rubygem that uses perftools and makes it easy to integrate with a Rails application, so I would recommend going with that if you want to try it.
Firstly stacktrace IS every method call that was on the stack at the time an error occurred, what other history could you want besides this?
Secondly, to answer your question, no there is no easy way to log all method calls. You could up your log level all the way to debug which should give you more stuff in the logs, but this will only be things that someone has actually chosen to log, unrelated to method calls.
It probably wouldn't be that difficult to patch ruby in such a way that every method call will print some log statements before and after the method execution, but this will once again be similar to what a stack trace would give you anyway and potentially less since you won't get line numbers etc.
If you want more info than the stack trace, logging is the way most people would do it.

"Correct" way to write log output from a background (Resque) job?

Resque jobs are just plain old ruby objects. I can use puts calls inside them to produce output into the console, or I can instantiate a standard Ruby Logger class with STDOUT and use that.
But is there a correct approach to logging in Rails, from places that aren't controllers or models? I see Rails.logger returns a BufferedLogger, but when I call info or warn etc on it, nothing happens. If I call flush on it, it just returns an empty array and nothing is output.
What's the convention here?
I'm not really sure that there is a convention. I had a pretty ugly logging system up until just recently. Now I use lumber to integrate log4r with Rails. That really made logging much nicer because I now have named loggers (e.g., logger matches the class name -- great for filtering output) and I can control log levels on a per-logger (i.e., per-class) basis.
There's also a GELF adapter for log4r if you want to use graylog2 to aggregate your logs.

Debugging - logging in development mode

NEWBIE logger question here:
What's the best way to log output to a development log for debugging purposes? How do you do it in a way that's quick, simple, effective?
To log in log/development.log:
Rails.logger.debug "Hello!"
Or, if you want to create a separate log, you could create a new logger in an initializer (config/initializers):
MyLogger = Logger.new(Rails.root.join("log", "custom.log"))
Then, in your app you can call:
MyLogger.debug "Hello!"
One option that I prefer over logging is using ruby debug. It allows you to put a break point anywhere in your code and inspect all local variables at that point in time. I find it more useful for tracking down bugs in cases where you have no friggin' idea what's going on and just want to look at everything.
Say you had a method like this and the behavior was not what you expected:
def my_method(arg)
# do something with argument
end
You could stick a debugger line in there:
def my_method(arg)
debugger
# do something with argument
end
You'll be able to then do things like this to get a better idea of what is going on:
p arg
p arg.method
p arg.another_method
p local_var
p local_var.method

"Printf" testing in Rails

I'm new to Rails and I'm aware it has things such as unit-testing built in. But I'm interested in doing some more simple tests that are equivalent to your "printf" in C. So I'm testing a login page I've written and want to trace the code to see what each line like my find methods are returning. I try outputting with "puts" but I don't get anything in the command-line.
I use puts statements all the time as well as the ruby debugger! It's great.
In rails you can do a couple things. I put "puts" in my code and when I run script/server at the command line, the output appears in my Terminal.app. I am running a Mac, but I am sure that there is a similar way to trace the activity of your app on your platform of choice.
The other option is to use the logger statement. you can call
logger.debug("My #{variable}")
and find these statements right in your log/development.log file.
Also, if you are running on a *nix system, you can use the "tail" command to trace the last statement written to your log one at a time.
tail -f log/development.log
This way you could write your statements and see them as they are happening. There are several levels of logging:
logger.warn
logger.info
logger.debug
logger.fatal
each environment (development, testing, production) will determine what "level" of logging will be called, so you may write log statements willy nilly with logger.debug while in development, but those log statements won't be written when you deploy based on the default log levels.
User something like this:
logger.info "method called with #{params.inspect}"
(you can put any variable inside the #{})
Once you're having fun with that, check out ./script/console and ruby-debug
Are you familiar with ruby-debug?
Install the ruby-debug gem.
Start your server with the -u option.
script/server -u
Put a debugger statement in your code where you want to stop.
You will have console access to your variables as well as the ability to step through your code.
Check the ruby-debug documentation for more details.
I've done this before - with Passenger, you don't have script/server's output, so I wrote this:
# extras/sexy_logging.rb
module SexyLogging
def log(text)
return true if RAILS_ENV == 'production'
string = "\e[0;32mLog:\e[m #{text}"
(100 - string.length).times do
string << ' '
end
string << "(#{caller.first})"
logger.debug string
end
end
ActiveRecord::Base.send :include, SexyLogging
ActionController::Base.send :include, SexyLogging
Then you can write
log variable
or
log 'Testing user'
tail -f log/development.log |grep Log:
and only see what you're logging, line by line and with colours.

Resources