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
=== modified file 'ircbot.py'
--- ircbot.py 2009-09-26 19:19:30 +0000
+++ ircbot.py 2009-09-27 18:55:19 +0000
@@ -36,25 +36,23 @@
36 "critical": logging.CRITICAL,36 "critical": logging.CRITICAL,
37}37}
3838
39handler = logging.StreamHandler(sys.stdout)39log_stdout_handler = logging.StreamHandler(sys.stdout)
40formatter = logging.Formatter(40formatter = logging.Formatter("%(asctime)s %(name)s:%(lineno)-4d "
41 "%(asctime)s %(name)s:%(lineno)-4d %(levelname)-8s %(message)s",41 "%(levelname)-8s %(message)s",
42 '%H:%M:%S')42 '%Y-%m-%d %H:%M:%S')
43handler.setFormatter(formatter)43log_stdout_handler.setFormatter(formatter)
44logger = logging.getLogger('ircbot')44logger = logging.getLogger('ircbot')
45logger.addHandler(handler)45logger.addHandler(log_stdout_handler)
4646logger.setLevel(logging.DEBUG)
4747
48class IrcBot (irc.IRCClient):48class IrcBot (irc.IRCClient):
49 """A IRC bot."""49 """A IRC bot."""
50 def __init__ (self, *more):50 def __init__ (self, *more):
51 self.dispatcher = dispatcher.Dispatcher(self)51 self.dispatcher = dispatcher.Dispatcher(self)
52 self._plugins = {}52 self._plugins = {}
53 logger.debug ("we're in(ited)!")53 logger.info("We're in(ited)!")
54 # logger.debug (more)
5554
56 def load_plugin (self, plugin_name, config, params, channel=None):55 def load_plugin (self, plugin_name, config, params, channel=None):
57 # logger.debug (config)
58 if "plugins_dir" in self.config:56 if "plugins_dir" in self.config:
59 path = self.config["plugins_dir"]57 path = self.config["plugins_dir"]
60 else:58 else:
@@ -71,22 +69,22 @@
71 self.dispatcher.new_plugin(instance, channel)69 self.dispatcher.new_plugin(instance, channel)
72 instance.init(config)70 instance.init(config)
73 except ImportError, e:71 except ImportError, e:
74 logger.error('%s not instanced: %s' % (plugin_name, e))72 logger.error('%s not instanced: %s', plugin_name, e)
75 except AttributeError, e:73 except AttributeError, e:
76 logger.error('%s not instanced: %s' % (plugin_name, e))74 logger.error('%s not instanced: %s', plugin_name, e)
77 except Exception, e:75 except Exception, e:
78 logger.error('%s not instanced: %s' % (plugin_name, e))76 logger.error('%s not instanced: %s', plugin_name, e)
79 print_exc (e)77 print_exc (e)
80 else:78 else:
81 logger.info ('%s instanced for %s' % (plugin_name,79 logger.info('%s instanced for %s', plugin_name,
82 (channel is not None) and channel or 'server'))80 (channel is not None) and channel or 'server')
8381
84 def load_server_plugins(self):82 def load_server_plugins(self):
85 params = {'nickname': self.nickname,83 params = {'nickname': self.nickname,
86 'encoding': self.encoding_server}84 'encoding': self.encoding_server}
8785
88 plugins= self.config.get('plugins', {})86 plugins= self.config.get('plugins', {})
89 logger.debug ("server plugins: %s" % plugins)87 logger.debug("server plugins: %s", plugins)
90 for plugin, config in plugins.items():88 for plugin, config in plugins.items():
91 self.load_plugin(plugin, config, params)89 self.load_plugin(plugin, config, params)
9290
@@ -96,7 +94,7 @@
96 self.encoding_server)}94 self.encoding_server)}
9795
98 plugins= self.config['channels'][channel].get ('plugins', {})96 plugins= self.config['channels'][channel].get ('plugins', {})
99 logger.debug ("channel plugins: %s" % plugins)97 logger.debug("channel plugins: %s", plugins)
100 for plugin, config in plugins.items ():98 for plugin, config in plugins.items ():
101 self.load_plugin (plugin, config, params, channel)99 self.load_plugin (plugin, config, params, channel)
102100
@@ -109,8 +107,8 @@
109 if "encoding" in v)107 if "encoding" in v)
110 self.password = self.config.get('password', None)108 self.password = self.config.get('password', None)
111 irc.IRCClient.connectionMade (self)109 irc.IRCClient.connectionMade (self)
112 logger.info("connected to %s:%d" %110 logger.info("connected to %s:%d",
113 (self.config['host'], self.config['port']))111 self.config['host'], self.config['port'])
114 self.load_server_plugins()112 self.load_server_plugins()
115 # configure the dispatcher113 # configure the dispatcher
116 self.dispatcher.init(self.config)114 self.dispatcher.init(self.config)
@@ -118,26 +116,26 @@
118116
119 def connectionLost(self, reason):117 def connectionLost(self, reason):
120 irc.IRCClient.connectionLost(self, reason)118 irc.IRCClient.connectionLost(self, reason)
121 logger.info ("disconnected from %s:%d" %119 logger.info("disconnected from %s:%d",
122 (self.config.get('host'), self.config.get('port')))120 self.config.get('host'), self.config.get('port'))
123 self.dispatcher.push(events.CONNECTION_LOST)121 self.dispatcher.push(events.CONNECTION_LOST)
124122
125 def signedOn(self):123 def signedOn(self):
126 logger.debug ("signed on %s:%d" %124 logger.debug("signed on %s:%d",
127 (self.config['host'], self.config['port']))125 self.config['host'], self.config['port'])
128 self.dispatcher.push(events.SIGNED_ON)126 self.dispatcher.push(events.SIGNED_ON)
129 for channel in self.config.get ('channels', []):127 for channel in self.config.get ('channels', []):
130 logger.debug ("joining %s on %s:%d" %128 logger.debug("joining %s on %s:%d",
131 (channel, self.config['host'], self.config['port']))129 channel, self.config['host'], self.config['port'])
132 self.join (channel)130 self.join (channel)
133131
134 def receivedMOTD(self, motd):132 def receivedMOTD(self, motd):
135 logger.debug ("motd from %s:%d" %133 logger.debug("motd from %s:%d",
136 (self.config['host'], self.config['port']))134 self.config['host'], self.config['port'])
137135
138 def joined(self, channel):136 def joined(self, channel):
139 """This will get called when the bot joins the channel."""137 """This will get called when the bot joins the channel."""
140 logger.info ("joined to %s" % channel)138 logger.info("joined to %s", channel)
141 self.load_channel_plugins (channel)139 self.load_channel_plugins (channel)
142 self.dispatcher.push(events.JOINED, channel)140 self.dispatcher.push(events.JOINED, channel)
143141
@@ -147,9 +145,8 @@
147 encoding = self.encoding_channels.get(channel, self.encoding_server)145 encoding = self.encoding_channels.get(channel, self.encoding_server)
148 msg = msg.decode(encoding)146 msg = msg.decode(encoding)
149147
150 logger.debug ("[%s] %s: %s" % (channel, user, msg))148 logger.debug("[%s] %s: %s", channel, user, msg)
151 user = user.split('!', 1)[0]149 user = user.split('!', 1)[0]
152 # self.logger.log("<%s> %s" % (user, msg))
153150
154 # Check to see if they're sending me a private message151 # Check to see if they're sending me a private message
155 if channel == self.nickname:152 if channel == self.nickname:
@@ -220,7 +217,7 @@
220 """217 """
221 If we get disconnected, reconnect to server.218 If we get disconnected, reconnect to server.
222 """219 """
223 logger.debug("We got disconnected because of %s" % str(reason))220 logger.debug("We got disconnected because of %s", reason)
224 connector.connect()221 connector.connect()
225222
226 def clientConnectionFailed(self, connector, reason):223 def clientConnectionFailed(self, connector, reason):
@@ -228,13 +225,12 @@
228 Stop main loop if connection failed, this should be changed to stop225 Stop main loop if connection failed, this should be changed to stop
229 only when no client remains connected226 only when no client remains connected
230 """227 """
231 logger.debug("Connection failed because of %s" % str(reason))228 logger.debug("Connection failed because of %s", reason)
232 # reactor.stop()229 # reactor.stop()
233230
234def main(to_use, plugin_loglvl):231def main(to_use, plugins_loglvl):
235 for server in to_use:232 for server in to_use:
236 # logger.debug (plugin_loglvl)233 server["log_config"] = plugins_loglvl
237 server["log_config"] = plugin_loglvl
238 bot = IRCBotFactory(server)234 bot = IRCBotFactory(server)
239 if server.get('ssl', False):235 if server.get('ssl', False):
240 reactor.connectSSL(server.get('host', '10.100.0.194'),236 reactor.connectSSL(server.get('host', '10.100.0.194'),
@@ -248,11 +244,14 @@
248244
249if __name__ == '__main__':245if __name__ == '__main__':
250 msg = u"""246 msg = u"""
251 ircbot.py [-t][-a][-o output_loglvl][-p plugin_loglvl] [server1, [...]]247 ircbot.py [-t][-a][-o output_loglvl][-p plugins_loglvl]
248 [-f fileloglvl][-n logfname] [server1, [...]]
252249
253 the servers are optional if -a is passed250 the servers are optional if -a is passed
254 the output_loglevel is the log level default for all the system251 the output_loglevel is the log level for the standard output
252 the file_loglevel is the log level for the output that goes to file
255 the pluginloglevel is a list of plugin_name:loglevel separated by commas253 the pluginloglevel is a list of plugin_name:loglevel separated by commas
254 the logfname is the filename to write the logs to
256"""255"""
257256
258 parser = optparse.OptionParser()257 parser = optparse.OptionParser()
@@ -265,6 +264,10 @@
265 help="sets the output log level.")264 help="sets the output log level.")
266 parser.add_option("-p", "--plugin-log-level", dest="plugloglvl",265 parser.add_option("-p", "--plugin-log-level", dest="plugloglvl",
267 help="sets the plugin log level. format is plugin:level,...")266 help="sets the plugin log level. format is plugin:level,...")
267 parser.add_option("-f", "--file-log-level", dest="fileloglvl",
268 help="sets the output log level.")
269 parser.add_option("-n", "--log-filename", dest="logfname",
270 help="specifies the name of the log file.")
268271
269 (options, args) = parser.parse_args()272 (options, args) = parser.parse_args()
270 test = bool(options.test)273 test = bool(options.test)
@@ -275,27 +278,28 @@
275 parser.print_help()278 parser.print_help()
276 exit()279 exit()
277280
278 # control the log level281 # control the output log level
279 if options.outloglvl is None:282 if options.outloglvl is None:
280 output_loglevel = "debug"283 output_loglevel = "info"
281 else:284 else:
282 output_loglevel = options.outloglvl.lower()285 output_loglevel = options.outloglvl.lower()
283 try:286 try:
284 logger.setLevel(LOG_LEVELS[output_loglevel])287 log_stdout_handler.setLevel(LOG_LEVELS[output_loglevel])
285 except KeyError:288 except KeyError:
286 print "The log level can be only:", LOG_LEVELS.keys()289 print "The log level can be only:", LOG_LEVELS.keys()
287 exit(1)290 exit(1)
288291
292 # control the plugins log level
289 plugins_loglvl = {}293 plugins_loglvl = {}
290 if options.plugloglvl is not None:294 if options.plugloglvl is not None:
291 try:295 try:
292 for pair in options.plugloglvl.split(","):296 for pair in options.plugloglvl.split(","):
293 plugin, loglvl = pair.split(":")297 plugin, loglvl = pair.split(":")
294 loglvl = loglvl.lower()298 loglvl = loglvl.lower()
295 logger.debug ("plugin %s, loglevel %s" % (plugin, loglvl))299 logger.debug("plugin %s, loglevel %s" % (plugin, loglvl))
296 if loglvl not in LOG_LEVELS:300 if loglvl not in LOG_LEVELS:
297 print "The log level can be only:", LOG_LEVELS.keys()301 print "The log level can be only:", LOG_LEVELS.keys()
298 exit()302 exit(1)
299 plugins_loglvl[plugin] = LOG_LEVELS[loglvl]303 plugins_loglvl[plugin] = LOG_LEVELS[loglvl]
300 except:304 except:
301 print "Remember that the plugin log level format is"305 print "Remember that the plugin log level format is"
@@ -310,6 +314,26 @@
310 print "See as an example the included here config.py.example"314 print "See as an example the included here config.py.example"
311 sys.exit()315 sys.exit()
312316
317 # handles the log file and its level
318 if options.logfname is None:
319 log_filename = "lalita.log"
320 else:
321 log_filename = options.logfname
322
323 if options.fileloglvl is None:
324 file_loglevel = logging.INFO
325 else:
326 try:
327 file_loglevel = LOG_LEVELS[options.fileloglvl.lower()]
328 except KeyError:
329 print "The log level can be only:", LOG_LEVELS.keys()
330 exit(1)
331
332 fh = logging.FileHandler(log_filename)
333 fh.setLevel(file_loglevel)
334 fh.setFormatter(formatter)
335 logger.addHandler(fh)
336
313 # get all servers or the indicated ones337 # get all servers or the indicated ones
314 servers = config.servers338 servers = config.servers
315 if all_servers:339 if all_servers:

Subscribers

People subscribed via source and target branches

to all changes: