]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - lib/rbot/logger.rb
b5f615d7881ed061f948a28ec1db55cd65601e35
[user/henk/code/ruby/rbot.git] / lib / rbot / logger.rb
1 # encoding: UTF-8
2 #-- vim:sw=2:et
3 #++
4 #
5 # :title: rbot logger
6
7 require 'logger'
8 require 'thread'
9 require 'singleton'
10
11 module Irc
12 class Bot
13
14   class LoggerManager
15     include Singleton
16
17     def initialize
18       @dateformat = "%Y/%m/%d %H:%M:%S"
19
20       @logger = Logger.new(STDERR)
21       @logger.datetime_format = @dateformat
22       @logger.level = Logger::Severity::DEBUG
23       @file_logger = nil
24
25       @queue = Queue.new
26       @thread = start_thread
27     end
28
29     def set_logfile(filename, keep, max_size)
30       @file_logger = Logger.new(filename, keep, max_size*1024*1024)
31       @file_logger.datetime_format = @dateformat
32       @file_logger.level = @logger.level
33     end
34
35     def set_level(level)
36       @logger.level = level
37       if @file_logger
38         @file_logger.level = level
39       end
40     end
41
42     def sync_log(severity, message = nil, progname = nil)
43       @logger.add(severity, message, progname)
44       if @file_logger
45         @file_logger.add(severity, message, progname)
46       end
47     end
48
49     def async_log(severity, message=nil, who_pos=1)
50       unless @thread
51         STDERR.puts('logger thread already destroyed, cannot log message!')
52       end
53
54       call_stack = caller
55       if call_stack.length > who_pos
56         who = call_stack[who_pos].sub(%r{(?:.+)/([^/]+):(\d+)(:in .*)?}) { "#{$1}:#{$2}#{$3}" }
57       else
58         who = "(unknown)"
59       end
60       # Output each line. To distinguish between separate messages and multi-line
61       # messages originating at the same time, we blank #{who} after the first message
62       # is output.
63       # Also, we output strings as-is but for other objects we use pretty_inspect
64       message = message.kind_of?(String) ? message : (message.pretty_inspect rescue '?')
65       qmsg = Array.new
66       message.each_line { |l|
67         qmsg.push [severity, l.chomp, who]
68         who = ' ' * who.size
69       }
70       @queue.push qmsg
71     end
72
73     def log_session_start
74       if @file_logger
75         @file_logger << "\n\n=== session started on #{Time.now.strftime(@dateformat)} ===\n\n"
76       end
77     end
78
79     def log_session_end
80       if @file_logger
81         @file_logger << "\n\n=== session ended on #{Time.now.strftime(@dateformat)} ===\n\n"
82       end
83     end
84
85     def halt_logger
86       if @thread and @thread.alive?
87         @queue << nil
88         @thread.join
89         @thread = nil
90       end
91     end
92
93     private
94
95     def start_thread
96       Thread.new do
97         lines = nil
98         while lines = @queue.pop
99           lines.each { |line|
100             sync_log(*line)
101           }
102         end
103       end
104     end
105
106   end
107
108 end
109 end
110
111 def debug(message=nil, who_pos=1)
112   Irc::Bot::LoggerManager.instance.async_log(Logger::Severity::DEBUG, message, who_pos)
113 end
114
115 def log(message=nil, who_pos=1)
116   Irc::Bot::LoggerManager.instance.async_log(Logger::Severity::INFO, message, who_pos)
117 end
118
119 def warning(message=nil, who_pos=1)
120   Irc::Bot::LoggerManager.instance.async_log(Logger::Severity::WARN, message, who_pos)
121 end
122
123 def error(message=nil, who_pos=1)
124   Irc::Bot::LoggerManager.instance.async_log(Logger::Severity::ERROR, message, who_pos)
125 end
126
127 def fatal(message=nil, who_pos=1)
128   Irc::Bot::LoggerManager.instance.async_log(Logger::Severity::FATAL, message, who_pos)
129 end