]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - lib/rbot/logger.rb
fix: TCPSocked.gethostbyname is deprecated
[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 enable_console_logger
18       @console_logger = Logger.new(STDERR)
19       @console_logger.datetime_format = @dateformat
20       @console_logger.level = Logger::Severity::DEBUG
21     end
22
23     def disable_console_logger
24       @console_logger = nil
25     end
26
27     def initialize
28       @dateformat = "%Y/%m/%d %H:%M:%S"
29
30       enable_console_logger
31
32       @file_logger = nil
33
34       @queue = Queue.new
35       start_thread
36     end
37
38     def set_logfile(filename, keep, max_size)
39       # close previous file logger if present
40       @file_logger.close if @file_logger
41
42       @file_logger = Logger.new(filename, keep, max_size*1024*1024)
43       @file_logger.datetime_format = @dateformat
44       @file_logger.level = @console_logger.level
45
46       # make sure the thread is running, which might be false after a fork
47       # (conveniently, we call set_logfile right after the fork)
48       start_thread
49     end
50
51     def set_level(level)
52       @console_logger.level = level if @console_logger
53       @file_logger.level = level if @file_logger
54     end
55
56     def sync_log(severity, message = nil, progname = nil)
57       @console_logger.add(severity, message, progname) if @console_logger
58       @file_logger.add(severity, message, progname) if @file_logger
59     end
60
61     def async_log(severity, message=nil, who_pos=1)
62       unless @thread
63         STDERR.puts('logger thread already destroyed, cannot log message!')
64       end
65
66       call_stack = caller
67       if call_stack.length > who_pos
68         who = call_stack[who_pos].sub(%r{(?:.+)/([^/]+):(\d+)(:in .*)?}) { "#{$1}:#{$2}#{$3}" }
69       else
70         who = "(unknown)"
71       end
72       # Output each line. To distinguish between separate messages and multi-line
73       # messages originating at the same time, we blank #{who} after the first message
74       # is output.
75       # Also, we output strings as-is but for other objects we use pretty_inspect
76       message = message.kind_of?(String) ? message : (message.pretty_inspect rescue '?')
77       qmsg = Array.new
78       message.each_line { |l|
79         qmsg.push [severity, l.chomp, who]
80         who = ' ' * who.size
81       }
82       @queue.push qmsg
83     end
84
85     def log_session_start
86       # if we forked, the thread may be dead, so let's restart it if necessary
87       start_thread
88       if @file_logger
89         @file_logger << "\n\n=== session started on #{Time.now.strftime(@dateformat)} ===\n\n"
90       end
91     end
92
93     def log_session_end
94       if @file_logger
95         @file_logger << "\n\n=== session ended on #{Time.now.strftime(@dateformat)} ===\n\n"
96       end
97     end
98
99     def halt_logger
100       if @thread and @thread.alive?
101         @queue << nil
102         @thread.join
103         @thread = nil
104         log_session_end
105       end
106     end
107
108     def flush
109       while @queue.size > 0
110         next
111       end
112     end
113
114     private
115
116     def start_thread
117       return if @thread and @thread.alive?
118       @thread = Thread.new do
119         lines = nil
120         while lines = @queue.pop
121           lines.each { |line|
122             sync_log(*line)
123           }
124         end
125       end
126     end
127
128   end
129
130 end
131 end
132
133 def debug(message=nil, who_pos=1)
134   Irc::Bot::LoggerManager.instance.async_log(Logger::Severity::DEBUG, message, who_pos)
135 end
136
137 def log(message=nil, who_pos=1)
138   Irc::Bot::LoggerManager.instance.async_log(Logger::Severity::INFO, message, who_pos)
139 end
140
141 def warning(message=nil, who_pos=1)
142   Irc::Bot::LoggerManager.instance.async_log(Logger::Severity::WARN, message, who_pos)
143 end
144
145 def error(message=nil, who_pos=1)
146   Irc::Bot::LoggerManager.instance.async_log(Logger::Severity::ERROR, message, who_pos)
147 end
148
149 def fatal(message=nil, who_pos=1)
150   Irc::Bot::LoggerManager.instance.async_log(Logger::Severity::FATAL, message, who_pos)
151 end