Merge lp://staging/~laliputienses/lalita/fix-logs into lp://staging/lalita
- fix-logs
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Guillermo Gonzalez | Pending | ||
laliputienses | Pending | ||
Review via email: mp+12494@code.staging.launchpad.net |
Commit message
Description of the change
Facundo Batista (facundo) wrote : | # |
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.
>>> lp = logging.
>>> h1 = logging.
>>> h1.setLevel(
>>> l.addHandler(h1)
>>> h = logging.
>>> h.setLevel(
>>> l.addHandler(h)
>>> lp.debug('foo')
>>> lp.getEffective
30
>>> l.getEffectiveL
30
>>> l.setLevel(
>>> lp.setLevel(
>>> l.getEffectiveL
20
>>> lp.getEffective
10
>>> lp.debug('foo')
foo
>>> l.debug('foo')
>>> l.info('foo')
foo
>>> lp.error('foo')
foo
foo
>>> l.error('foo')
foo
foo
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
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 | 36 | "critical": logging.CRITICAL, | 36 | "critical": logging.CRITICAL, |
6 | 37 | } | 37 | } |
7 | 38 | 38 | ||
13 | 39 | handler = logging.StreamHandler(sys.stdout) | 39 | log_stdout_handler = logging.StreamHandler(sys.stdout) |
14 | 40 | formatter = logging.Formatter( | 40 | formatter = logging.Formatter("%(asctime)s %(name)s:%(lineno)-4d " |
15 | 41 | "%(asctime)s %(name)s:%(lineno)-4d %(levelname)-8s %(message)s", | 41 | "%(levelname)-8s %(message)s", |
16 | 42 | '%H:%M:%S') | 42 | '%Y-%m-%d %H:%M:%S') |
17 | 43 | handler.setFormatter(formatter) | 43 | log_stdout_handler.setFormatter(formatter) |
18 | 44 | logger = logging.getLogger('ircbot') | 44 | logger = logging.getLogger('ircbot') |
21 | 45 | logger.addHandler(handler) | 45 | logger.addHandler(log_stdout_handler) |
22 | 46 | 46 | logger.setLevel(logging.DEBUG) | |
23 | 47 | 47 | ||
24 | 48 | class IrcBot (irc.IRCClient): | 48 | class IrcBot (irc.IRCClient): |
25 | 49 | """A IRC bot.""" | 49 | """A IRC bot.""" |
26 | 50 | def __init__ (self, *more): | 50 | def __init__ (self, *more): |
27 | 51 | self.dispatcher = dispatcher.Dispatcher(self) | 51 | self.dispatcher = dispatcher.Dispatcher(self) |
28 | 52 | self._plugins = {} | 52 | self._plugins = {} |
31 | 53 | logger.debug ("we're in(ited)!") | 53 | logger.info("We're in(ited)!") |
30 | 54 | # logger.debug (more) | ||
32 | 55 | 54 | ||
33 | 56 | def load_plugin (self, plugin_name, config, params, channel=None): | 55 | def load_plugin (self, plugin_name, config, params, channel=None): |
34 | 57 | # logger.debug (config) | ||
35 | 58 | if "plugins_dir" in self.config: | 56 | if "plugins_dir" in self.config: |
36 | 59 | path = self.config["plugins_dir"] | 57 | path = self.config["plugins_dir"] |
37 | 60 | else: | 58 | else: |
38 | @@ -71,22 +69,22 @@ | |||
39 | 71 | self.dispatcher.new_plugin(instance, channel) | 69 | self.dispatcher.new_plugin(instance, channel) |
40 | 72 | instance.init(config) | 70 | instance.init(config) |
41 | 73 | except ImportError, e: | 71 | except ImportError, e: |
43 | 74 | logger.error('%s not instanced: %s' % (plugin_name, e)) | 72 | logger.error('%s not instanced: %s', plugin_name, e) |
44 | 75 | except AttributeError, e: | 73 | except AttributeError, e: |
46 | 76 | logger.error('%s not instanced: %s' % (plugin_name, e)) | 74 | logger.error('%s not instanced: %s', plugin_name, e) |
47 | 77 | except Exception, e: | 75 | except Exception, e: |
49 | 78 | logger.error('%s not instanced: %s' % (plugin_name, e)) | 76 | logger.error('%s not instanced: %s', plugin_name, e) |
50 | 79 | print_exc (e) | 77 | print_exc (e) |
51 | 80 | else: | 78 | else: |
54 | 81 | logger.info ('%s instanced for %s' % (plugin_name, | 79 | logger.info('%s instanced for %s', plugin_name, |
55 | 82 | (channel is not None) and channel or 'server')) | 80 | (channel is not None) and channel or 'server') |
56 | 83 | 81 | ||
57 | 84 | def load_server_plugins(self): | 82 | def load_server_plugins(self): |
58 | 85 | params = {'nickname': self.nickname, | 83 | params = {'nickname': self.nickname, |
59 | 86 | 'encoding': self.encoding_server} | 84 | 'encoding': self.encoding_server} |
60 | 87 | 85 | ||
61 | 88 | plugins= self.config.get('plugins', {}) | 86 | plugins= self.config.get('plugins', {}) |
63 | 89 | logger.debug ("server plugins: %s" % plugins) | 87 | logger.debug("server plugins: %s", plugins) |
64 | 90 | for plugin, config in plugins.items(): | 88 | for plugin, config in plugins.items(): |
65 | 91 | self.load_plugin(plugin, config, params) | 89 | self.load_plugin(plugin, config, params) |
66 | 92 | 90 | ||
67 | @@ -96,7 +94,7 @@ | |||
68 | 96 | self.encoding_server)} | 94 | self.encoding_server)} |
69 | 97 | 95 | ||
70 | 98 | plugins= self.config['channels'][channel].get ('plugins', {}) | 96 | plugins= self.config['channels'][channel].get ('plugins', {}) |
72 | 99 | logger.debug ("channel plugins: %s" % plugins) | 97 | logger.debug("channel plugins: %s", plugins) |
73 | 100 | for plugin, config in plugins.items (): | 98 | for plugin, config in plugins.items (): |
74 | 101 | self.load_plugin (plugin, config, params, channel) | 99 | self.load_plugin (plugin, config, params, channel) |
75 | 102 | 100 | ||
76 | @@ -109,8 +107,8 @@ | |||
77 | 109 | if "encoding" in v) | 107 | if "encoding" in v) |
78 | 110 | self.password = self.config.get('password', None) | 108 | self.password = self.config.get('password', None) |
79 | 111 | irc.IRCClient.connectionMade (self) | 109 | irc.IRCClient.connectionMade (self) |
82 | 112 | logger.info("connected to %s:%d" % | 110 | logger.info("connected to %s:%d", |
83 | 113 | (self.config['host'], self.config['port'])) | 111 | self.config['host'], self.config['port']) |
84 | 114 | self.load_server_plugins() | 112 | self.load_server_plugins() |
85 | 115 | # configure the dispatcher | 113 | # configure the dispatcher |
86 | 116 | self.dispatcher.init(self.config) | 114 | self.dispatcher.init(self.config) |
87 | @@ -118,26 +116,26 @@ | |||
88 | 118 | 116 | ||
89 | 119 | def connectionLost(self, reason): | 117 | def connectionLost(self, reason): |
90 | 120 | irc.IRCClient.connectionLost(self, reason) | 118 | irc.IRCClient.connectionLost(self, reason) |
93 | 121 | logger.info ("disconnected from %s:%d" % | 119 | logger.info("disconnected from %s:%d", |
94 | 122 | (self.config.get('host'), self.config.get('port'))) | 120 | self.config.get('host'), self.config.get('port')) |
95 | 123 | self.dispatcher.push(events.CONNECTION_LOST) | 121 | self.dispatcher.push(events.CONNECTION_LOST) |
96 | 124 | 122 | ||
97 | 125 | def signedOn(self): | 123 | def signedOn(self): |
100 | 126 | logger.debug ("signed on %s:%d" % | 124 | logger.debug("signed on %s:%d", |
101 | 127 | (self.config['host'], self.config['port'])) | 125 | self.config['host'], self.config['port']) |
102 | 128 | self.dispatcher.push(events.SIGNED_ON) | 126 | self.dispatcher.push(events.SIGNED_ON) |
103 | 129 | for channel in self.config.get ('channels', []): | 127 | for channel in self.config.get ('channels', []): |
106 | 130 | logger.debug ("joining %s on %s:%d" % | 128 | logger.debug("joining %s on %s:%d", |
107 | 131 | (channel, self.config['host'], self.config['port'])) | 129 | channel, self.config['host'], self.config['port']) |
108 | 132 | self.join (channel) | 130 | self.join (channel) |
109 | 133 | 131 | ||
110 | 134 | def receivedMOTD(self, motd): | 132 | def receivedMOTD(self, motd): |
113 | 135 | logger.debug ("motd from %s:%d" % | 133 | logger.debug("motd from %s:%d", |
114 | 136 | (self.config['host'], self.config['port'])) | 134 | self.config['host'], self.config['port']) |
115 | 137 | 135 | ||
116 | 138 | def joined(self, channel): | 136 | def joined(self, channel): |
117 | 139 | """This will get called when the bot joins the channel.""" | 137 | """This will get called when the bot joins the channel.""" |
119 | 140 | logger.info ("joined to %s" % channel) | 138 | logger.info("joined to %s", channel) |
120 | 141 | self.load_channel_plugins (channel) | 139 | self.load_channel_plugins (channel) |
121 | 142 | self.dispatcher.push(events.JOINED, channel) | 140 | self.dispatcher.push(events.JOINED, channel) |
122 | 143 | 141 | ||
123 | @@ -147,9 +145,8 @@ | |||
124 | 147 | encoding = self.encoding_channels.get(channel, self.encoding_server) | 145 | encoding = self.encoding_channels.get(channel, self.encoding_server) |
125 | 148 | msg = msg.decode(encoding) | 146 | msg = msg.decode(encoding) |
126 | 149 | 147 | ||
128 | 150 | logger.debug ("[%s] %s: %s" % (channel, user, msg)) | 148 | logger.debug("[%s] %s: %s", channel, user, msg) |
129 | 151 | user = user.split('!', 1)[0] | 149 | user = user.split('!', 1)[0] |
130 | 152 | # self.logger.log("<%s> %s" % (user, msg)) | ||
131 | 153 | 150 | ||
132 | 154 | # Check to see if they're sending me a private message | 151 | # Check to see if they're sending me a private message |
133 | 155 | if channel == self.nickname: | 152 | if channel == self.nickname: |
134 | @@ -220,7 +217,7 @@ | |||
135 | 220 | """ | 217 | """ |
136 | 221 | If we get disconnected, reconnect to server. | 218 | If we get disconnected, reconnect to server. |
137 | 222 | """ | 219 | """ |
139 | 223 | logger.debug("We got disconnected because of %s" % str(reason)) | 220 | logger.debug("We got disconnected because of %s", reason) |
140 | 224 | connector.connect() | 221 | connector.connect() |
141 | 225 | 222 | ||
142 | 226 | def clientConnectionFailed(self, connector, reason): | 223 | def clientConnectionFailed(self, connector, reason): |
143 | @@ -228,13 +225,12 @@ | |||
144 | 228 | Stop main loop if connection failed, this should be changed to stop | 225 | Stop main loop if connection failed, this should be changed to stop |
145 | 229 | only when no client remains connected | 226 | only when no client remains connected |
146 | 230 | """ | 227 | """ |
148 | 231 | logger.debug("Connection failed because of %s" % str(reason)) | 228 | logger.debug("Connection failed because of %s", reason) |
149 | 232 | # reactor.stop() | 229 | # reactor.stop() |
150 | 233 | 230 | ||
152 | 234 | def main(to_use, plugin_loglvl): | 231 | def main(to_use, plugins_loglvl): |
153 | 235 | for server in to_use: | 232 | for server in to_use: |
156 | 236 | # logger.debug (plugin_loglvl) | 233 | server["log_config"] = plugins_loglvl |
155 | 237 | server["log_config"] = plugin_loglvl | ||
157 | 238 | bot = IRCBotFactory(server) | 234 | bot = IRCBotFactory(server) |
158 | 239 | if server.get('ssl', False): | 235 | if server.get('ssl', False): |
159 | 240 | reactor.connectSSL(server.get('host', '10.100.0.194'), | 236 | reactor.connectSSL(server.get('host', '10.100.0.194'), |
160 | @@ -248,11 +244,14 @@ | |||
161 | 248 | 244 | ||
162 | 249 | if __name__ == '__main__': | 245 | if __name__ == '__main__': |
163 | 250 | msg = u""" | 246 | msg = u""" |
165 | 251 | ircbot.py [-t][-a][-o output_loglvl][-p plugin_loglvl] [server1, [...]] | 247 | ircbot.py [-t][-a][-o output_loglvl][-p plugins_loglvl] |
166 | 248 | [-f fileloglvl][-n logfname] [server1, [...]] | ||
167 | 252 | 249 | ||
168 | 253 | the servers are optional if -a is passed | 250 | the servers are optional if -a is passed |
170 | 254 | the output_loglevel is the log level default for all the system | 251 | the output_loglevel is the log level for the standard output |
171 | 252 | the file_loglevel is the log level for the output that goes to file | ||
172 | 255 | the pluginloglevel is a list of plugin_name:loglevel separated by commas | 253 | the pluginloglevel is a list of plugin_name:loglevel separated by commas |
173 | 254 | the logfname is the filename to write the logs to | ||
174 | 256 | """ | 255 | """ |
175 | 257 | 256 | ||
176 | 258 | parser = optparse.OptionParser() | 257 | parser = optparse.OptionParser() |
177 | @@ -265,6 +264,10 @@ | |||
178 | 265 | help="sets the output log level.") | 264 | help="sets the output log level.") |
179 | 266 | parser.add_option("-p", "--plugin-log-level", dest="plugloglvl", | 265 | parser.add_option("-p", "--plugin-log-level", dest="plugloglvl", |
180 | 267 | help="sets the plugin log level. format is plugin:level,...") | 266 | help="sets the plugin log level. format is plugin:level,...") |
181 | 267 | parser.add_option("-f", "--file-log-level", dest="fileloglvl", | ||
182 | 268 | help="sets the output log level.") | ||
183 | 269 | parser.add_option("-n", "--log-filename", dest="logfname", | ||
184 | 270 | help="specifies the name of the log file.") | ||
185 | 268 | 271 | ||
186 | 269 | (options, args) = parser.parse_args() | 272 | (options, args) = parser.parse_args() |
187 | 270 | test = bool(options.test) | 273 | test = bool(options.test) |
188 | @@ -275,27 +278,28 @@ | |||
189 | 275 | parser.print_help() | 278 | parser.print_help() |
190 | 276 | exit() | 279 | exit() |
191 | 277 | 280 | ||
193 | 278 | # control the log level | 281 | # control the output log level |
194 | 279 | if options.outloglvl is None: | 282 | if options.outloglvl is None: |
196 | 280 | output_loglevel = "debug" | 283 | output_loglevel = "info" |
197 | 281 | else: | 284 | else: |
198 | 282 | output_loglevel = options.outloglvl.lower() | 285 | output_loglevel = options.outloglvl.lower() |
199 | 283 | try: | 286 | try: |
201 | 284 | logger.setLevel(LOG_LEVELS[output_loglevel]) | 287 | log_stdout_handler.setLevel(LOG_LEVELS[output_loglevel]) |
202 | 285 | except KeyError: | 288 | except KeyError: |
203 | 286 | print "The log level can be only:", LOG_LEVELS.keys() | 289 | print "The log level can be only:", LOG_LEVELS.keys() |
204 | 287 | exit(1) | 290 | exit(1) |
205 | 288 | 291 | ||
206 | 292 | # control the plugins log level | ||
207 | 289 | plugins_loglvl = {} | 293 | plugins_loglvl = {} |
208 | 290 | if options.plugloglvl is not None: | 294 | if options.plugloglvl is not None: |
209 | 291 | try: | 295 | try: |
210 | 292 | for pair in options.plugloglvl.split(","): | 296 | for pair in options.plugloglvl.split(","): |
211 | 293 | plugin, loglvl = pair.split(":") | 297 | plugin, loglvl = pair.split(":") |
212 | 294 | loglvl = loglvl.lower() | 298 | loglvl = loglvl.lower() |
214 | 295 | logger.debug ("plugin %s, loglevel %s" % (plugin, loglvl)) | 299 | logger.debug("plugin %s, loglevel %s" % (plugin, loglvl)) |
215 | 296 | if loglvl not in LOG_LEVELS: | 300 | if loglvl not in LOG_LEVELS: |
216 | 297 | print "The log level can be only:", LOG_LEVELS.keys() | 301 | print "The log level can be only:", LOG_LEVELS.keys() |
218 | 298 | exit() | 302 | exit(1) |
219 | 299 | plugins_loglvl[plugin] = LOG_LEVELS[loglvl] | 303 | plugins_loglvl[plugin] = LOG_LEVELS[loglvl] |
220 | 300 | except: | 304 | except: |
221 | 301 | print "Remember that the plugin log level format is" | 305 | print "Remember that the plugin log level format is" |
222 | @@ -310,6 +314,26 @@ | |||
223 | 310 | print "See as an example the included here config.py.example" | 314 | print "See as an example the included here config.py.example" |
224 | 311 | sys.exit() | 315 | sys.exit() |
225 | 312 | 316 | ||
226 | 317 | # handles the log file and its level | ||
227 | 318 | if options.logfname is None: | ||
228 | 319 | log_filename = "lalita.log" | ||
229 | 320 | else: | ||
230 | 321 | log_filename = options.logfname | ||
231 | 322 | |||
232 | 323 | if options.fileloglvl is None: | ||
233 | 324 | file_loglevel = logging.INFO | ||
234 | 325 | else: | ||
235 | 326 | try: | ||
236 | 327 | file_loglevel = LOG_LEVELS[options.fileloglvl.lower()] | ||
237 | 328 | except KeyError: | ||
238 | 329 | print "The log level can be only:", LOG_LEVELS.keys() | ||
239 | 330 | exit(1) | ||
240 | 331 | |||
241 | 332 | fh = logging.FileHandler(log_filename) | ||
242 | 333 | fh.setLevel(file_loglevel) | ||
243 | 334 | fh.setFormatter(formatter) | ||
244 | 335 | logger.addHandler(fh) | ||
245 | 336 | |||
246 | 313 | # get all servers or the indicated ones | 337 | # get all servers or the indicated ones |
247 | 314 | servers = config.servers | 338 | servers = config.servers |
248 | 315 | if all_servers: | 339 | if all_servers: |
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??