require 'logger' require 'singleton' require "tlogger/version" module Tlogger class Error < StandardError; end # Your code goes here... # # Singleton object to facilitate tag management # class TloggerConf include Singleton attr_reader :active_tags, :scoped_tag, :blacklisted_tags, :show_source #GLOBAL_TAG = :global GLOBAL_TAG = "" INT_TAG = :tlogger def initialize @active_tags = [] # tag added to black listed will not be printed out even the tag is added later in the code path @blacklisted_tags = [] @disable_all_tags = false @auto_tag = false # todo # allow to redirect certain tag to specific output. tag: [] @output_map = {} # if output_map is there, then there should be pre created log file with specific output defined in the map. [] => log_instance @output_log = {} # show where is the log being printed out. Like auto_tag output @show_source = false # end todo end def show_source @show_source = true end alias_method :auto_tag_on, :show_source def hide_source @show_source = false end alias_method :auto_tag_off, :hide_source def is_show_source? @show_source end alias_method :is_auto_tag_on?, :is_show_source? #def auto_tag_on # @auto_tag = true #end #def auto_tag_off # @auto_tag = false #end #def is_auto_tag_on? # @auto_tag #end def activate_tag(tag) @active_tags << tag end def deactivate_tag(tag) @active_tags.delete(tag) end def blacklist_tag(tag) if tag.is_a?(Array) @blacklisted_tags += tag else @blacklisted_tags << tag end end def all_tags_off @disable_all_tags = true end def all_tags_on @disable_all_tags = false end def whitelist_tag(tag) if tag.is_a?(Array) tag.each do |t| @blacklisted_tags.delete(t) end else @blacklisted_tags.delete(tag) end end def whitelist_all_tags @disabled_tags.clear end def is_tag_active?(tag) if @disable_all_tags false else @active_tags.include?(tag) #and not @disabled_tags.include?(tag) end end def remove_all_active_tags @active_tags.clear end def set_scoped_tag(tag) @scoped_tag = tag end def clear_scoped_tag @scoped_tag = nil end def has_scoped_tag? if @disable_all_tags false else not @scoped_tag.nil? and not @scoped_tag.empty? end end def is_scoped_tag_active? #@active_tags.include?(@scoped_tag) not @blacklisted_tags.include?(@scoped_tag) end def self.method_missing(mtd,*args,&block) if TloggerConf.instance.respond_to?(mtd) TloggerConf.instance.send(mtd,*args,&block) else super end end end # # end TloggerConf singleton # # # add object like methods to make module a class # class << self attr_accessor :tag include Tlogger PROXY_MTD = [:debug, :info, :error, :warn] def new(*args) if args.length == 0 args << STDOUT end @tlogger = Logger.new(*args) @tag = TloggerConf::GLOBAL_TAG # disable by default # If there is issue then enable it back in application level self end def tag=(val) @tag = val TloggerConf.activate_tag(@tag) self end def tdebug(tag,*args) with_tag(tag) do self.debug(*args) end self end def terror(tag, *args) with_tag(tag) do self.error(*args) end self end def tinfo(tag, *args) with_tag(tag) do self.info(*args) end self end def twarn(tag, *args) with_tag(tag) do self.warn(*args) end self end def intDebug(msg) #puts TloggerConf.active_tags if TloggerConf.instance.is_tag_active?(TloggerConf::INT_TAG) msg2 = "[#{TloggerConf::INT_TAG}] #{msg}" #puts "intDebug" @tlogger.debug(msg2) end end def method_missing(mtd,*args,&block) #@tlogger.debug "[tlogger] method_missing: Method #{mtd}" intDebug("method_missing: #{mtd}") if @tlogger.respond_to?(mtd) if PROXY_MTD.include?(mtd) if @tag.nil? or @tag.empty? # no tag. Output like normal log @tlogger.send(mtd, *args, &block) else if TloggerConf.has_scoped_tag? if TloggerConf.is_scoped_tag_active? intDebug("Scoped tag detected") tag = [] tag << TloggerConf.scoped_tag if TloggerConf.instance.is_show_source? tag << " - " tag << find_caller end args[0] = "[#{tag.join}] #{args[0]}" @tlogger.send(mtd,*args,&block) end elsif TloggerConf.is_auto_tag_on? intDebug("auto_tag is on...") args = tag_class(*args) @tlogger.send(mtd,*args,&block) elsif TloggerConf.is_tag_active?(@tag) intDebug("Tagged output...") tag = [] tag << @tag if TloggerConf.instance.is_show_source? tag << " - " tag << find_caller end args[0] = "[#{tag.join}] #{args[0]}" @tlogger.send(mtd,*args,&block) end end else intDebug("Not proxy method for logger. Pass to logger to handle. (#{mtd})") ## not the debug, info, warn and error method, no need change message @tlogger.send(mtd, *args, &block) end elsif TloggerConf.instance.respond_to?(mtd) # redirect the config method to make it consistent API intDebug("Redirect to TloggerConf for consistancy (#{mtd})") TloggerConf.send(mtd, *args, &block) else intDebug("Call method_missing parent to handle method '#{mtd}'") super end end # end method_missing # private def tag_class(*args) args[0] = "[#{find_caller}] #{args[0]}" args end # end tag_class() # 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 #wd = Dir.getwd #indx = @cal =~ /#{wd}/ #if indx != nil # @scal = [] # @scal << @cal[0..indx] # @scal << @cal[indx+wd.length..-1] # @scal.join #else # @cal #end end # end find_caller # end # # end class definition # def with_tag(tag,&block) if block TloggerConf.instance.set_scoped_tag(tag) #if not TloggerConf.instance.disabled_tags.include?(tag) block.call TloggerConf.instance.clear_scoped_tag end end end