Good afternoon.
I want to replace the Logger from Ruby core by my own simplistic Module
“BasicLogging”, after years, when I had to admit that I am anyway never using
all the features of the Logger class: It is the same formater for everything
and I had never use for object- or class-specific configurations.  This
facilitates the configuration of the logger from an application-wide
configuration. I can still “mute” individual objects/classes to reduce the
output.
The whole module is attached below this post.
Chances are, I oversee a bunch of problems with my code. Programming is 
just a hobby. Are there obvious glitches, which I must address? In one of 
my programs, my module appears to work just as I like it to.
Here a usage example for a class-level logger:
------------
  Array.extend(BasicLogging)
  Array.set_level(BasicLogging::INFO)
  Array.info('TEST')
-----------
output: 
Array [class] info 16:22:26:662619: TEST
Object-level:
------------
  ar = Array.new
  ar.extend(BasicLogging)
  # --- no output, default level is UNKNOWN : 
  l = __LINE__
  ar.debug(l.next.to_s << ': debug-test 0')
  # output on level debug
  ar.set_level(BasicLogging::DEBUG)
  l = __LINE__
  ar.debug(l.next.to_s << ': debug-test 1')
--------------
output:
Array debug 16:22:26:662894: 124: debug-test 1
The file basic_logging.rb contains more test-code at the bottom. Thank you 
for any comments. Shoot at will. 
---------------------- basic_logging.rb -------------------
#!/bin/env ruby
#encoding: UTF-8
=begin
/***************************************************************************
 *   ©2023-2023, Michael Uplawski <
news:michael....@uplawski.eu>           *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the WTFPL 2.0 or later, see                     * 
 *   <
http://www.wtfpl.net/about/>                                           *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                  *
 *                                                                         *
 ***************************************************************************/
=end
#
# Simplified logging. 
# See example code at the bottom of this file.
# Execute this file to see the output.
module BasicLogging
  DEBUG = 0
  INFO =  1
  WARN =  2
  ERROR = 3
  FATAL = 4
  UNKNOWN = nil
  
  # this is mainly for the translation of method calls into log levels
  Levels = {:debug => DEBUG, :info => INFO, :warn => WARN, :error => ERROR,
            :fatal => FATAL, :unknown => UNKNOWN}
  @@log_level = UNKNOWN
  @@target = STDOUT
  @@muted = []
  # do not log, if caller is obj (class or instance)
  def self.mute(obj)
    name = obj.class == Class ? obj.name.dup : 
obj.class.name
    @@muted << name
  end
  def self.is_muted?(obj)
    name = obj.class == Class ? obj.name.dup : 
obj.class.name
    @@muted.include?(name)  
  end
  # set the log level 
  def set_level(lv)
    if lv.respond_to?(:to_str)
      lv = Levels[lv.to_sym]
    end
    if(!lv || (lv.respond_to?(:to_int) && lv >= DEBUG && lv <= FATAL) )
      @@log_level = lv
    else
      STDERR.puts __FILE__.dup << ": ERROR : invalid log level \"" << lv.to_s << "\""
      STDERR.puts "Keepinng old log level " << Levels.keys.detect {| k| Levels[k] == @@log_level}.to_s
    end
  end
  # set the log target 
  def set_target(tg)
    if tg.respond_to?(:to_io) 
      @@target = tg
    elsif(!File::exist?(tg) || ( File.file?(tg) && File.writable?(tg) ) )
      @@target = File.open(tg, 'w+')  
    else
      STDERR.puts __FILE__.dup << ': ERROR : target ' << tg << ' cannot be set'
      STDERR.puts "Keeping old target " << @@target.inspect
      return
    end
  end
  # Output of log messages, depending on the log level 
  # and the name of the alias method which is actually called.
  def log(message)
    if !BasicLogging.is_muted?(self)
      # how has this method been called?
      mlevel = __callee__
      if Levels.has_key?(mlevel) && Levels[mlevel] <=  FATAL
        # output only for levels equal or above the value that corresponds to
        # the calling alias.
        format_log( message, mlevel) if @@log_level && Levels[mlevel] >= @@log_level 
      else
        STDERR.puts __FILE__.dup << ": ERROR : invalid log level \"" << mlevel.to_s << "\""
      end
    end
  end
  alias :debug :log
  alias :info :log
  alias :warn :log
  alias :error :log
  alias :fatal :log
  private 
  # 1 format for all loggers.
  def format_log(message, mlevel)
    # indicate if a class or an instance of a class is calling.
    name = self.class == Class ? self.name.dup << ' [class]' : 
self.class.name
    @@target.puts '' << name << ' ' << mlevel.to_s << ' ' << Time.now.strftime("%H:%M:%S:%6N")  << ': ' << message
  end
end
#---------test: execute file----------
if $0 == __FILE__
  Array.extend(BasicLogging)
  Array.set_level(BasicLogging::INFO)
  Array.info('TEST')
  ar = Array.new
  ar.extend(BasicLogging)
  # --- no output : 
  l = __LINE__
  ar.debug(l.next.to_s << ': debug-test 0')
  # output
  ar.set_level(BasicLogging::DEBUG)
  l = __LINE__
  ar.debug(l.next.to_s << ': debug-test 1')
  obj = Object.new
  obj.extend(BasicLogging)
  obj.set_level(BasicLogging::DEBUG)
  puts "--------debug-----------"
  obj.debug('debug')
  
obj.info('info')
  obj.warn('warn')
  obj.error('error')
  obj.fatal('fatal')
  puts "--------info-----------"
  obj.set_level("info")
  obj.debug('debug')
  
obj.info('info')
  obj.warn('warn')
  obj.error('error')
  obj.fatal('fatal')
  puts "--------fatal-----------"
  obj.set_level("fatal")
  obj.debug('debug')
  
obj.info('info')
  obj.warn('warn')
  obj.error('error')
  obj.fatal('fatal')
  puts "--------UNKNOWN-----------"
  obj.set_level(nil)
  obj.debug('debug')
  
obj.info('info')
  obj.warn('warn')
  obj.error('error')
  obj.fatal('fatal')
  puts " ------ Output into file ----"
  obj.set_target "/tmp/test_log.log"
  puts " ------ INFO -----------"
  obj.set_level BasicLogging::INFO
  
obj.info('info output')
  
obj.info('info output 2') 
  puts "---------- invalid -------"
  obj.set_target "/dev/sr0"
  obj.set_level "power"
end
# EOF