class Tlogger::Tlogger
Tlogger
class is meant to be a thin wrapper around the Ruby Logger class (by default) to provide contextual logging capabilities to the logging system.
Contextual logging allow developers:
-
Structure the log message not only by the severity (debug, info, error, warning) but also another key that is useful for the application during troublehshooting purposes. This can provide more info to the log message being logged. For example can automatically tag the log message with number of 1789 loops in the program
-
Subsequent from this context info, developer now can selectively turn on / off certain logging message to get the clarity needed. Relying on the above example, if we are only interested in loop 1232, we can disabled all other log message EXCEPT the tag show loop_1232. This will drastically reduce the effort required in reading all the 1231 lines of log.
I found it rather helpful especially in managing the print out of log AFTER it has been logging from everywhere in my programs. I also found that just filtering by log level (debug, info, error and warn) is not sufficient sometime to lessen the effort of log reading for a specific issue especially the only way to debug is turned on the debug level and ALL debug messages now sprang to life! It is really not an easy task to look for specific info especially when it was an old project.
Now you can just disable all and only turn on the specific tag around the issue area to investigate the issue. You will now have better focus in the issue on hand instead of hunting the line that you need from long list of debug output.
Attributes
include_caller
(true/false) tell the logger to print the caller together with the tag
logger
it is the actual logger instance of this Tlogger
tag
is the tag that is being set for this logger session.
One session shall only have one specific tag value, which is the default tag for this logger session.
If multiple tags are required, use the method tdebug, terror, twarn, tinfo or with_tag
block to create a new tag
Note that the tag can be in symbol or string, however shall convert to symbol when processing
Public Class Methods
# File lib/tlogger/tlogger.rb, line 40 def initialize(*args , &block) # default to console if args.length == 0 args << STDOUT end @opts = {} if args[-1].is_a?(Hash) @opts = opts @opts = { } if @opts.nil? args = args[0..-2] end @logger = @opts[:logger_instance] || Logger.new(*args,&block) @disabled = [] @dHistory = {} @include_caller = false @tag = nil @genable = true @exception = [] end
Public Instance Methods
:method: clear_exceptions
Clear the exception list. All exampted tags given either by off_all_tags_except
or on_all_tags_except
shall be reset
# File lib/tlogger/tlogger.rb, line 171 def clear_exceptions @exception.clear end
:method: method_missing
This is where the delegation to the Logger object happen or no_method_exception shall be thrown
# File lib/tlogger/tlogger.rb, line 189 def method_missing(mtd, *args, &block) if [:debug, :error, :info, :warn].include?(mtd) if args.length > 0 and args[0].is_a?(Symbol) tag = args[0] args = args[1..-1] else tag = @tag end if is_genabled?(tag) and not tag_disabled?(tag) if block if not (tag.nil? or tag.empty?) and args.length == 0 args = [ format_message(tag) ] end out = block else if not (tag.nil? or tag.empty?) str = args[0] args = [ format_message(tag) ] out = Proc.new { str } else out = block end end @logger.send(mtd, *args, &out) end # if not disabled elsif [:tdebug, :terror, :tinfo, :twarn].include?(mtd) key = args[0] if is_genabled?(key) and not tag_disabled?(key.to_sym) if block out = Proc.new { block.call } args = [ format_message(key) ] else str = args[1] out = Proc.new { str } args = [ format_message(key) ] end mtd = mtd.to_s[1..-1].to_sym @logger.send(mtd, *args, &out) end elsif [:odebug, :oerror, :oinfo, :owarn].include?(mtd) key = args[0] if is_genabled?(key) and not tag_disabled?(key) if block out = Proc.new { block.call } args = [ format_message(key) ] else str = args[1] out = Proc.new { str } args = [ format_message(key) ] end msg = out.call if not (msg.nil? or msg.empty?) if not already_shown_or_add(key,msg) mtd = mtd.to_s[1..-1].to_sym @logger.send(mtd, *args, &out) end end end elsif [:ifdebug, :iferror, :ifinfo, :ifwarn].include?(mtd) cond = args[0] key = args[1] if cond.is_a?(Proc) cond = cond.call end if is_genabled?(key) and not tag_disabled?(key) and cond if block out = Proc.new { block.call } args = [ format_message(key) ] else str = args[2] out = Proc.new { str } args = [ format_message(key) ] end msg = out.call if not (msg.nil? or msg.empty?) mtd = mtd.to_s[2..-1].to_sym @logger.send(mtd, *args, &out) end end elsif @logger.respond_to?(mtd) @logger.send(mtd, *args, &block) else super end end
:method: off_tag
Turn off a tag. After turning off, the log message that tie to this tag shall not be printed out
Do note that all tags by default are turned on.
# File lib/tlogger/tlogger.rb, line 85 def off_tag(*tags) tags.each do |tag| if not (tag.nil? or tag.empty? or @disabled.include?(tag)) @disabled << tag.to_sym end end end
:method: on_tag
Turn on a tag.
Note that by default all tags are turned on. This only affect whatever tags that has been turned off via the method off_tag
. It doesn't work as adding a tag. Adding a tag message should use tdebug, terror, tinfo, twarn or with_tag
# File lib/tlogger/tlogger.rb, line 102 def on_tag(*tags) tags.each do |tag| @disabled.delete(tag.to_sym) if not (tag.nil? or tag.empty?) end end
:method: remove_from_exception
Remote a set of tags from the exception list
# File lib/tlogger/tlogger.rb, line 180 def remove_from_exception(*tags) @exception.delete_if { |e| tags.include?(e) } end
:method: show_source
Helper setting the flag include_caller
# File lib/tlogger/tlogger.rb, line 317 def show_source @include_caller = true end
:method: tag_disabled?
Check if the tag is disabled
# File lib/tlogger/tlogger.rb, line 305 def tag_disabled?(tag) if tag.nil? or tag.empty? false else @disabled.include?(tag.to_sym) end end
:method: with_tag
Tag all log inside the block with the given tag value
Useful to tag multiple lines of log under single tag
# File lib/tlogger/tlogger.rb, line 70 def with_tag(tag,&block) if block and not tag.nil? log = self.clone log.tag = tag block.call(log) end end
Private Instance Methods
# File lib/tlogger/tlogger.rb, line 351 def add_to_history(key,dgt) @dHistory[key.to_sym] = [] if @dHistory[key.to_sym].nil? @dHistory[key.to_sym] << dgt if not @dHistory[key.to_sym].include?(dgt) end
# File lib/tlogger/tlogger.rb, line 339 def already_shown_or_add(key,msg) smsg = Digest::SHA256.hexdigest(msg) if @dHistory[key.to_sym].nil? add_to_history(key,smsg) false else res = @dHistory[key.to_sym].include?(smsg) add_to_history(key,smsg) if not res res end end
# File lib/tlogger/tlogger.rb, line 356 def find_caller caller.each do |c| next if c =~ /tlogger.rb/ @cal = c break end if @cal.nil? or @cal.empty? @cal = caller[0] end # reduce it down to last two folder? sp = @cal.split(File::SEPARATOR) if sp.length > 1 msg = "/#{sp[-2]}/#{sp[-1]}" else msg = sp[-1] end msg end
# File lib/tlogger/tlogger.rb, line 322 def format_message(key) # returning args array if @include_caller "[#{key}] #{find_caller} " else "[#{key}] " end end
# File lib/tlogger/tlogger.rb, line 331 def is_genabled?(key) if key.nil? true else (@genable and not @exception.include?(key.to_sym)) or (not @genable and @exception.include?(key.to_sym)) end end