I want to write a script in ruby. The goal of the script
is to automate the build process of a cmake project.
I want to add a lot of debug out but if I use puts or
print the output will always be visible and I don't want that.
I want to do something like
my_script --debug $foo
and to have output related with the development of the script.
thanks in advance
You should try out Logger.
require 'logger'
$log = Logger.new(STDOUT)
$log.level = Logger::DEBUG
$log.debug "Sample debug message"
$log.info "Sample info message"
$log.error "Sample error message"
You only need to change one line to decide which messages should be printed (i.e. $log.level = Logger::DEBUG). Alternatively, you can parse the command line options to set the Logger level.
If you think the output is too verbose, you can redefine it like so:
class Logger
def format_message(severity, timestamp, progname, msg)
"#{timestamp} #{msg}\n"
end
end
You can use Logger
By setting the level of logging like this
log.level = Logger::DEBUG
you can manage to print out or not print out the debug messages.
Also you can choose the output stream, it could be console or file like this
log = Logger.new(STDOUT)
Related
I am trying to execute rspec from ruby, and get the status or number of failures from a method or something like that. Actually I am running something like this:
system("rspec 'myfilepath'")
but I only can get the string returned by the function. Is there any way to do this directly using objects?
I think the best way would be using RSpec's configuration and Formatter. This would not involve parsing the IO stream, also gives much richer result customisation programmatically.
RSpec 2:
require 'rspec'
config = RSpec.configuration
# optionally set the console output to colourful
# equivalent to set --color in .rspec file
config.color = true
# using the output to create a formatter
# documentation formatter is one of the default rspec formatter options
json_formatter = RSpec::Core::Formatters::JsonFormatter.new(config.output)
# set up the reporter with this formatter
reporter = RSpec::Core::Reporter.new(json_formatter)
config.instance_variable_set(:#reporter, reporter)
# run the test with rspec runner
# 'my_spec.rb' is the location of the spec file
RSpec::Core::Runner.run(['my_spec.rb'])
Now you can use the json_formatter object to get result and summary of a spec test.
# gets an array of examples executed in this test run
json_formatter.output_hash
An example of output_hash value can be found here:
RSpec 3
require 'rspec'
require 'rspec/core/formatters/json_formatter'
config = RSpec.configuration
formatter = RSpec::Core::Formatters::JsonFormatter.new(config.output_stream)
# create reporter with json formatter
reporter = RSpec::Core::Reporter.new(config)
config.instance_variable_set(:#reporter, reporter)
# internal hack
# api may not be stable, make sure lock down Rspec version
loader = config.send(:formatter_loader)
notifications = loader.send(:notifications_for, RSpec::Core::Formatters::JsonFormatter)
reporter.register_listener(formatter, *notifications)
RSpec::Core::Runner.run(['spec.rb'])
# here's your json hash
p formatter.output_hash
Other Resources
Detailed work through
Gist example
I suggest you to take a look into rspec source code to find out the answer. I think you can start with example_group_runner
Edit: Ok here is the way:
RSpec::Core::Runner::run(options, err, out)
Options - array of directories, err & out - streams. For example
RSpec::Core::Runner.run(['spec', 'another_specs'], $stderr, $stdout)
Your problem is that you're using the Kernel#system method to execute your command, which only returns true or false based on whether or not it can find the command and run it successfully. Instead you want to capture the output of the rspec command. Essentially you want to capture everything that rspec outputs to STDOUT. You can then iterate through the output to find and parse the line which will tell you how many examples were run and how many failures there were.
Something along the following lines:
require 'open3'
stdin, stdout, stderr = Open3.popen3('rspec spec/models/my_crazy_spec.rb')
total_examples = 0
total_failures = 0
stdout.readlines.each do |line|
if line =~ /(\d*) examples, (\d*) failures/
total_examples = $1
total_failures = $2
end
end
puts total_examples
puts total_failures
This should output the number of total examples and number of failures - adapt as needed.
This one prints to console and at the same time captures the message. The formatter.stop is just a stub function, I don't know what it is for normally, I had to include it to use DocumentationFormatter. Also the formatter output contains console coloring codes.
formatter = RSpec::Core::Formatters::DocumentationFormatter.new(StringIO.new)
def formatter.stop(arg1)
end
RSpec.configuration.reporter.register_listener(formatter, :message, :dump_summary, :dump_profile, :stop, :seed, :close, :start, :example_group_started)
RSpec::Core::Runner.run(['test.rb','-fdocumentation'])
puts formatter.output.string
This is a ruby script which i am using to log my status.
require 'logger'
log = Logger.new( 'log.txt', 'daily' )
log.debug "Once the log becomes at least one"
log.debug "day old, it will be renamed and a"
log.debug "new log.txt file will be created."
Now i want to make a new ruby file in which i want to include logger it can be like this
module Logging
def logger
Logging.logger
end
def self.logger
#logger ||= Logger.new(STDOUT)
end
end
But i am not able to understand this so can anyone explain it.
my requirement is like there are lots of ruby script file i want to put a logger in module and include that in every file than write log in log file it can be warning it can be a info or anything else.
A better alternative would be:
module Logging
def logger
#logger ||= Logger.new(STDOUT)
end
end
And use it like this
class MyLoggingClient
include Logging
#Now you have access to the method `logger` and the instance variable `#logger`.
end
What I can gather from your question is the code works... you're just confused on what it does... if that's correct then to explain, when you inculde Logging in any of your classes the from anywhere in the classes methods call logger.log("This is a log message") it will log that message to the console that started the scripts.
Does that answer your question?
Assume I have a custom task in my recipe as such:
task :custom_task1 do
run_locally "cap -S config=blah another_custom_task
end
and
task :another_custom_task do
puts "hi"
end
Then, "hi" won't be printed.
How to fix or overcome the situation? It is not allowing me to use command line whatsoever.
Edit:
Why can't I use logger?
Capistrano, by default talks too much - so I have a setting that sets its logger to shout only important errors. So can't use logger.info or something as such.
Try to use Logger:
logger.info "hi"
This script is named o.rb:
#logger = Logger.new(STDOUT)
#logger.info "start_time : #{start_time}"
When I run it using ./o.rb, the output on the console is correct.
However, when I tried ./o.rb > log.txt 2>&1, the log file is empty!
Why did this happen?
I have the same issue while using the simple puts function.
UPDATE
This will reproduce this issue:
require 'logger'
logger = Logger.new(STDOUT)
loop do
logger.info "This is a test haha"
sleep(1)
end
When I run it using ./foo.rb, it writes correctly to the console output.
When I run ./foo.rb > log.txt, I get nothing.
Also, when I use ./foo.rb | tee log.txt, nothing is written to the console and the log file is empty.
The log.txt file was created but remains empty.
My Ruby version is 1.8.7.
It's a buffering problem, you can set the standard output to sync and this should resolve it.
#!/usr/bin/env ruby
require 'logger'
$stdout.sync = true
logger = Logger.new($stdout)
loop do
logger.info "This is a test haha"
sleep 1
end
I'm trying to build a very simple sinatra app deployed on heroku.
our app is not outputting stuff to a web browser, it's communicating with another computer via an API. so my usual trick of just printing a little extra debugging info to the browser while I'm using the app doesnt work.
the sample code I've seen for related apps show multiple 'puts' or 'p' statement used ot sort of see what's going on...
where does the output go that I can see that output as the program executes, or afterwards.
and in general, if you're flailing around with code hosted at Heroku that's just not doing what you want, what IS the easiest way to at various places in the code output messages like "foo equals 123" so you can see that output to figure out what's happening in the code?
p and puts dont output so the logs I can see when I type "heroku logs" for example...
If you use a cedar stack, try to put a line bellow in config.ru,
$stdout.sync = true
http://devcenter.heroku.com/articles/ruby#logging
Original post was in February 2011, and Cedar stack was introduced in May, so this doesn't seem to be help for original question, but some of you may find this could be help.
http://blog.heroku.com/archives/2011/5/31/celadon_cedar/
According to http://docs.heroku.com/logging you should be able to have puts and p just go to your log if you add the basic logger (which has apparently been added by default to all apps created after February 2nd, 2011).
For non-Heroku basic log-to-file with Sinatra and Logger:
require 'logger'
Dir.mkdir('logs') unless File.exist?('logs')
$log = Logger.new('logs/output.log','weekly')
configure :production do
$log.level = Logger::WARN
end
configure :development do
$log.level = Logger::DEBUG
end
get "/" do
$log.debug "Hello, World!"
end
This will work fine. test_logging.rb
require 'sinatra'
require 'logger'
enable :logging
before do
logger.level = Logger::DEBUG
end
get '/' do
logger.debug "Handling 'hello world' request."
logger.info "Hello world."
return "<h1>Hello World</h1>"
end
See here for tips on how to write to the Logger: http://mikenaberezny.com/2007/02/24/rails-logging-tips/
The example given is:
class HomeController < ActionController::Base
def index
logger.info 'informational message'
end
end
This is the line that works for me:
# On config.ru, before run:
enable :logging, :dump_errors, :raise_errors