Logging output during ruby processes is hugely beneficial for gaining insight into running code.
Ruby is a really fun language to write and, as a result, I prefer to write my heavy-lifting tasks in Ruby. This could be migrating content from one system to another, parsing and processing a set of files, analyzing data, etc. There are several approaches to writing scripts in ruby, be it a rake task, a command-line script, or even a little Ruby library.
When when working with long-running processes (whether you wrote them or not), it's a good idea to provide yourself with feedback.
When I'm working with a simple task and have to write a small amount of procedural ruby, I usually just use puts
to print some infor to the console. Something like this:
puts 'Exporting data ...'
# do the export work
puts 'Done.'
One issue with puts
is that it prints the message on a new line. So, instead of puts
, you could use print
and control your newlines:
print 'Exporting data ... '
# do the export work
print "Done.\n"
Or you can work directly with Ruby's IO class. In this case you have an object as either $stdout
or STDOUT
from which you can write to standard output. Your code from above may look more like this:
$stdout.write('Exporting data ... ')
# do the export work
$stdout.write("Done.\n")
Use your preference for any one of these approaches. With the exception of the newline in puts
I have yet to run into any major issues with any of these approaches. It's mostly personal preference.
And with any of these approaches you can colorize the output. There are a handful of colors to use, you just need to find a reference (like this) to a list of ANSI color codes.
For example, if you wanted your "Done." to be green, you could revise the most recent example to look like this:
$stdout.write('Exporting data ... ')
# do the export work
$stdout.write("\e[32mDone.\e[0m\n")
This would render "Export data ..." in white and "Done." in green.
When your code is short and simple it can be enough to write the output (and color, if necessary) directly in the code. But as your codebase gets larger, it can really help to pull that logic out into a utility class and reference as needed. This way you don't have to remember the colors, just a simple DSL for your class.
Here's an example of a logger utility class:
class Logger
class << self
def write(str, color = :white)
STDOUT.write(colorize(str, color.to_sym))
end
private
def colors
@colors ||= {
blue: 34,
green: 32,
light_blue: 36,
pink: 35,
red: 31,
white: 256,
yellow: 33
}
end
def colorize(str, color_code)
"\e[#{colors[color_code]}m#{str}\e[0m"
end
end
end
The class << self
is a ruby singleton idiom. What it enables me to do in this situation is have what appear to be private class methods. What it ultimately does is clean up the class so that we can access the write
method directly on the Logger
class and still keep the code relatively clean.
Now when I want to log I have to make sure I've required this file and then I can access the write
method on the Logger
class while maintaining the colorization I wanted, like so:
Logger.write('Exporting data ... ')
# do the export work
Logger.write("Done.\n", :green)
This quickly becomes much easier to manage in large projects.
As you can see, there are plenty of approaches for logging output in your ruby code. The most important piece to remember is to do it. It doesn't really matter which approach you take, just as long as you're giving yourself feedback for your long-running processes.
References: