implementing logger in ruby script - ruby

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?

Related

Not able to find global log file in Ruby

I have a script called main.rb in which I call modules. In the script, I am creating a log file (something like \abc\xyz\script\tool.log) and storing it in a global variable $LOG: $LOG = Logger.new('tool.log', 'daily')
From main.rb I call another module's method (say HostM.changeDir1) which changes directory to \abc\xyz. Now when I am trying to write into $LOG it errors out by printing \abc\xyz\tool.log does not exist. I was wondering how can I make it look for the log in proper location i.e., \abc\xyz\script\tool.log. Need guidance in fixing this issue.
Add the full path to the log file is one option
$LOG = Logger.new('\abc\xyz\script\tool.log', 'daily')
However, using a global variable is usually poor practice, and I expect using an absolute path is also going to cause problems if you move the app to another location. Therefore, I'd suggest you wrap the Logger in a new class that defines a standard behaviour and a path to the log file that is relative to the file where the new class is defined.
require 'logger'
class AppLogger < Logger
def initialize(period = 'daily')
path_to_log = File.expand_path('relative/path/to/tool.log', File.dirname(__FILE__))
super path_to_log, period
end
end
Then when you need a logger in your app, you can do this:
logger = AppLogger.new
logger.debug 'Whoops'
If you want to ensure you only work with one logger instance, I'd load the logger instance in your Main class, and share it from there:
class Main
require_relative 'app_logger'
def self.logger
#logger ||= AppLogger.new
end
....
end
Then in the rest of your app, you'll be able to call the logger like this:
Main.logger.debug 'Whoops!'

log in non sidekiq class

I have a worker that delegates the work to another class like this:
class SynJob
include Sidekiq::Worker
sidekiq_options queue: :sync
def perform(user_id)
OtherClass.new(blah, blah, blah)
end
end
class OtherClass
def initialize
puts "we are in OtherClass"
end
end
My question is, how do I log to stdout from OtherClass.
My puts statements do not show up in the heroku stdout log.
The literal answer to your question is to use puts or other Ruby APIs for writing to stdout. You can call this both in your SynJob or your OtherClass code and it will execute the same, writing to the stdout of the sidekiq worker process.
However, this probably is not what you want to do. If this is a Rails app, you probably want to write to the Rails logger, which should be available both in your worker and in other code:
Rails.logger.info "I'm a debug message"
This will show up in the appropriate log both locally and when running deployed on Heroku.

how can I enable a specific debug output in ruby?

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)

very basic ruby/sinatra/heroku/debugging question: how to see output of puts and p?

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

Can I disable the log header for ruby logger?

I'm currently running into kind of a problem.
As you might know, the ruby logger adds a logging header at the top of every newly created logfile.
"# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
I am logging CSV files to import them in a warehouse later, usually I just skip the first line with the header. It's seems like there is a bug in the logger, because sometimes the logging header appears more than once, right in the middle of a log file.
So I decided to simply leave that header out. To my surprise I didn't find any argument one could pass at the creation of a logger. I thought of something like this:
Logger.new "info.log", :skip_header => true
But it's just not there. I searched in the ruby core sources and surprisingly there really is nothing that could prevent the logger from adding the log header:
def create_logfile(filename)
logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT))
logdev.sync = true
add_log_header(logdev)
logdev
end
def add_log_header(file)
file.write(
"# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
)
end
Does anyone have an idea what I could do, to prevent the log header? I'm using Ruby 1.8.7 302 with Rails 2.3.5 here. Simply ignoring the comments on the warehouse side is not possible because I have no control over the code there, and it seems to be to risky to simply ignore it, if something goes wrong with a a logging line.
Does someone know a logger that allows this? Do you think it would be a good idea to use and write plain to a file?
Thanks in advance,
Tommy
Ideally the method add_log_header on the Logger instance should be overwritten, but since add_log_header is called on initialize, you're too late by the time you get your hands on it.
Well, you could just overwrite the add_log_header method on the Class.
class Logger::LogDevice
def add_log_header(file)
end
end
log1 = Logger.new('info1.log')
But if your app needs more instances of Logger after this, they will behave the same: no header. To prevent this:
# dismantle the header and save it under another name
class Logger::LogDevice
alias orig_add_log_header add_log_header
def add_log_header(file)
end
end
# Quick,create an instance
log1 = Logger.new('test_log1file.log')
# restore the old method:
class Logger::LogDevice
alias add_log_header orig_add_log_header
end
Here's a solution that involves subclassing Logger. We have to be sneaky with initialize and super to keep it from creating a standard Logger::LogDevice too early.
class HeadlessLogger < Logger
def initialize(logdev, shift_age = 0, shift_size = 1048576)
super(nil) # this prevents it from initializing a LogDevice
if logdev
#logdev = HeadlessLogger::LogDevice.new(logdev, shift_age: shift_age, shift_size: shift_size)
end
end
class LogDevice < ::Logger::LogDevice
def add_log_header(file) ; end
end
end
As an alternative to patching the logger class, simply do not let it create the log file by touching it upfront:
FileUtils.touch logfile_path
Logger.new logfile_path
In plain Ruby you will need to require 'fileutils' from stdlib obviously.
Edit: This will not work if you use the built-in logrotation though, or the file is deleted, as there is no on-rotate hook and it will then write the header yet again.

Resources