def test_request_with_items_key(self): """ An exception report can be generated for requests with 'items' in request GET, POST, FILES, or COOKIES QueryDicts. """ value = '<td>items</td><td class="code"><pre>'Oops'</pre></td>' # GET request = self.rf.get('/test_view/?items=Oops') reporter = ExceptionReporter(request, None, None, None) html = reporter.get_traceback_html() self.assertInHTML(value, html) # POST request = self.rf.post('/test_view/', data={'items': 'Oops'}) reporter = ExceptionReporter(request, None, None, None) html = reporter.get_traceback_html() self.assertInHTML(value, html) # FILES fp = StringIO('filecontent') request = self.rf.post('/test_view/', data={'name': 'filename', 'items': fp}) reporter = ExceptionReporter(request, None, None, None) html = reporter.get_traceback_html() self.assertInHTML( '<td>items</td><td class="code"><pre><InMemoryUploadedFile: ' 'items (application/octet-stream)></pre></td>', html ) # COOKES rf = RequestFactory() rf.cookies['items'] = 'Oops' request = rf.get('/test_view/') reporter = ExceptionReporter(request, None, None, None) html = reporter.get_traceback_html() self.assertInHTML('<td>items</td><td class="code"><pre>'Oops'</pre></td>', html)
def emit(self, record): try: request = record.request subject = '%s (%s IP): %s' % ( record.levelname, ('internal' if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS else 'EXTERNAL'), record.getMessage() ) filter = get_exception_reporter_filter(request) request_repr = '\n{}'.format(force_text(filter.get_request_repr(request))) except Exception: subject = '%s: %s' % ( record.levelname, record.getMessage() ) request = None request_repr = "unavailable" subject = self.format_subject(subject) if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) message = "%s\n\nRequest repr(): %s" % (self.format(record), request_repr) reporter = ExceptionReporter(request, is_email=True, *exc_info) html_message = reporter.get_traceback_html() if self.include_html else None self.send_mail(subject, message, fail_silently=True, html_message=html_message)
def emit(self, record): try: request = record.request subject = '%s (%s IP): %s' % ( record.levelname, (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), record.msg ) filter = get_exception_reporter_filter(request) request_repr = filter.get_request_repr(request) except: subject = '%s: %s' % ( record.levelname, record.getMessage() ) request = None request_repr = "Request repr() unavailable." if record.exc_info: exc_info = record.exc_info stack_trace = '\n'.join(traceback.format_exception(*record.exc_info)) else: exc_info = (None, record.getMessage(), None) stack_trace = 'No stack trace available' message = "%s\n\n%s" % (stack_trace, request_repr) reporter = ExceptionReporter(request, is_email=True, *exc_info) html_message = self.include_html and reporter.get_traceback_html() or None mail.mail_admins(subject, message, fail_silently=True, html_message=html_message)
def emit(self, record): try: request = record.request except Exception: request = None subject = '%s: %s' % ( record.levelname, record.getMessage() ) subject = subject.replace('\n', '\\n').replace('\r', '\\r') # Since we add a nicely formatted traceback on our own, create a copy # of the log record without the exception data. no_exc_record = copy(record) no_exc_record.exc_info = None no_exc_record.exc_text = None if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) if settings.HACKATHON_DEV_EMAILS: reporter = ExceptionReporter(request, is_email=True, *exc_info) message = "%s\n\n%s" % (self.format(no_exc_record), reporter.get_traceback_text()) html_message = reporter.get_traceback_html() msg = EmailMultiAlternatives(subject, message, 'server@' + settings.HACKATHON_DOMAIN, settings.HACKATHON_DEV_EMAILS) msg.attach_alternative(html_message, 'text/html') msg.send(fail_silently=True)
def emit(self, record): import traceback from django.views.debug import ExceptionReporter try: request = record.request subject = '%s (%s): %s' % ( record.levelname, request.META.get('REMOTE_ADDR'), record.msg ) request_repr = repr(request) except Exception: subject = '%s: %s' % ( record.levelname, record.msg ) request = None request_repr = "Request repr() unavailable" if record.exc_info: exc_info = record.exc_info stack_trace = '\n'.join(traceback.format_exception(*record.exc_info)) else: exc_info = (None, record.msg, None) stack_trace = 'No stack trace available' message = "%s\n\n%s" % (stack_trace, request_repr) reporter = ExceptionReporter(request, is_email=True, *exc_info) html_message = self.include_html and reporter.get_traceback_html() or None # mail_admins(subject, message, fail_silently=True, mail_admins(subject, message, html_message=html_message)
def log_exception_data(self, exception, exc_type, exc_value, tb, queue_name='default'): key = self._make_key(exc_type, str(exception)) exc_log_entry = None if key not in self._exceptions: from django.views.debug import ExceptionReporter # first arg to ExceptionReporter.__init__() is usually a request object reporter = ExceptionReporter(None, exc_type, exc_value, tb) html = reporter.get_traceback_html() exc_log_entry = self.create( exception_type=exc_type.__name__, exception_module=getattr(exc_type, '__module__', "None"), queue_name=queue_name, message=str(exception), html=html, ) self._exceptions.update({ key: exc_log_entry, }) else: exc_log_entry = self._exceptions[key] exc_log_entry.increment() exc_log_entry.save() return exc_log_entry
def test_reporting_of_nested_exceptions(self): request = self.rf.get('/test_view/') try: try: raise AttributeError(mark_safe('<p>Top level</p>')) except AttributeError as explicit: try: raise ValueError(mark_safe('<p>Second exception</p>')) from explicit except ValueError: raise IndexError(mark_safe('<p>Final exception</p>')) except Exception: # Custom exception handler, just pass it into ExceptionReporter exc_type, exc_value, tb = sys.exc_info() explicit_exc = 'The above exception ({0}) was the direct cause of the following exception:' implicit_exc = 'During handling of the above exception ({0}), another exception occurred:' reporter = ExceptionReporter(request, exc_type, exc_value, tb) html = reporter.get_traceback_html() # Both messages are twice on page -- one rendered as html, # one as plain text (for pastebin) self.assertEqual(2, html.count(explicit_exc.format('<p>Top level</p>'))) self.assertEqual(2, html.count(implicit_exc.format('<p>Second exception</p>'))) self.assertEqual(10, html.count('<p>Final exception</p>')) text = reporter.get_traceback_text() self.assertIn(explicit_exc.format('<p>Top level</p>'), text) self.assertIn(implicit_exc.format('<p>Second exception</p>'), text) self.assertEqual(3, text.count('<p>Final exception</p>'))
def emit(self, record): try: request = record.request subject = "%s (%s IP): %s" % ( record.levelname, ("internal" if request.META.get("REMOTE_ADDR") in settings.INTERNAL_IPS else "EXTERNAL"), record.getMessage(), ) filter = get_exception_reporter_filter(request) request_repr = filter.get_request_repr(request) except Exception: subject = "%s: %s" % (record.levelname, record.getMessage()) request = None request_repr = "Request repr() unavailable." subject = self.format_subject(subject) if record.exc_info: exc_info = record.exc_info stack_trace = "\n".join(traceback.format_exception(*record.exc_info)) else: exc_info = (None, record.getMessage(), None) stack_trace = "No stack trace available" message = "%s\n\n%s" % (stack_trace, request_repr) reporter = ExceptionReporter(request, is_email=True, *exc_info) html_message = reporter.get_traceback_html() if self.include_html else None mail.mail_admins(subject, message, fail_silently=True, html_message=html_message, connection=self.connection())
def test_ignore_traceback_evaluation_exceptions(self): """ Don't trip over exceptions generated by crafted objects when evaluating them while cleansing (#24455). """ class BrokenEvaluation(Exception): pass def broken_setup(): raise BrokenEvaluation request = self.rf.get("/test_view/") broken_lazy = SimpleLazyObject(broken_setup) try: bool(broken_lazy) except BrokenEvaluation: exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(request, exc_type, exc_value, tb) try: html = reporter.get_traceback_html() except BrokenEvaluation: self.fail("Broken evaluation in traceback is not caught.") self.assertIn("BrokenEvaluation", html, "Evaluation exception reason not mentioned in traceback")
def emit(self, record): try: request = record.request subject = '%s (%s IP): %s' % ( record.levelname, ('internal' if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS else 'EXTERNAL'), record.getMessage() ) filter = get_exception_reporter_filter(request) request_repr = '\n{0}'.format(force_text(filter.get_request_repr(request))) except Exception: subject = '%s: %s' % ( record.levelname, record.getMessage() ) request = None request_repr = "unavailable" subject = self.format_subject(subject) if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) message = "%s\n\nRequest repr(): %s" % (self.format(record), request_repr) reporter = ExceptionReporter(request, is_email=True, *exc_info) html_message = reporter.get_traceback_html() if self.include_html else None conn = self.connection() conn.send_email('*****@*****.**', subject, html_message, ['*****@*****.**'], format='html')
def emit(self, record): try: request = record.request subject = '%s (%s IP: %s): %s' % (record.levelname, (request.user if request.user else 'No user'), ('internal' if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS else 'EXTERNAL'), record.getMessage()) except Exception: subject = '%s: %s' % (record.levelname, record.getMessage()) request = None subject = self.format_subject(subject) # Since we add a nicely formatted traceback on our own, create a copy # of the log record without the exception data. no_exc_record = copy(record) no_exc_record.exc_info = None no_exc_record.exc_text = None if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) reporter = ExceptionReporter(request, is_email=True, *exc_info) message = "%s\n\n%s" % (self.format(no_exc_record), reporter.get_traceback_text()) html_message = reporter.get_traceback_html() if self.include_html else None self.send_mail(subject, message, fail_silently=True, html_message=html_message)
def better_uncaught_exception_emails(self, request, resolver, exc_info): """ Processing for any otherwise uncaught exceptions (those that will generate HTTP 500 responses). Can be overridden by subclasses who want customised 500 handling. Be *very* careful when overriding this because the error could be caused by anything, so assuming something like the database is always available would be an error. """ from django.conf import settings from django.core.mail import EmailMultiAlternatives from django.views.debug import ExceptionReporter # Only send details emails in the production environment. if settings.DEBUG == False: reporter = ExceptionReporter(request, *exc_info) # Prepare the email headers for sending. from_ = u"Exception Reporter <*****@*****.**>" to_ = from_ subject = "Detailed stack trace." message = EmailMultiAlternatives(subject, reporter.get_traceback_text(), from_, [to_]) message.attach_alternative(reporter.get_traceback_html(), 'text/html') message.send() # Make sure to then just call the base handler. return self.original_handle_uncaught_exception(request, resolver, exc_info)
def test_exception_fetching_user(self): """ The error page can be rendered if the current user can't be retrieved (such as when the database is unavailable). """ class ExceptionUser: def __str__(self): raise Exception() request = self.rf.get('/test_view/') request.user = ExceptionUser() try: raise ValueError('Oops') except ValueError: exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(request, exc_type, exc_value, tb) html = reporter.get_traceback_html() self.assertInHTML('<h1>ValueError at /test_view/</h1>', html) self.assertIn('<pre class="exception_value">Oops</pre>', html) self.assertIn('<h3 id="user-info">USER</h3>', html) self.assertIn('<p>[unable to retrieve the current user]</p>', html) text = reporter.get_traceback_text() self.assertIn('USER: [unable to retrieve the current user]', text)
def get_response(self, request): exc_type, exc_value, traceback = sys.exc_info() reporter = ExceptionReporter( request, exc_type, exc_value, traceback.tb_next ) html = reporter.get_traceback_html() http_response = http.HttpResponseServerError() if settings.DEBUG: http_response = http.HttpResponseServerError( html, content_type='text/html; charset=utf-8' ) elif getattr(settings, 'EMAIL_CRASHES', False): # Send Email Crash Report subject = 'django-firestone crash report' message = EmailMessage( subject=settings.EMAIL_SUBJECT_PREFIX + subject, body=html, from_email=settings.SERVER_EMAIL, to=[admin[1] for admin in settings.ADMINS] ) message.content_subtype = 'html' message.send(fail_silently=True) return http_response
def emit(self, record): try: request = record.request subject = "%s (%s IP): %s" % ( record.levelname, ("internal" if request.META.get("REMOTE_ADDR") in settings.INTERNAL_IPS else "EXTERNAL"), record.getMessage(), ) except Exception: subject = "%s: %s" % (record.levelname, record.getMessage()) request = None if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) reporter = ExceptionReporter(request, is_email=False, *exc_info) html_message = reporter.get_traceback_html() print "BAD HOST", record DisallowedHost.objects.create( http_host=request.META.get("HTTP_HOST") if request else None, remote_addr=request.META.get("REMOTE_ADDR") if request else None, http_x_forwarded_for=request.META.get("HTTP_X_FORWARDED_FOR") if request else None, request_uri=request.META.get("REQUEST_URI") if request else None, request_method=request.META.get("REQUEST_METHOD") if request else None, query_string=request.META.get("QUERY_STRING") if request else None, path_info=request.META.get("PATH_INFO") if request else None, http_user_agent=request.META.get("HTTP_USER_AGENT") if request else None, html_report=html_message, )
def __call__(self, req): if req.method!="POST": return JsonResponse(ajax_error(405, 'Accepts only POST request')) try: ajax_method=req.POST['ajax_method'] if not hasattr(self, ajax_method): return JsonResponse(ajax_error(405,"Unknown ajax method '%s'" % ajax_method)) method = getattr(self, ajax_method) post=dict(req.POST) del post['ajax_method'] kwargs = {} for name in post: value = post[name] if len(value)==1: value=value[0] kwargs[str(name)] = value return JsonResponse(method(req, **kwargs)) except Exception, e: try: if dblogger: exc_info = sys.exc_info() report = ExceptionReporter(req, *exc_info) dblogger.exception(e, report.get_traceback_html()) except: pass return JsonResponse(ajax_error(405,"Server Exception: %s:%s" % (e.__class__, e)))
def progress_error_reporter(): """ Use this wrapper around your progress loops like this: >>> with progress_error_reporter(): >>> for item in with_progress(collection, name='my long process that can throw errors') >>> # heavy processing actions with sometimes an exception :-) When an exception gets raised from inside the body of your for-loop, it will be caught and the progress bar will show a link to the exception. The exception is rendered by the standard exception reporter, containing the full stack trace with variables. """ try: yield except Exception as exc_outer: try: if hasattr(tls, 'djprogress__stack') and tls.djprogress__stack: from djprogress.models import Progress progress_id = tls.djprogress__stack.pop() progress = Progress.objects.get(pk=progress_id) exc_type, exc_value, exc_traceback = sys.exc_info() er = ExceptionReporter(None, exc_type, exc_value, exc_traceback) html = er.get_traceback_html() progress.exception = html progress.save() except Exception as exc_inner: # When the error reporter fails for whatever reason, catch and log the # exception here so that our regular code flow isn't interrupted. The # 'raise' statement will take care of the rest. logger.exception(exc_inner) raise exc_outer
def emit(self, record): """Send a log error over email. Args: The logging.LogRecord object. See http://docs.python.org/library/logging.html#logging.LogRecord """ from django.conf import settings if settings.DEBUG and record.levelno < logging.WARNING: # NOTE: You don't want to try this on dev_appserver. Trust me. return signature = self.__GetRecordSignature(record) try: from google.appengine.api import memcache if not memcache.add(signature, True, time=self.log_interval): return except Exception: pass formatted_record = self.format(record) request = None try: if sys.version_info < (2, 5): # A nasty workaround required because Python 2.4's logging # module doesn't support passing in extra context. # For this handler, the only extra data we need is the # request, and that's in the top stack frame. request = record.exc_info[2].tb_frame.f_locals['request'] else: request = record.request except Exception: pass try: for jid, params in self.recipients.items(): if record.levelno < params['level']: continue sender = 'errors@%s.appspotmail.com' % app_id subject = '(%s) error reported for %s, version %s' % (record.levelname, app_id, app_ver) message = formatted_record exc_info = record.exc_info if record.exc_info else (None, record.msg, None) reporter = ExceptionReporter(request, is_email=True, *exc_info) html_message = reporter.get_traceback_html() or None mail = EmailMultiAlternatives('%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject), message, sender, [jid]) if html_message: mail.attach_alternative(html_message, 'text/html') mail.send() except OverQuotaError: pass except Exception: self.handleError(record)
def test_auditing(self): def foo(): return bar() def bar(): return baz() def baz(): return auditing.FakeTraceback() tb = foo() er = ExceptionReporter(None, type, None, tb) # if this fails we've messed up the fake traceback html = er.get_traceback_html()
def show_server_error(request): """ 500 error handler to show Django default 500 template with nice error information and traceback. Useful in testing, if you can't set DEBUG=True. Templates: `500.html` Context: sys.exc_info() results """ exc_type, exc_value, exc_traceback = sys.exc_info() error = ExceptionReporter(request, exc_type, exc_value, exc_traceback) return http.HttpResponseServerError(error.get_traceback_html())
def send_manually_exception_email(request, e): exc_info = sys.exc_info() reporter = ExceptionReporter(request, is_email=True, *exc_info) subject = e.message.replace('\n', '\\n').replace('\r', '\\r')[:989] message = "%s\n\n%s" % ( '\n'.join(traceback.format_exception(*exc_info)), reporter.filter.get_request_repr(request) ) mail.mail_admins( subject, message, fail_silently=True, html_message=reporter.get_traceback_html() )
def test_message_only(self): reporter = ExceptionReporter(None, None, "I'm a little teapot", None) html = reporter.get_traceback_html() self.assertIn('<h1>Report</h1>', html) self.assertIn('<pre class="exception_value">I'm a little teapot</pre>', html) self.assertNotIn('<th>Request Method:</th>', html) self.assertNotIn('<th>Request URL:</th>', html) self.assertNotIn('<th>Exception Type:</th>', html) self.assertNotIn('<th>Exception Value:</th>', html) self.assertNotIn('<h2>Traceback ', html) self.assertIn('<h2>Request information</h2>', html) self.assertIn('<p>Request data not supplied</p>', html)
def _send_email(self, subject, message, exc_info=None, attachments=None): """ Helper method mimicking :class:`AdminEmailHandler` - if exception is available renders traceback as HTML message content """ if exc_info is not None: reporter = ExceptionReporter(None, is_email=True, *exc_info) html_message = reporter.get_traceback_html() attachments.append(("debug.html", html_message, "text/html")) self.logger.info("Sending message to admins: %s - %s", subject, message) self._mail_admins_with_attachment(subject, message, attachments=attachments)
def test_unprintable_values_handling(self): "Unprintable values should not make the output generation choke." try: class OomOutput(object): def __repr__(self): raise MemoryError('OOM') oomvalue = OomOutput() # NOQA raise ValueError() except Exception: exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(None, exc_type, exc_value, tb) html = reporter.get_traceback_html() self.assertIn('<td class="code"><pre>Error in formatting', html)
def test_unfrozen_importlib(self): """ importlib is not a frozen app, but its loader thinks it's frozen which results in an ImportError on Python 3. Refs #21443. """ try: request = self.rf.get('/test_view/') importlib.import_module('abc.def.invalid.name') except Exception: exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(request, exc_type, exc_value, tb) html = reporter.get_traceback_html() self.assertIn('<h1>ImportError at /test_view/</h1>', html)
def uncaught_exception_email(self, request, resolver, exc_info): from django.conf import settings from django.views.debug import ExceptionReporter if settings.DEBUG is False: reporter = ExceptionReporter(request, *exc_info) SendmailQueue()._add( subject=getattr(self, 'uncaught_exception_subject', 'Django exception stack trace'), body=reporter.get_traceback_text(), html_body=reporter.get_traceback_html(), to=self.developers_emails )._flush() return self.original_handle_uncaught_exception(request, resolver, exc_info)
def test_request_and_message(self): "A message can be provided in addition to a request" request = self.rf.get('/test_view/') reporter = ExceptionReporter(request, None, "I'm a little teapot", None) html = reporter.get_traceback_html() self.assertIn('<h1>Report at /test_view/</h1>', html) self.assertIn('<pre class="exception_value">I'm a little teapot</pre>', html) self.assertIn('<th>Request Method:</th>', html) self.assertIn('<th>Request URL:</th>', html) self.assertNotIn('<th>Exception Type:</th>', html) self.assertNotIn('<th>Exception Value:</th>', html) self.assertNotIn('<h2>Traceback ', html) self.assertIn('<h2>Request information</h2>', html) self.assertNotIn('<p>Request data not supplied</p>', html)
def test_non_utf8_values_handling(self): "Non-UTF-8 exceptions/values should not make the output generation choke." try: class NonUtf8Output(Exception): def __repr__(self): return b'EXC\xe9EXC' somevar = b'VAL\xe9VAL' # NOQA raise NonUtf8Output() except Exception: exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(None, exc_type, exc_value, tb) html = reporter.get_traceback_html() self.assertIn('VAL\\xe9VAL', html) self.assertIn('EXC\\xe9EXC', html)
def test_no_exception(self): "An exception report can be generated for just a request" request = self.rf.get('/test_view/') reporter = ExceptionReporter(request, None, None, None) html = reporter.get_traceback_html() self.assertIn('<h1>Report at /test_view/</h1>', html) self.assertIn('<pre class="exception_value">No exception message supplied</pre>', html) self.assertIn('<th>Request Method:</th>', html) self.assertIn('<th>Request URL:</th>', html) self.assertNotIn('<th>Exception Type:</th>', html) self.assertNotIn('<th>Exception Value:</th>', html) self.assertNotIn('<h2>Traceback ', html) self.assertIn('<h2>Request information</h2>', html) self.assertNotIn('<p>Request data not supplied</p>', html)
def test_encoding_error(self): """ A UnicodeError displays a portion of the problematic string. HTML in safe strings is escaped. """ try: mark_safe('abcdefghijkl<p>mnὀp</p>qrstuwxyz').encode('ascii') except Exception: exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(None, exc_type, exc_value, tb) html = reporter.get_traceback_html() self.assertIn('<h2>Unicode error hint</h2>', html) self.assertIn('The string that could not be encoded/decoded was: ', html) self.assertIn('<strong><p>mnὀp</p></strong>', html)
def test_request_with_items_key(self): """ An exception report can be generated for requests with 'items' in request GET, POST, FILES, or COOKIES QueryDicts. """ if six.PY3: value = '<td>items</td><td class="code"><pre>'Oops'</pre></td>' else: value = '<td>items</td><td class="code"><pre>u'Oops'</pre></td>' # GET request = self.rf.get('/test_view/?items=Oops') reporter = ExceptionReporter(request, None, None, None) html = reporter.get_traceback_html() self.assertInHTML(value, html) # POST request = self.rf.post('/test_view/', data={'items': 'Oops'}) reporter = ExceptionReporter(request, None, None, None) html = reporter.get_traceback_html() self.assertInHTML(value, html) # FILES fp = six.StringIO('filecontent') request = self.rf.post('/test_view/', data={'name': 'filename', 'items': fp}) reporter = ExceptionReporter(request, None, None, None) html = reporter.get_traceback_html() self.assertInHTML( '<td>items</td><td class="code"><pre><InMemoryUploadedFile: ' 'items (application/octet-stream)></pre></td>', html ) # COOKES rf = RequestFactory() rf.cookies['items'] = 'Oops' request = rf.get('/test_view/') reporter = ExceptionReporter(request, None, None, None) html = reporter.get_traceback_html() self.assertInHTML('<td>items</td><td class="code"><pre>'Oops'</pre></td>', html)
def test_no_exception(self): "An exception report can be generated for just a request" request = self.rf.get('/test_view/') reporter = ExceptionReporter(request, None, None, None) html = reporter.get_traceback_html() self.assertIn('<h1>Report at /test_view/</h1>', html) self.assertIn( '<pre class="exception_value">No exception supplied</pre>', html) self.assertIn('<th>Request Method:</th>', html) self.assertIn('<th>Request URL:</th>', html) self.assertNotIn('<th>Exception Type:</th>', html) self.assertNotIn('<th>Exception Value:</th>', html) self.assertNotIn('<h2>Traceback ', html) self.assertIn('<h2>Request information</h2>', html) self.assertNotIn('<p>Request data not supplied</p>', html)
def mail_error(request, exc_info): from django.core.mail import mail_admins # When DEBUG is False, send an error message to the admins. from django.views.debug import ExceptionReporter reporter = ExceptionReporter(request, *exc_info) html = reporter.get_traceback_html() subject = '%s had a problem at %s' % (request.user, request.path) try: request_repr = repr(request) except: request_repr = "Request repr() unavailable" message = "%s\n\n%s" % (get_traceback(exc_info), request_repr) mail_admins(subject, message, fail_silently=False, html_message=html)
def error_handler(self, error, request, meth): """ A decorator that generates our preferred output formats for two common cases: -- APIGeneralError (you can raise this or a descendent in API code) -- FormValidationError (generated by 'validate' decorator) """ if isinstance(error, FormValidationError): """ Optional 'beatified' form error handling. Comment this if clause out if you want the normal output. """ name, description = form_errors(error.form) return JSONErrorResponse(name, description) if isinstance(error, APIUserError) or isinstance( error, APIRequestError): return JSONErrorResponse(error.api_error_name, error.api_error_description, error.api_error_status, error.api_error_domain) # If we got here, the we have a serious server error. # # log this whether or not we send email exc_type, exc_value, tb = sys.exc_info() rep = ExceptionReporter(request, exc_type, exc_value, tb.tb_next) # add logging here traceback.print_exc() traceback.print_tb(tb) from django.conf import settings if getattr(settings, 'PISTON_EMAIL_ERRORS', False): subject = "iCoupon crash report" html = rep.get_traceback_html() message = EmailMessage(settings.EMAIL_SUBJECT_PREFIX + subject, html, settings.SERVER_EMAIL, [admin[1] for admin in settings.ADMINS]) message.content_subtype = 'html' message.send(fail_silenetly=True) if isinstance(error, APIInternalError): return JSONErrorResponse(error.api_error_name, error.api_error_description, error.api_error_status, error.api_error_domain) return JSONErrorResponse("Unknown Exception", "traceback logged", 500, "EXC")
def test_too_large_values_handling(self): "Large values should not create a large HTML." large = 256 * 1024 repr_of_str_adds = len(repr('')) try: class LargeOutput: def __repr__(self): return repr('A' * large) largevalue = LargeOutput() # NOQA raise ValueError() except Exception: exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(None, exc_type, exc_value, tb) html = reporter.get_traceback_html() self.assertEqual(len(html) // 1024 // 128, 0) # still fit in 128Kb self.assertIn('<trimmed %d bytes string>' % (large + repr_of_str_adds,), html)
def server_error(request): exc_info = sys.exc_info() reporter = ExceptionReporter(request, *exc_info) html = reporter.get_traceback_html() msg = EmailMessage( 'server_error@%s' % request.path, html, settings.SERVER_EMAIL, ['%s <%s>' % (name, address) for name, address in settings.ADMINS]) msg.content_subtype = "html" msg.send(fail_silently=True) template_name = '500.html' t = loader.get_template(template_name) #logging.getLogger('server_error').error(request) return HttpResponseServerError(t.render(Context({})))
def test_request_and_message(self): "A message can be provided in addition to a request" request = self.rf.get('/test_view/') reporter = ExceptionReporter(request, None, "I'm a little teapot", None) html = reporter.get_traceback_html() self.assertIn('<h1>Report at /test_view/</h1>', html) self.assertIn( '<pre class="exception_value">I'm a little teapot</pre>', html) self.assertIn('<th>Request Method:</th>', html) self.assertIn('<th>Request URL:</th>', html) self.assertNotIn('<th>Exception Type:</th>', html) self.assertNotIn('<th>Exception Value:</th>', html) self.assertNotIn('<h2>Traceback ', html) self.assertIn('<h2>Request information</h2>', html) self.assertNotIn('<p>Request data not supplied</p>', html)
def notify_exception(request, e): """ Emulates Django's email Exception reporter. Will produce and send traceback and request info. http://stackoverflow.com/a/29878519/1330003 """ exc_info = sys.exc_info() reporter = ExceptionReporter(request, is_email=True, *exc_info) subject = e.message.replace('\n', '\\n').replace('\r', '\\r')[:989] message = "%s\n\n%s" % ( '\n'.join(traceback.format_exception(*exc_info)), reporter.filter.get_request_repr(request) ) mail.mail_admins( subject, message, fail_silently=True, html_message=reporter.get_traceback_html() )
def test_no_request(self): "An exception report can be generated without request" try: raise ValueError("Can't find my keys") except ValueError: exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(None, exc_type, exc_value, tb) html = reporter.get_traceback_html() self.assertIn('<h1>ValueError</h1>', html) self.assertIn('<pre class="exception_value">Can't find my keys</pre>', html) self.assertNotIn('<th>Request Method:</th>', html) self.assertNotIn('<th>Request URL:</th>', html) self.assertIn('<th>Exception Type:</th>', html) self.assertIn('<th>Exception Value:</th>', html) self.assertIn('<h2>Traceback ', html) self.assertIn('<h2>Request information</h2>', html) self.assertIn('<p>Request data not supplied</p>', html)
def handle_uncaught_exception(self, request, resolver, exc_info): """ Processing for any otherwise uncaught exceptions (those that will generate HTTP 500 responses). Can be overridden by subclasses who want customised 500 handling. Be *very* careful when overriding this because the error could be caused by anything, so assuming something like the database is always available would be an error. """ from django.conf import settings from django.core.mail import mail_admins if settings.DEBUG_PROPAGATE_EXCEPTIONS: raise if settings.DEBUG: from django.views import debug return debug.technical_500_response(request, *exc_info) # When DEBUG is False, send an error message to the admins. from django.views.debug import ExceptionReporter reporter = ExceptionReporter(request, *exc_info) html = reporter.get_traceback_html() 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) extra_emails = self._get_extra_emails(exc_info) mail_admins(subject, message, fail_silently=True, html_message=html, extra_emails=extra_emails) # If Http500 handler is not installed, re-raise last exception if resolver.urlconf_module is None: raise exc_info[1], None, exc_info[2] # Return an HttpResponse that displays a friendly error message. callback, param_dict = resolver.resolve500() return callback(request, **param_dict)
def emit(self, record): """ Construct body of message here """ try: request = record.request subject = '%s (%s IP): %s' % (record.levelname, ( 'internal' if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS else 'EXTERNAL'), record.getMessage()) except Exception: subject = '%s: %s' % (record.levelname, record.getMessage()) request = None subject = self.format_subject(subject) # Since we add a nicely formatted traceback on our own, create a copy # of the log record without the exception data. no_exc_record = copy(record) no_exc_record.exc_info = None no_exc_record.exc_text = None if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) session = '' post = '' get = '' meta = '' if request is not None: try: session = str(request.session.__dict__) post = str(request.POST.__dict__) get = str(request.GET.__dict__) meta = str(request.META.__dict__) except: # try to log exception in logging xa xa pass reporter = ExceptionReporter(request, is_email=True, *exc_info) message = u"%s\n\n%s" % (self.format(no_exc_record), \ "SESSION: \n" + session + "POST: \n" + post + "GET: \n" + get + "META: \n" + meta) html_message = reporter.get_traceback_html() # html is being added message = u"{}\n{}".format(message, html_message) self.send_mail(subject, message)
def test_request_and_exception(self): "A simple exception report can be generated" try: request = self.rf.get('/test_view/') raise ValueError("Can't find my keys") except ValueError: exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(request, exc_type, exc_value, tb) html = reporter.get_traceback_html() self.assertIn('<h1>ValueError at /test_view/</h1>', html) self.assertIn('<pre class="exception_value">Can't find my keys</pre>', html) self.assertIn('<th>Request Method:</th>', html) self.assertIn('<th>Request URL:</th>', html) self.assertIn('<th>Exception Type:</th>', html) self.assertIn('<th>Exception Value:</th>', html) self.assertIn('<h2>Traceback ', html) self.assertIn('<h2>Request information</h2>', html) self.assertNotIn('<p>Request data not supplied</p>', html)
def wrapper(*args, **kwargs): try: func(*args, **kwargs) except: if settings.SEND_EMAIL: excType, excValue, traceback = sys.exc_info() reporter = ExceptionReporter(FAKE_HTTP_REQUEST, excType, excValue, traceback.tb_next) subject = 'Cron: Uncaught exception running %s' % module body = reporter.get_traceback_html() msgFrom = settings.SERVER_EMAIL msgTo = [admin[1] for admin in settings.FAILURE_RECIPIENTS] message = EmailMessage(subject, body, msgFrom, msgTo) message.content_subtype = 'html' message.send(fail_silently=False) raise finally: connection.close()
def send_exception_email(request=None): """ Send exception report email for the given exception e. """ if request is None: factory = RequestFactory() request = factory.get('/') exc_info = sys.exc_info() reporter = ExceptionReporter(request, is_email=True, *exc_info) subject = unicode(exc_info[1].message).replace('\n', '\\n').replace('\r', '\\r')[:989] mail_admins(subject, reporter.get_traceback_text(), fail_silently=True, html_message=reporter.get_traceback_html())
def emit(self, record): """ Taken from AdminEmailHandler.emit(...). The final part changes, because we want to send to addresses taken from settings.MANAGERS (instead of addresses taken from settings.ADMINS) """ # print "record: %s" % record.__dict__ try: ## request = record.request ## subject = '%s (%s IP): %s' % ( ## record.levelname, ## ('internal' if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS ## else 'EXTERNAL'), ## record.getMessage() ## ) ## filter = get_exception_reporter_filter(request) ## request_repr = '\n{0}'.format(force_text(filter.get_request_repr(request))) subject = record.subject except Exception: subject = '%s: %s' % (record.levelname, record.getMessage()) # request = None # request_repr = "unavailable" subject = self.format_subject(subject) if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) # message = "%s\n\nRequest repr(): %s" % (self.format(record), request_repr) message = self.format(record) request = None reporter = ExceptionReporter(request, is_email=True, *exc_info) html_message = reporter.get_traceback_html( ) if self.include_html else None mail.mail_managers(subject, message, fail_silently=True, html_message=html_message)
def emit(self, record): import traceback from django.conf import settings from django.views.debug import ExceptionReporter try: if sys.version_info < (2, 5): # A nasty workaround required because Python 2.4's logging # module doesn't support passing in extra context. # For this handler, the only extra data we need is the # request, and that's in the top stack frame. request = record.exc_info[2].tb_frame.f_locals['request'] else: request = record.request subject = '%s (%s IP): %s' % (record.levelname, ( request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), record.msg) request_repr = repr(request) except: subject = '%s: %s' % (record.levelname, record.msg) request = None request_repr = "Request repr() unavailable" if record.exc_info: exc_info = record.exc_info stack_trace = '\n'.join( traceback.format_exception(*record.exc_info)) else: exc_info = (None, record.msg, None) stack_trace = 'No stack trace available' message = "%s\n\n%s\n\n%s" % (self.format(record), stack_trace, request_repr) print message reporter = ExceptionReporter(request, is_email=True, *exc_info) html_message = self.include_html and reporter.get_traceback_html( ) or None mail.mail_admins(subject, message, fail_silently=True, html_message=html_message)
def process_exception(self, request, exception): """log unhandled 500 errors""" import json, requests, sys from datetime import datetime from django.conf import settings from django.views.debug import ExceptionReporter from models import DjelmahHost reporter = ExceptionReporter(request, exception.__class__, exception.message, sys.exc_info()[2]) data = json.dumps({ 'host': request.get_host(), 'path': request.get_full_path(), 'username': request.user.username, 'datetime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'error_type': exception.__class__.__name__, 'error_message': exception.message, 'status_code': "500", 'raw_html': reporter.get_traceback_html() }) headers = {'Content-Type': "application/json"} hosts = DjelmahHost.objects.filter(active=True) for host in hosts: headers['Authorization'] = "ApiKey {}:{}".format( host.username, host.api_key) url = host.hostname + "/djelmah/api/v1/logs/" requests.post(url, data=data, headers=headers) return None
def test_reporting_frames_without_source(self): try: source = "def funcName():\n raise Error('Whoops')\nfuncName()" namespace = {} code = compile(source, 'generated', 'exec') exec(code, namespace) except Exception: exc_type, exc_value, tb = sys.exc_info() request = self.rf.get('/test_view/') reporter = ExceptionReporter(request, exc_type, exc_value, tb) frames = reporter.get_traceback_frames() last_frame = frames[-1] self.assertEqual(last_frame['context_line'], '<source code not available>') self.assertEqual(last_frame['filename'], 'generated') self.assertEqual(last_frame['function'], 'funcName') self.assertEqual(last_frame['lineno'], 2) html = reporter.get_traceback_html() self.assertIn('generated in funcName', html) text = reporter.get_traceback_text() self.assertIn('"generated" in funcName', text)
def process_exception(self, request, exception): if settings.DEBUG_PROPAGATE_EXCEPTIONS or settings.DEBUG or isinstance( exception, (SystemExit, exceptions.PermissionDenied, http.Http404)): return exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(request, exc_type, exc_value, tb.tb_next) subject = 'Detailed Error (%s IP): %s' % ( (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path) html = reporter.get_traceback_html() message = EmailMessage(settings.EMAIL_SUBJECT_PREFIX + subject, html, settings.SERVER_EMAIL, [admin[1] for admin in settings.ADMINS]) message.content_subtype = 'html' message.send(fail_silently=True)
def send_exception_email(request, exception, subject=None, exc_info=None): '''Adapted from: http://stackoverflow.com/questions/29392281/manually-trigger-django-email-error-report ''' # Allow passing of exc_info if exc_info is None: exc_info = sys.exc_info() reporter = ExceptionReporter(request, is_email=True, *exc_info) # Should we auto-gen a subject if subject is None: subject = exception.message.replace('\n', '\\n').replace('\r', '\\r')[:989] # Compile the body of the email message = '%s\n\n%s' % ('\n'.join(traceback.format_exception(*exc_info)), reporter.filter.get_post_parameters(request)) mail.mail_admins(subject, message, fail_silently=True, html_message=reporter.get_traceback_html())
def emit(self, record): from hlogging.models import LoggingUser, LoggingMessage try: request = record.request except Exception: request = None if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) reporter = ExceptionReporter(request, is_email=True, *exc_info) html = reporter.get_traceback_html() text = self.format(record) levelname = record.levelname for type in self.types: users = LoggingUser.objects.filter(type=type).all() message = LoggingMessage(level=levelname, text=text, html=html) backend = import_string(LOGGING_BACKEND.get(type))() backend.send(users, message)
def process_exception(self, request, exception): """log unhandled 500 errors""" import json, requests, sys from datetime import datetime from django.conf import settings from django.forms.models import model_to_dict from django.views.debug import ExceptionReporter from models import DjelmahHost, DjelmahLog reporter = ExceptionReporter(request, exception.__class__, exception.message, sys.exc_info()[2]) log = DjelmahLog(host=request.get_host(), path=request.get_full_path(), username=request.user.username, datetime=datetime.now(), error_type=exception.__class__.__name__, error_message=exception.message, status_code="500", raw_html=reporter.get_traceback_html()) data = json.dumps(model_to_dict(log), default=lambda obj: obj.__str__()) headers = {'Content-Type': "application/json"} hosts = DjelmahHost.objects.filter(active=True) for host in hosts: if host.hostname == "localhost": log.save() else: headers['Authorization'] = "ApiKey {}:{}".format( host.username, host.api_key) url = host.hostname + "/djelmah/api/v1/logs/" requests.post(url, data=data, headers=headers) return None
def emit(self, record): try: request = record.request subject = '%s (%s IP): %s' % (record.levelname, ( request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), record.getMessage()) filter = get_exception_reporter_filter(request) request_repr = filter.get_request_repr(request) except Exception: subject = '%s: %s' % (record.levelname, record.getMessage()) request = None request_repr = "Request repr() unavailable." subject = self.format_subject(subject) if record.exc_info: exc_info = record.exc_info stack_trace = '\n'.join( traceback.format_exception(*record.exc_info)) else: exc_info = (None, record.getMessage(), None) stack_trace = 'No stack trace available' message = "%s\n\n%s" % (stack_trace, request_repr) reporter = ExceptionReporter(request, is_email=True, *exc_info) html_message = self.include_html and reporter.get_traceback_html( ) or None # create new connection connection = mail.get_connection() connection.password = settings.ALTERNATE_EMAIL_HOST_PASSWORD connection.username = settings.ALTERNATE_EMAIL_HOST_USER connection.host = settings.ALTERNATE_EMAIL_HOST connection.port = settings.ALTERNATE_EMAIL_PORT connection.use_tls = settings.ALTERNATE_EMAIL_USE_TLS mail.mail_admins(subject, message, fail_silently=True, html_message=html_message, connection=connection)
def get_response(self, request): exc_type, exc_value, traceback = sys.exc_info() reporter = ExceptionReporter(request, exc_type, exc_value, traceback.tb_next) html = reporter.get_traceback_html() http_response = http.HttpResponseServerError() if settings.DEBUG: http_response = http.HttpResponseServerError( html, content_type='text/html; charset=utf-8') elif getattr(settings, 'EMAIL_CRASHES', False): # Send Email Crash Report subject = 'django-firestone crash report' message = EmailMessage(subject=settings.EMAIL_SUBJECT_PREFIX + subject, body=html, from_email=settings.SERVER_EMAIL, to=[admin[1] for admin in settings.ADMINS]) message.content_subtype = 'html' message.send(fail_silently=True) return http_response
def uncaught_exception_email(self, request, resolver, exc_info): """ # Save uncaught exception handler. BaseHandler.original_handle_uncaught_exception = BaseHandler.handle_uncaught_exception # Override uncaught exception handler. BaseHandler.handle_uncaught_exception = uncaught_exception_email BaseHandler.developers_emails = ['*****@*****.**'] BaseHandler.uncaught_exception_subject = 'Django exception stack trace at your-hostname.net' """ from django.conf import settings from django.views.debug import ExceptionReporter if settings.DEBUG is False: reporter = ExceptionReporter(request, *exc_info) SendmailQueue()._add( subject=getattr(self, 'uncaught_exception_subject', 'Django exception stack trace'), body=reporter.get_traceback_text(), html_body=reporter.get_traceback_html(), to=self.developers_emails )._flush() return self.original_handle_uncaught_exception(request, resolver, exc_info)
def process_exception(self, request, exception): """ Create a technical server error response. The last three arguments are the values returned from sys.exc_info(). """ #because PostgreSQL default run on read commited mode, #so if any error occur, it should rollback the batch of sql statements. #connection._rollback() # for further explain: http://www.hoamon.info/blog/2013/04/12/difference_between_mysql_and_postgresql_with_django.html reporter = ExceptionReporter(request, *sys.exc_info()) #phase I, record bug page html bp = BugPage(html=reporter.get_traceback_html()) bp.save() #phase II, record request's detail bp.save_with_request(request=request) #phase III, search the same bug kind bp.kind = bp.find_bug_kind() bp.save() if request.is_ajax(): return HttpResponseServerError(json.dumps({'code': bp.code}), mimetype='application/json') else: if not settings.DEBUG or request.META.get( 'REMOTE_ADDR', '') in settings.INTERNAL_IPS: try: t = get_template_by_site_and_lang('500.html', sub_dir='') except TemplateDoesNotExist: try: t = get_template('500.html') except TemplateDoesNotExist: t = get_template_by_site_and_lang('500.html', sub_dir='ho600_lib') html = t.render( RequestContext(request, { 'request': request, 'bug_page': bp })) return HttpResponseServerError(html)
def emit(self, record): try: request = record.request subject = '%s (%s IP): %s' % ( record.levelname, ('internal' if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS else 'EXTERNAL'), record.getMessage() ) except Exception: subject = '%s: %s' % ( record.levelname, record.getMessage() ) request = None subject = self.format_subject(subject) # Since we add a nicely formatted traceback on our own, create a copy # of the log record without the exception data. no_exc_record = copy(record) no_exc_record.exc_info = None no_exc_record.exc_text = None if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) reporter = ExceptionReporter(request, is_email=True, *exc_info) message = "%s\n\n%s" % (self.format(no_exc_record), reporter.get_traceback_text()) html_message = reporter.get_traceback_html() if self.include_html else None send_mail(subject, message, from_email=settings.EMAIL_HOST_USER, recipient_list=settings.EMAIL_ADMIN_MAILS, fail_silently=True, html_message=html_message )