[Twisted-Python] [cpushare@cpushare.com: CPUShare Exception]

Hello,
I wrote the below code in my server:
from twisted.python import log
# local from cpushare.mail import send_exception
class cpushare_logging_observer_class(object): def __init__(self, factory): self.factory = factory def start(self): if self.factory.production: log.addObserver(self.emit) def stop(self): if self.factory.production: log.removeObserver(self.emit) def emit(self, eventDict): edm = eventDict['message'] if not edm: if eventDict['isError'] and eventDict.has_key('failure'): send_exception(eventDict['failure'])
to receive exceptions by email like the below if (send_exception sends me an sms for the very first exception too). I do a very similar thing in nevow, but in nevow I handle it through the nevow layer, not through twisted.
Now to me it seems that the below exception isn't really interesting to me, any client could generate it by injecting garbage in the ssl connection.
Does anybody has suggestions on the best way to filter out all OpenSSL.SSL.Error exceptions before calling send_exception in the above code? Thanks!
(twisted is great ;)
----- Forwarded message from cpushare@cpushare.com -----
Date: Thu, 7 Jul 2005 14:14:08 +0200 (CEST) From: cpushare@cpushare.com To: andrea.kernel@tiscali.it Subject: CPUShare Exception X-Mailbox-Line: From nobody Thu Jul 7 14:14:07 2005
Traceback (most recent call last): File "/home/build/bin/i686/python-20050707/lib/python2.4/site-packages/twisted/python/log.py", line 43, in callWithContext
File "/home/build/bin/i686/python-20050707/lib/python2.4/site-packages/twisted/python/context.py", line 59, in callWithContext
File "/home/build/bin/i686/python-20050707/lib/python2.4/site-packages/twisted/python/context.py", line 37, in callWithContext
File "/home/build/bin/i686/python-20050707/lib/python2.4/site-packages/twisted/internet/pollreactor.py", line 160, in _doReadOrWrite
--- <exception caught here> --- File "/home/build/bin/i686/python-20050707/lib/python2.4/site-packages/twisted/internet/tcp.py", line 111, in doRead
File "/home/build/bin/i686/python-20050707/lib/python2.4/site-packages/twisted/internet/tcp.py", line 339, in doRead
OpenSSL.SSL.Error: [('SSL routines', 'SSL3_READ_BYTES', 'ssl handshake failure')]
----- End forwarded message -----

On Thu, 7 Jul 2005 14:22:56 +0200, Andrea Arcangeli andrea@cpushare.com wrote:
Does anybody has suggestions on the best way to filter out all OpenSSL.SSL.Error exceptions before calling send_exception in the above code? Thanks!
It seems like you might want to filter more than just OpenSSL.SSL.Error ;). eventDict['failure'] is a twisted.python.failure.Failure object; see the API docs or the code for that class for details on introspecting them (they're designed to be easier to introspect than Python tuples).
For your particular request:
if not eventDict['failure'].check(OpenSSL.SSL.Error): send_exception(...)

On Thu, Jul 07, 2005 at 08:48:59AM -0400, glyph@divmod.com wrote:
It seems like you might want to filter more than just OpenSSL.SSL.Error ;).
very likely ;), but I guess I can wait until some harmless annoyance trigger like in this case.
The number of emails the server sends me has a maximum of 10, to avoid getting the same exception too many times (and the max number of sms is 1). So even something goes wrong and I'm on vacation I don't risk to fill the inbox ;)
eventDict['failure'] is a twisted.python.failure.Failure object; see the API docs or the code for that class for details on introspecting them (they're designed to be easier to introspect than Python tuples).
For your particular request:
if not eventDict['failure'].check(OpenSSL.SSL.Error): send_exception(...)
cool, I updated it like this.
from OpenSSL import SSL from twisted.python import log
# local from cpushare.mail import send_exception
class cpushare_logging_observer_class(object): def __init__(self, factory): self.factory = factory def start(self): if self.factory.production: log.addObserver(self.emit) def stop(self): if self.factory.production: log.removeObserver(self.emit) def emit(self, eventDict): edm = eventDict['message'] if not edm: if eventDict['isError'] and eventDict.has_key('failure'): failure = eventDict['failure'] if not failure.check(SSL.Error): send_exception(failure)
Thanks.

On Thu, 7 Jul 2005 16:23:13 +0200, Andrea Arcangeli andrea@cpushare.com wrote:
On Thu, Jul 07, 2005 at 08:48:59AM -0400, glyph@divmod.com wrote:
It seems like you might want to filter more than just OpenSSL.SSL.Error ;).
very likely ;), but I guess I can wait until some harmless annoyance trigger like in this case.
The number of emails the server sends me has a maximum of 10, to avoid getting the same exception too many times (and the max number of sms is 1). So even something goes wrong and I'm on vacation I don't risk to fill the inbox ;)
Rather than a simple counter, why not hash tracebacks so they are not sent more than once? For example:
from twisted.python.failure import Failure import sha
def a(): b() def b(): c() def c(): raise RuntimeError()
def fail(): try: a() except: return Failure()
def fhash(f): return sha.new( f.getTraceback(elideFrameworkCode=1, detail='brief')).digest()
f1 = fail() f2 = fail()
print fhash(f1) == fhash(f2)

On Thu, 7 Jul 2005 10:42:12 -0400, glyph@divmod.com wrote:
On Thu, 7 Jul 2005 16:23:13 +0200, Andrea Arcangeli andrea@cpushare.com wrote:
On Thu, Jul 07, 2005 at 08:48:59AM -0400, glyph@divmod.com wrote:
It seems like you might want to filter more than just OpenSSL.SSL.Error ;).
very likely ;), but I guess I can wait until some harmless annoyance trigger like in this case.
The number of emails the server sends me has a maximum of 10, to avoid getting the same exception too many times (and the max number of sms is 1). So even something goes wrong and I'm on vacation I don't risk to fill the inbox ;)
Rather than a simple counter, why not hash tracebacks so they are not sent more than once? For example:
This tends to work poorly for most tracebacks. As soon as you have one that contains an object with a default repr, the ID section makes each hash different.
When I did this, I settled on hashing just the qual of the exception class and the brief string (failure.getErrorMessage()) version of it. This has a similar problem, but seems to work ok in practice.
Jp

On Thu, Jul 07, 2005 at 11:06:51AM -0400, Jp Calderone wrote:
When I did this, I settled on hashing just the qual of the exception class
I guess the qual would be failure.value.__class__.__module__ + failure.value.__class__.__name__ or did I misunderstood?
Isn't it simpler to hash on failure.value.__class__ instead of the qual?
and the brief string (failure.getErrorMessage()) version of it. This has a
That's neat too, the only disavantage compared to glyph's approach is that the stack trace could be different but the exception the same, stuff like AttributeError is quite common. gliph's example code wouldn't risk to lose different stack traces.
The counter is good enough for now but I'll probably stack it on top of glyph's appraoch in the future.
Thanks for the interesting hints!
participants (3)
-
Andrea Arcangeli
-
glyph@divmod.com
-
Jp Calderone