Merge lp://staging/~laliputienses/lalita/fix-logs into lp://staging/lalita

Proposed by Facundo Batista
Status: Merged
Merge reported by: Facundo Batista
Merged at revision: not available
Proposed branch: lp://staging/~laliputienses/lalita/fix-logs
Merge into: lp://staging/lalita
Diff against target: 248 lines
1 file modified
ircbot.py (+66/-42)
To merge this branch: bzr merge lp://staging/~laliputienses/lalita/fix-logs
Reviewer Review Type Date Requested Status
Guillermo Gonzalez Pending
laliputienses Pending
Review via email: mp+12494@code.staging.launchpad.net
To post a comment you must log in.
Revision history for this message
Facundo Batista (facundo) wrote :

I'm asking review here specially because there's a bug in the actual code situation.

If I start the bot like...

   ircbot.py -f debug freenode

...the log in the file will be DEBUG and the log in the stdout will be INFO. This is OK! But if something bad happens (try breaking a plugin on purpose, for example, to get an exception), this exception will be logged in the file but NOT shown in the standard output. Why??

Revision history for this message
Guillermo Gonzalez (verterok) wrote :

I need to take a closer look...but what you'r trying to do works out of the box. So my bet is that there is a bug somewhere in the logger configuration/setup for the plugins/dispatcher.

e.g:

>>> import logging
>>> l = logging.getLogger('ircbot')
>>> lp = logging.getLogger('ircbot.plugins.Foo')
>>> h1 = logging.StreamHandler()
>>> h1.setLevel(logging.INFO)
>>> l.addHandler(h1)
>>> h = logging.StreamHandler()
>>> h.setLevel(logging.DEBUG)
>>> l.addHandler(h)
>>> lp.debug('foo')
>>> lp.getEffectiveLevel()
30
>>> l.getEffectiveLevel()
30
>>> l.setLevel(logging.INFO)
>>> lp.setLevel(logging.DEBUG)
>>> l.getEffectiveLevel()
20
>>> lp.getEffectiveLevel()
10
>>> lp.debug('foo')
foo
>>> l.debug('foo')
>>> l.info('foo')
foo
>>> lp.error('foo')
foo
foo
>>> l.error('foo')
foo
foo

Revision history for this message
Facundo Batista (facundo) wrote :

> I need to take a closer look...but what you'r trying to do works out of the
> box. So my bet is that there is a bug somewhere in the logger
> configuration/setup for the plugins/dispatcher.

Ok, I merge this... we can check later what happens...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ircbot.py'
2--- ircbot.py 2009-09-26 19:19:30 +0000
3+++ ircbot.py 2009-09-27 18:55:19 +0000
4@@ -36,25 +36,23 @@
5 "critical": logging.CRITICAL,
6 }
7
8-handler = logging.StreamHandler(sys.stdout)
9-formatter = logging.Formatter(
10- "%(asctime)s %(name)s:%(lineno)-4d %(levelname)-8s %(message)s",
11- '%H:%M:%S')
12-handler.setFormatter(formatter)
13+log_stdout_handler = logging.StreamHandler(sys.stdout)
14+formatter = logging.Formatter("%(asctime)s %(name)s:%(lineno)-4d "
15+ "%(levelname)-8s %(message)s",
16+ '%Y-%m-%d %H:%M:%S')
17+log_stdout_handler.setFormatter(formatter)
18 logger = logging.getLogger('ircbot')
19-logger.addHandler(handler)
20-
21+logger.addHandler(log_stdout_handler)
22+logger.setLevel(logging.DEBUG)
23
24 class IrcBot (irc.IRCClient):
25 """A IRC bot."""
26 def __init__ (self, *more):
27 self.dispatcher = dispatcher.Dispatcher(self)
28 self._plugins = {}
29- logger.debug ("we're in(ited)!")
30- # logger.debug (more)
31+ logger.info("We're in(ited)!")
32
33 def load_plugin (self, plugin_name, config, params, channel=None):
34- # logger.debug (config)
35 if "plugins_dir" in self.config:
36 path = self.config["plugins_dir"]
37 else:
38@@ -71,22 +69,22 @@
39 self.dispatcher.new_plugin(instance, channel)
40 instance.init(config)
41 except ImportError, e:
42- logger.error('%s not instanced: %s' % (plugin_name, e))
43+ logger.error('%s not instanced: %s', plugin_name, e)
44 except AttributeError, e:
45- logger.error('%s not instanced: %s' % (plugin_name, e))
46+ logger.error('%s not instanced: %s', plugin_name, e)
47 except Exception, e:
48- logger.error('%s not instanced: %s' % (plugin_name, e))
49+ logger.error('%s not instanced: %s', plugin_name, e)
50 print_exc (e)
51 else:
52- logger.info ('%s instanced for %s' % (plugin_name,
53- (channel is not None) and channel or 'server'))
54+ logger.info('%s instanced for %s', plugin_name,
55+ (channel is not None) and channel or 'server')
56
57 def load_server_plugins(self):
58 params = {'nickname': self.nickname,
59 'encoding': self.encoding_server}
60
61 plugins= self.config.get('plugins', {})
62- logger.debug ("server plugins: %s" % plugins)
63+ logger.debug("server plugins: %s", plugins)
64 for plugin, config in plugins.items():
65 self.load_plugin(plugin, config, params)
66
67@@ -96,7 +94,7 @@
68 self.encoding_server)}
69
70 plugins= self.config['channels'][channel].get ('plugins', {})
71- logger.debug ("channel plugins: %s" % plugins)
72+ logger.debug("channel plugins: %s", plugins)
73 for plugin, config in plugins.items ():
74 self.load_plugin (plugin, config, params, channel)
75
76@@ -109,8 +107,8 @@
77 if "encoding" in v)
78 self.password = self.config.get('password', None)
79 irc.IRCClient.connectionMade (self)
80- logger.info("connected to %s:%d" %
81- (self.config['host'], self.config['port']))
82+ logger.info("connected to %s:%d",
83+ self.config['host'], self.config['port'])
84 self.load_server_plugins()
85 # configure the dispatcher
86 self.dispatcher.init(self.config)
87@@ -118,26 +116,26 @@
88
89 def connectionLost(self, reason):
90 irc.IRCClient.connectionLost(self, reason)
91- logger.info ("disconnected from %s:%d" %
92- (self.config.get('host'), self.config.get('port')))
93+ logger.info("disconnected from %s:%d",
94+ self.config.get('host'), self.config.get('port'))
95 self.dispatcher.push(events.CONNECTION_LOST)
96
97 def signedOn(self):
98- logger.debug ("signed on %s:%d" %
99- (self.config['host'], self.config['port']))
100+ logger.debug("signed on %s:%d",
101+ self.config['host'], self.config['port'])
102 self.dispatcher.push(events.SIGNED_ON)
103 for channel in self.config.get ('channels', []):
104- logger.debug ("joining %s on %s:%d" %
105- (channel, self.config['host'], self.config['port']))
106+ logger.debug("joining %s on %s:%d",
107+ channel, self.config['host'], self.config['port'])
108 self.join (channel)
109
110 def receivedMOTD(self, motd):
111- logger.debug ("motd from %s:%d" %
112- (self.config['host'], self.config['port']))
113+ logger.debug("motd from %s:%d",
114+ self.config['host'], self.config['port'])
115
116 def joined(self, channel):
117 """This will get called when the bot joins the channel."""
118- logger.info ("joined to %s" % channel)
119+ logger.info("joined to %s", channel)
120 self.load_channel_plugins (channel)
121 self.dispatcher.push(events.JOINED, channel)
122
123@@ -147,9 +145,8 @@
124 encoding = self.encoding_channels.get(channel, self.encoding_server)
125 msg = msg.decode(encoding)
126
127- logger.debug ("[%s] %s: %s" % (channel, user, msg))
128+ logger.debug("[%s] %s: %s", channel, user, msg)
129 user = user.split('!', 1)[0]
130- # self.logger.log("<%s> %s" % (user, msg))
131
132 # Check to see if they're sending me a private message
133 if channel == self.nickname:
134@@ -220,7 +217,7 @@
135 """
136 If we get disconnected, reconnect to server.
137 """
138- logger.debug("We got disconnected because of %s" % str(reason))
139+ logger.debug("We got disconnected because of %s", reason)
140 connector.connect()
141
142 def clientConnectionFailed(self, connector, reason):
143@@ -228,13 +225,12 @@
144 Stop main loop if connection failed, this should be changed to stop
145 only when no client remains connected
146 """
147- logger.debug("Connection failed because of %s" % str(reason))
148+ logger.debug("Connection failed because of %s", reason)
149 # reactor.stop()
150
151-def main(to_use, plugin_loglvl):
152+def main(to_use, plugins_loglvl):
153 for server in to_use:
154- # logger.debug (plugin_loglvl)
155- server["log_config"] = plugin_loglvl
156+ server["log_config"] = plugins_loglvl
157 bot = IRCBotFactory(server)
158 if server.get('ssl', False):
159 reactor.connectSSL(server.get('host', '10.100.0.194'),
160@@ -248,11 +244,14 @@
161
162 if __name__ == '__main__':
163 msg = u"""
164- ircbot.py [-t][-a][-o output_loglvl][-p plugin_loglvl] [server1, [...]]
165+ ircbot.py [-t][-a][-o output_loglvl][-p plugins_loglvl]
166+ [-f fileloglvl][-n logfname] [server1, [...]]
167
168 the servers are optional if -a is passed
169- the output_loglevel is the log level default for all the system
170+ the output_loglevel is the log level for the standard output
171+ the file_loglevel is the log level for the output that goes to file
172 the pluginloglevel is a list of plugin_name:loglevel separated by commas
173+ the logfname is the filename to write the logs to
174 """
175
176 parser = optparse.OptionParser()
177@@ -265,6 +264,10 @@
178 help="sets the output log level.")
179 parser.add_option("-p", "--plugin-log-level", dest="plugloglvl",
180 help="sets the plugin log level. format is plugin:level,...")
181+ parser.add_option("-f", "--file-log-level", dest="fileloglvl",
182+ help="sets the output log level.")
183+ parser.add_option("-n", "--log-filename", dest="logfname",
184+ help="specifies the name of the log file.")
185
186 (options, args) = parser.parse_args()
187 test = bool(options.test)
188@@ -275,27 +278,28 @@
189 parser.print_help()
190 exit()
191
192- # control the log level
193+ # control the output log level
194 if options.outloglvl is None:
195- output_loglevel = "debug"
196+ output_loglevel = "info"
197 else:
198 output_loglevel = options.outloglvl.lower()
199 try:
200- logger.setLevel(LOG_LEVELS[output_loglevel])
201+ log_stdout_handler.setLevel(LOG_LEVELS[output_loglevel])
202 except KeyError:
203 print "The log level can be only:", LOG_LEVELS.keys()
204 exit(1)
205
206+ # control the plugins log level
207 plugins_loglvl = {}
208 if options.plugloglvl is not None:
209 try:
210 for pair in options.plugloglvl.split(","):
211 plugin, loglvl = pair.split(":")
212 loglvl = loglvl.lower()
213- logger.debug ("plugin %s, loglevel %s" % (plugin, loglvl))
214+ logger.debug("plugin %s, loglevel %s" % (plugin, loglvl))
215 if loglvl not in LOG_LEVELS:
216 print "The log level can be only:", LOG_LEVELS.keys()
217- exit()
218+ exit(1)
219 plugins_loglvl[plugin] = LOG_LEVELS[loglvl]
220 except:
221 print "Remember that the plugin log level format is"
222@@ -310,6 +314,26 @@
223 print "See as an example the included here config.py.example"
224 sys.exit()
225
226+ # handles the log file and its level
227+ if options.logfname is None:
228+ log_filename = "lalita.log"
229+ else:
230+ log_filename = options.logfname
231+
232+ if options.fileloglvl is None:
233+ file_loglevel = logging.INFO
234+ else:
235+ try:
236+ file_loglevel = LOG_LEVELS[options.fileloglvl.lower()]
237+ except KeyError:
238+ print "The log level can be only:", LOG_LEVELS.keys()
239+ exit(1)
240+
241+ fh = logging.FileHandler(log_filename)
242+ fh.setLevel(file_loglevel)
243+ fh.setFormatter(formatter)
244+ logger.addHandler(fh)
245+
246 # get all servers or the indicated ones
247 servers = config.servers
248 if all_servers:

Subscribers

People subscribed via source and target branches

to all changes: