Web Images Videos Maps News Shopping Gmail more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Customizing notification method for internal server errors
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  14 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Jesse Young  
View profile  
 More options Oct 15 2008, 4:58 pm
From: Jesse Young <adu...@gmail.com>
Date: Wed, 15 Oct 2008 13:58:35 -0700 (PDT)
Local: Wed, Oct 15 2008 4:58 pm
Subject: Customizing notification method for internal server errors
The built-in behavior for
django.core.handlers.base.handle_uncaught_exception calls mail_admins
for each internal server error.

So if a very high-traffic view has an internal server error, duplicate
emails will be sent at a very high rate. This isn't usually
desirable...

We worked around this by changing mail_admins directly in our copy of
Django to store the last time an email was sent on the filesystem and
avoid sending multiple emails in too short of a time interval. But it
seems like there should be a better way to customize this without
having to modify Django.

I suppose one could define a mail_admins replacement in our app and
assign it to django.core.mail.mail_admins. But that's rather hacky...

Also, BaseHandler says that handle_uncaught_exception can be
overridden, but its derived classes ModPythonHandler and WSGIHandler
are referenced directly in Django, so I don't really see how to
subclass it without changing the Django code.

I was thinking it would be useful to add a setting like
EXCEPTION_NOTIFIER = 'path.to.custom.notifier' , where the default
would look something like this:

def mail_exception_to_admins(request, exc_info):
        from django.core.mail import mail_admins
        subject = 'Error (%s IP): %s' %
((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and
'internal' or 'EXTERNAL'), request.path)
        try:
            request_repr = repr(request)
        except:
            request_repr = "Request repr() unavailable"
        message = "%s\n\n%s" % (self._get_traceback(exc_info),
request_repr)
        mail_admins(subject, message, fail_silently=True)

Thoughts?


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jeremy Dunck  
View profile  
 More options Oct 15 2008, 5:18 pm
From: "Jeremy Dunck" <jdu...@gmail.com>
Date: Wed, 15 Oct 2008 16:18:53 -0500
Local: Wed, Oct 15 2008 5:18 pm
Subject: Re: Customizing notification method for internal server errors
On Wed, Oct 15, 2008 at 3:58 PM, Jesse Young <adu...@gmail.com> wrote:

...

I like the idea, but not the addition of yet another setting.  Maybe
an on_exception signal could be added which can do its own thing and
return False if the default action shouldn't be taken?

    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jesse Young  
View profile  
 More options Oct 15 2008, 7:26 pm
From: Jesse Young <adu...@gmail.com>
Date: Wed, 15 Oct 2008 16:26:35 -0700 (PDT)
Local: Wed, Oct 15 2008 7:26 pm
Subject: Re: Customizing notification method for internal server errors
I see there is a got_request_exception signal already... so one could
effectively do the same thing by adding a signal handler and making
settings.ADMINS the empty list so that mail_admins effectively becomes
a no-op.

Even so, it looks like mail_admins will open a SMTP connection to send
an email message even if the message has no recipients. So it seems
wrong to force every non-debug exception to go through that code path.
(If your servers are melting down, opening hundreds of SMTP
connections probably won't help the situation.)

-Jesse

On Oct 15, 2:18 pm, "Jeremy Dunck" <jdu...@gmail.com> wrote:


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jeremy Dunck  
View profile  
 More options Oct 15 2008, 8:59 pm
From: "Jeremy Dunck" <jdu...@gmail.com>
Date: Wed, 15 Oct 2008 19:59:14 -0500
Local: Wed, Oct 15 2008 8:59 pm
Subject: Re: Customizing notification method for internal server errors

On Wed, Oct 15, 2008 at 6:26 PM, Jesse Young <adu...@gmail.com> wrote:

> I see there is a got_request_exception signal already... so one could
> effectively do the same thing by adding a signal handler and making
> settings.ADMINS the empty list so that mail_admins effectively becomes
> a no-op.

> Even so, it looks like mail_admins will open a SMTP connection to send
> an email message even if the message has no recipients. So it seems
> wrong to force every non-debug exception to go through that code path.
> (If your servers are melting down, opening hundreds of SMTP
> connections probably won't help the situation.)

In handlers.base.get_response, theres:
"
receivers = dispatcher.send(signal=signals.got_request_exception,
request=request)
"

Return value cases:
In [2]: l = [] #no receivers
In [3]: l2 = [None] #only old receivers
In [4]: l3 = [False] #new receiver asking not to default handle
In [5]: l4 = [None, False] #old and new receiver
In [6]: l5 = [True, False] #mix of new receivers, one asking not to
default handle

The odd edge case is where a different signal handlers return both
True and False (where existing code would return None).  What to do
there is a design choice; I'd vote for False wins.

So I'd add:
"
if receivers:
    default_handler = not bool([ret_value for ret_value in receivers
if ret_value == False])
else:
    default_handler = True

if default_handler:
   ...existing handling code here...
callback, param_dict = resolver.resolve500()
return callback(request, **param_dict)
"


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Malcolm Tredinnick  
View profile  
 More options Oct 15 2008, 9:15 pm
From: Malcolm Tredinnick <malc...@pointy-stick.com>
Date: Thu, 16 Oct 2008 12:15:08 +1100
Local: Wed, Oct 15 2008 9:15 pm
Subject: Re: Customizing notification method for internal server errors

On Wed, 2008-10-15 at 13:58 -0700, Jesse Young wrote:
> The built-in behavior for
> django.core.handlers.base.handle_uncaught_exception calls mail_admins
> for each internal server error.

> So if a very high-traffic view has an internal server error, duplicate
> emails will be sent at a very high rate. This isn't usually
> desirable...

So the reason handle_uncaught_exception is in its own method is, as
noted in the docstring for that method, so that you can have exactly
this type of control. I have one client, for example, who want to use
Python's logging module instead of sending email and no doubt lots of
other customisations are possible.

The idea is that you create your own subclass of which
django/core/handlers/* class you want (wsgi or modpython, typically) and
override the handle_uncaught_exception method. After all, you specify
the handler class to use when setting things up to talk to the
webserver, so it's just as easy to use your own subclass as one of
Django's built in versions.

This is done via subclassing rather than a setting to avoid settings
proliferation for something where there's no real common case of
customisations and so the ultimate configuration is provided: you write
Python code to do whatever you want. It's also meant to impose a slight
barrier to entry in the sense that you have to be able to write Python
code in order to customise this, which is reasonable for something as
core-functionality oriented as handling uncaught exceptions (and no
problems for people on django-dev, obviously).

Regards,
Malcolm


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jesse Young  
View profile  
 More options Oct 15 2008, 9:59 pm
From: Jesse Young <adu...@gmail.com>
Date: Wed, 15 Oct 2008 18:59:30 -0700 (PDT)
Local: Wed, Oct 15 2008 9:59 pm
Subject: Re: Customizing notification method for internal server errors
Hi Malcolm,

Thanks for explaining the rationale behind this. It'd certainly be
possible to do what we want by overriding handle_uncaught_exception in
a ModPythonHandler subclass.

This method has a higher barrier to entry than I'd like, though. For
one, this kind of customization requires updating the apache
configuration file to point to the new handler. It's annoying to have
to update Apache config files in synchronization with the Python app
code.

Also, I suspect that a large number of Django developers use
"manage.py runserver"  (which is hardcoded to use WSGIHandler) for
development and testing and use ModPythonHandler on the release
servers. To minimize unexpected bugs in the release environment that
never show up in the test environment, it's best not to introduce
additional differences between these environments. A custom
implementation of handle_uncaught_exception would be hard for a
developer using "manage.py runserver" to test.

My hunch is that even though there isn't a common way that users would
want to customize uncaught exceptions, it's probably common that users
would want to customize it in some way or another. So subclassing the
handler seems like a rather high barrier to entry.

-Jesse

On Oct 15, 6:15 pm, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
oggie rob  
View profile  
 More options Oct 16 2008, 12:35 am
From: oggie rob <oz.robhar...@gmail.com>
Date: Wed, 15 Oct 2008 21:35:18 -0700 (PDT)
Local: Thurs, Oct 16 2008 12:35 am
Subject: Re: Customizing notification method for internal server errors
Did you try subclassing list (& overriding __iter__) for the ADMINS
object?

 -rob

On Oct 15, 1:58 pm, Jesse Young <adu...@gmail.com> wrote:


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jesse Young  
View profile  
 More options Oct 16 2008, 1:18 am
From: Jesse Young <adu...@gmail.com>
Date: Wed, 15 Oct 2008 22:18:19 -0700 (PDT)
Local: Thurs, Oct 16 2008 1:18 am
Subject: Re: Customizing notification method for internal server errors
Is your suggestion that, since mail_admins happens to be the only
place in Django that uses settings.ADMINS, I could do something like:

class AdminsObject(list):
   def __iter__(self):
     // do some custom notification
     // manually write the friendly 500 error page to the output
stream somehow
     raise Exception // can't raise StopIteration here or mail_admins
will connect to the SMTP server
ADMINS = AdminsObject()

That would be pretty hilarious. Not particularly straightforward or
maintainable though.

-Jesse

On Oct 15, 9:35 pm, oggie rob <oz.robhar...@gmail.com> wrote:


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ivan Sagalaev  
View profile  
 More options Oct 16 2008, 12:02 pm
From: Ivan Sagalaev <man...@softwaremaniacs.org>
Date: Thu, 16 Oct 2008 20:02:22 +0400
Local: Thurs, Oct 16 2008 12:02 pm
Subject: Re: Customizing notification method for internal server errors

Jesse Young wrote:
> The built-in behavior for
> django.core.handlers.base.handle_uncaught_exception calls mail_admins
> for each internal server error.

> So if a very high-traffic view has an internal server error, duplicate
> emails will be sent at a very high rate. This isn't usually
> desirable...

We're working it around by not having settings.ADMINS set in production
environment. Instead we log unhandled exceptions by listening to
`signals.got_request_exception`. I don't even consider it as a
workaround actually but as a normal solution :-)

    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
oggie rob  
View profile  
 More options Oct 16 2008, 12:35 pm
From: oggie rob <oz.robhar...@gmail.com>
Date: Thu, 16 Oct 2008 09:35:51 -0700 (PDT)
Local: Thurs, Oct 16 2008 12:35 pm
Subject: Re: Customizing notification method for internal server errors
On Oct 15, 10:18 pm, Jesse Young <adu...@gmail.com> wrote:

> Is your suggestion that, since mail_admins happens to be the only
> place in Django that uses settings.ADMINS, I could do something like:

> class AdminsObject(list):
>    def __iter__(self):
>      // do some custom notification
>      // manually write the friendly 500 error page to the output
> stream somehow
>      raise Exception // can't raise StopIteration here or mail_admins
> will connect to the SMTP server
> ADMINS = AdminsObject()

I was hoping it wouldn't be quite that ugly! And just had an empty
list.iter in mind. Something like:

class AdminsObject(list):
   def __iter__(self):
       if ok_to_send(): # enough time since last mail or whatever
           return super(AdminsObject, self).__iter__()
       return [].__iter__()

ADMINS = AdminsObject([
  ('Your Name', 'your_em...@domain.com'),
])

I think your exception would propagate up to the
handle_uncaught_exception and the user would not see the "friendly
error message".

However, after seeing your comment regarding the exception I looked at
EmailMessage and was surprised to see that it attempts to send even
with an empty ADMINS list. It should return if not self.to and not
self.bcc, I think.

> That would be pretty hilarious. Not particularly straightforward or
> maintainable though.

Yes, the got_request_exception signal seems like a better solution as
it gives you more context.

 -rob


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Malcolm Tredinnick  
View profile  
 More options Oct 16 2008, 5:41 pm
From: Malcolm Tredinnick <malc...@pointy-stick.com>
Date: Fri, 17 Oct 2008 08:41:27 +1100
Local: Thurs, Oct 16 2008 5:41 pm
Subject: Re: Customizing notification method for internal server errors

On Wed, 2008-10-15 at 18:59 -0700, Jesse Young wrote:
> Hi Malcolm,

> Thanks for explaining the rationale behind this. It'd certainly be
> possible to do what we want by overriding handle_uncaught_exception in
> a ModPythonHandler subclass.

> This method has a higher barrier to entry than I'd like, though. For
> one, this kind of customization requires updating the apache
> configuration file to point to the new handler. It's annoying to have
> to update Apache config files in synchronization with the Python app
> code.

Well, not really. You have to set the Apache configuration once to point
to the right thing. Just like you do now.

> Also, I suspect that a large number of Django developers use
> "manage.py runserver"  (which is hardcoded to use WSGIHandler) for
> development and testing and use ModPythonHandler on the release
> servers. To minimize unexpected bugs in the release environment that
> never show up in the test environment, it's best not to introduce
> additional differences between these environments. A custom
> implementation of handle_uncaught_exception would be hard for a
> developer using "manage.py runserver" to test.

Patches welcome to fix that if you see it as a real problem.

> My hunch is that even though there isn't a common way that users would
> want to customize uncaught exceptions, it's probably common that users
> would want to customize it in some way or another. So subclassing the
> handler seems like a rather high barrier to entry.

No it's not. Since there's no common way to customize, sub-classing is
the perfect way to do it, since people can then do whatever they want.
How is asking somebody to write a subclass in Python a high barrier to
entry? We're assuming knowledge of the language, but that's all.

I don't see any of your objections here a real issues except the need
for being able to simulate things in the development server.

Regards,
Malcolm


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jesse Young  
View profile  
 More options Oct 16 2008, 6:15 pm
From: Jesse Young <adu...@gmail.com>
Date: Thu, 16 Oct 2008 15:15:16 -0700 (PDT)
Local: Thurs, Oct 16 2008 6:15 pm
Subject: Re: Customizing notification method for internal server errors

> No it's not. Since there's no common way to customize, sub-classing is
> the perfect way to do it, since people can then do whatever they want.
> How is asking somebody to write a subclass in Python a high barrier to
> entry? We're assuming knowledge of the language, but that's all.

Well, I'm not saying that writing a subclass in Python is a high
barrier to entry. I'm saying that the handler in particular is hard to
subclass. And I agree that subclassing it would be 'the perfect way',
if only it didn't require a configuration change (yes, only once, but
that is once more than required by basically any other change to a
Django app) and didn't introduce differences between the test and
release environments.

I mean, really, the notification method for errors should have nothing
to do with the type of web server interface you have (WSGI /
mod_python). It's just an artifact of the way the code is currently
factored.

> Patches welcome to fix that if you see it as a real problem.

I suppose the easiest way is to patch mail_admins to not attempt to
send email if ADMINS is empty.

On Oct 16, 2:41 pm, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Malcolm Tredinnick  
View profile  
 More options Oct 16 2008, 6:26 pm
From: Malcolm Tredinnick <malc...@pointy-stick.com>
Date: Fri, 17 Oct 2008 09:26:18 +1100
Local: Thurs, Oct 16 2008 6:26 pm
Subject: Re: Customizing notification method for internal server errors

On Thu, 2008-10-16 at 15:15 -0700, Jesse Young wrote:
> > No it's not. Since there's no common way to customize, sub-classing is
> > the perfect way to do it, since people can then do whatever they want.
> > How is asking somebody to write a subclass in Python a high barrier to
> > entry? We're assuming knowledge of the language, but that's all.

> Well, I'm not saying that writing a subclass in Python is a high
> barrier to entry. I'm saying that the handler in particular is hard to
> subclass. And I agree that subclassing it would be 'the perfect way',
> if only it didn't require a configuration change (yes, only once, but
> that is once more than required by basically any other change to a
> Django app)

No, this isn't correct. You already have to specify which handler to
run. You still have to do that exactly once in each case.

> and didn't introduce differences between the test and
> release environments.

There's already differences between the test and release environments if
you mean runserver versus anything running with a real webserver.
Expecting complete parity there is a false goal and you absolutely must
do real production-preparedness tests against the real webserver you're
going to use in production. That's hardly a surprise. A  patch to allow
something like --with-handler='my.handler.class' (making up an API on
the spot; that needs to be thought about) would be a good idea for
completeness, though, you're right.

> I mean, really, the notification method for errors should have nothing
> to do with the type of web server interface you have (WSGI /
> mod_python).

The method is called handle_uncaught_exception, not
notify_about_uncaught_exception. Right now it only happens to do
notification, but because it's extensible it could do stuff that is
handler dependent.

Malcolm


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jesse Young  
View profile  
 More options Oct 16 2008, 6:50 pm
From: Jesse Young <adu...@gmail.com>
Date: Thu, 16 Oct 2008 15:50:44 -0700 (PDT)
Local: Thurs, Oct 16 2008 6:50 pm
Subject: Re: Customizing notification method for internal server errors
The --with-handler idea for manage.py runserver sounds reasonable to
me.

I just wanted to clarify a couple of points.

> No, this isn't correct. You already have to specify which handler to
> run. You still have to do that exactly once in each case.

I meant that it requires one extra configuration change if you've
already deployed your app using the default handler, and later want to
override handle_uncaught_exception.

> There's already differences between the test and release environments if
> you mean runserver versus anything running with a real webserver.
> Expecting complete parity there is a false goal

Sure, but that doesn't mean I shouldn't try to avoid making the test/
release environments more different than they already are.

-Jesse


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google