sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/

lib/sup/logger.rb (2010B) - raw

      1 require "sup/util"
      2 require 'stringio'
      3 require 'thread'
      4 
      5 module Redwood
      6 
      7 ## simple centralized logger. outputs to multiple sinks by calling << on them.
      8 ## also keeps a record of all messages, so that adding a new sink will send all
      9 ## previous messages to it by default.
     10 class Logger
     11   include Redwood::Singleton
     12 
     13   LEVELS = %w(debug info warn error) # in order!
     14 
     15   def initialize level=nil
     16     level ||= ENV["SUP_LOG_LEVEL"] || "info"
     17     self.level = level
     18     @mutex = Mutex.new
     19     @buf = StringIO.new
     20     @sinks = []
     21   end
     22 
     23   def level; LEVELS[@level] end
     24   def level=(level); @level = LEVELS.index(level) || raise(ArgumentError, "invalid log level #{level.inspect}: should be one of #{LEVELS * ', '}"); end
     25 
     26   def add_sink s, copy_current=true
     27     @mutex.synchronize do
     28       @sinks << s
     29       s << @buf.string if copy_current
     30     end
     31   end
     32 
     33   def remove_sink s; @mutex.synchronize { @sinks.delete s } end
     34   def remove_all_sinks!; @mutex.synchronize { @sinks.clear } end
     35   def clear!; @mutex.synchronize { @buf = StringIO.new } end
     36 
     37   LEVELS.each_with_index do |l, method_level|
     38     define_method(l) do |s|
     39       if method_level >= @level
     40         send_message format_message(l, Time.now, s)
     41       end
     42     end
     43   end
     44 
     45   ## send a message regardless of the current logging level
     46   def force_message m; send_message format_message(nil, Time.now, m) end
     47 
     48 private
     49 
     50   ## level can be nil!
     51   def format_message level, time, msg
     52     prefix = case level
     53       when "warn"; "WARNING: "
     54       when "error"; "ERROR: "
     55       else ""
     56     end
     57     "[#{time.to_s}] #{prefix}#{msg.rstrip}\n"
     58   end
     59 
     60   ## actually distribute the message
     61   def send_message m
     62     @mutex.synchronize do
     63       @sinks.each do |sink|
     64         sink << m
     65         sink.flush if sink.respond_to?(:flush) and level == "debug"
     66       end
     67       @buf << m
     68     end
     69   end
     70 end
     71 
     72 ## include me to have top-level #debug, #info, etc. methods.
     73 module LogsStuff
     74   Logger::LEVELS.each { |l| define_method(l) { |s, uplevel = 0| Logger.instance.send(l, s) } }
     75 end
     76 
     77 end