File: logger.rb

package info (click to toggle)
sup-mail 1.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,412 kB
  • sloc: ruby: 13,047; sh: 167; makefile: 12
file content (77 lines) | stat: -rw-r--r-- 2,010 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
require "sup/util"
require 'stringio'
require 'thread'

module Redwood

## simple centralized logger. outputs to multiple sinks by calling << on them.
## also keeps a record of all messages, so that adding a new sink will send all
## previous messages to it by default.
class Logger
  include Redwood::Singleton

  LEVELS = %w(debug info warn error) # in order!

  def initialize level=nil
    level ||= ENV["SUP_LOG_LEVEL"] || "info"
    self.level = level
    @mutex = Mutex.new
    @buf = StringIO.new
    @sinks = []
  end

  def level; LEVELS[@level] end
  def level=(level); @level = LEVELS.index(level) || raise(ArgumentError, "invalid log level #{level.inspect}: should be one of #{LEVELS * ', '}"); end

  def add_sink s, copy_current=true
    @mutex.synchronize do
      @sinks << s
      s << @buf.string if copy_current
    end
  end

  def remove_sink s; @mutex.synchronize { @sinks.delete s } end
  def remove_all_sinks!; @mutex.synchronize { @sinks.clear } end
  def clear!; @mutex.synchronize { @buf = StringIO.new } end

  LEVELS.each_with_index do |l, method_level|
    define_method(l) do |s|
      if method_level >= @level
        send_message format_message(l, Time.now, s)
      end
    end
  end

  ## send a message regardless of the current logging level
  def force_message m; send_message format_message(nil, Time.now, m) end

private

  ## level can be nil!
  def format_message level, time, msg
    prefix = case level
      when "warn"; "WARNING: "
      when "error"; "ERROR: "
      else ""
    end
    "[#{time.to_s}] #{prefix}#{msg.rstrip}\n"
  end

  ## actually distribute the message
  def send_message m
    @mutex.synchronize do
      @sinks.each do |sink|
        sink << m
        sink.flush if sink.respond_to?(:flush) and level == "debug"
      end
      @buf << m
    end
  end
end

## include me to have top-level #debug, #info, etc. methods.
module LogsStuff
  Logger::LEVELS.each { |l| define_method(l) { |s, uplevel = 0| Logger.instance.send(l, s) } }
end

end