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 = "items = 'Oops'" else: value = "items = u'Oops'" # GET request = self.rf.get('/test_view/?items=Oops') reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn(value, text) # POST request = self.rf.post('/test_view/', data={'items': 'Oops'}) reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn(value, text) # FILES fp = six.StringIO('filecontent') request = self.rf.post('/test_view/', data={'name': 'filename', 'items': fp}) reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn('items = <InMemoryUploadedFile:', text) # COOKES rf = RequestFactory() rf.cookies['items'] = 'Oops' request = rf.get('/test_view/') reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn("items = 'Oops'", text)
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 = "items = 'Oops'" else: value = "items = u'Oops'" # GET request = self.rf.get("/test_view/?items=Oops") reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn(value, text) # POST request = self.rf.post("/test_view/", data={"items": "Oops"}) reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn(value, text) # FILES fp = six.StringIO("filecontent") request = self.rf.post("/test_view/", data={"name": "filename", "items": fp}) reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn("items = <InMemoryUploadedFile:", text) # COOKES rf = RequestFactory() rf.cookies["items"] = "Oops" request = rf.get("/test_view/") reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn("items = 'Oops'", text)
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. """ # GET request = self.rf.get('/test_view/?items=Oops') reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn("items = 'Oops'", text) # POST request = self.rf.post('/test_view/', data={'items': 'Oops'}) reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn("items = 'Oops'", text) # FILES fp = StringIO('filecontent') request = self.rf.post('/test_view/', data={'name': 'filename', 'items': fp}) reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn('items = <InMemoryUploadedFile:', text) # COOKES rf = RequestFactory() rf.cookies['items'] = 'Oops' request = rf.get('/test_view/') reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn("items = 'Oops'", text)
def handle_exception(self, exc, request): from django.utils.log import getLogger from django.conf import settings logger = getLogger('django.request') exc_info = sys.exc_info() logger.error( 'Internal Server Error: %s', request.path, exc_info=exc_info, extra={ 'status_code': 500, 'request': request } ) resp = HttpResponse('', status=500, content_type='text/plain') resp.content = '' if hasattr(exc, 'resp_obj'): resp = exc.resp_obj resp.status_code = 500 resp.set_common_headers(request) else: resp = HttpResponse('', status=500, content_type='text/plain') resp.content = 'An error occured.' if settings.DEBUG: from django.views.debug import ExceptionReporter reporter = ExceptionReporter(request, *exc_info) resp.content = reporter.get_traceback_text() resp['Content-Type'] = 'text/plain' return resp
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 emit(self, record): """ Handle the exceptions every 500 error page. """ 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()) if record.request: request = record.request else: 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=False, *exc_info) message = "%s\n\n%s" % (self.format(no_exc_record), reporter.get_traceback_text()) html_message = reporter.get_traceback_html() # need to load model here, because it's declared in settings from except_catcher.models import ExceptionReport report = ExceptionReport.objects.create(subject=subject, message=message, html_message=html_message)
def get_context_data(self, *args, **kwargs): try: self.initialize(*args, **kwargs) qs = self.get_initial_queryset() # number of records before filtering total_records = qs.count() qs = self.filter_queryset(qs) # number of records after filtering total_display_records = qs.count() qs = self.ordering(qs) qs = self.paging(qs) # prepare output data if self.pre_camel_case_notation: aaData = self.prepare_results(qs) ret = {'sEcho': int(self._querydict.get('sEcho', 0)), 'iTotalRecords': total_records, 'iTotalDisplayRecords': total_display_records, 'aaData': aaData } else: data = self.prepare_results(qs) ret = {'draw': int(self._querydict.get('draw', 0)), 'recordsTotal': total_records, 'recordsFiltered': total_display_records, 'data': data } except Exception as e: logger.exception(str(e)) if settings.DEBUG: import sys from django.views.debug import ExceptionReporter reporter = ExceptionReporter(None, *sys.exc_info()) text = "\n" + reporter.get_traceback_text() else: text = "\nAn error occured while processing an AJAX request." if self.pre_camel_case_notation: ret = {'result': 'error', 'sError': text, 'text': text, 'aaData': [], 'sEcho': int(self._querydict.get('sEcho', 0)), 'iTotalRecords': 0, 'iTotalDisplayRecords': 0, } else: ret = {'error': text, 'data': [], 'recordsTotal': 0, 'recordsFiltered': 0, 'draw': int(self._querydict.get('draw', 0))} return ret
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 get_data(self, request): """ Gets all data, unpaged, as a list of dicts. """ qs = self.get_initial_queryset(request) qs = self.filter_queryset(qs) qs = self.ordering(qs) data = self.prepare_results(qs) try: qs = self.get_initial_queryset(request) qs = self.filter_queryset(qs) qs = self.ordering(qs) data = self.prepare_results(qs) except Exception as e: logger.exception(str(e)) if settings.DEBUG: import sys from django.views.debug import ExceptionReporter reporter = ExceptionReporter(None, *sys.exc_info()) text = "\n" + reporter.get_traceback_text() else: text = "\nAn error occured while processing an AJAX request." data = {'error': text} return data
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 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): if not self.active: return try: request = record.request except Exception: request = None title = '%s: %s' % (record.exc_info[1].__class__.__name__, record.exc_info[1]) title = title.replace('\n', '\\n').replace('\r', '\\r') issue_id = self.get_issue_id(title) if not issue_id: 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()) self.create_issue(title, message) else: self.reopen_issue(issue_id)
def emit(self, record): try: request = record.request hostname = request.get_host() subject = '%s %s' % ( hostname.split('.')[0], # e.g. tfc-app2 record.getMessage() ) except Exception: subject = '%s: %s' % ( record.levelname, record.getMessage() ) request = None hostname = 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 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 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 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 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): %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 render_to_json(response, *args, **kwargs): """ Creates the main structure and returns the JSON response. """ # determine the status code if hasattr(response, 'status_code'): status_code = response.status_code elif issubclass(type(response), Http404): status_code = 404 elif issubclass(type(response), Exception): status_code = 500 logger.exception(str(response), extra={'request': kwargs.pop('request', None)}) if settings.DEBUG: import sys reporter = ExceptionReporter(None, *sys.exc_info()) text = reporter.get_traceback_text() response = HttpResponseServerError(text, content_type='text/plain') else: response = HttpResponseServerError("An error occured while processing an AJAX request.", content_type='text/plain') else: status_code = 200 # creating main structure data = { 'status': status_code, 'statusText': REASON_PHRASES.get(status_code, 'UNKNOWN STATUS CODE'), 'content': response } return JSONResponse(data, *args, **kwargs)
def emit(self, record): try: if self.routing_key_formatter: routing_key = self.routing_key_formatter(record) else: routing_key = self.routing_key_format.format( name=record.name, level=record.levelname) if hasattr(record, 'request'): no_exc_record = copy(record) del no_exc_record.exc_info del no_exc_record.exc_text del no_exc_record.request if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) reporter = ExceptionReporter(record.request, is_email=False, *exc_info) no_exc_record.traceback = reporter.get_traceback_text() formatted = self.format(no_exc_record) else: formatted = self.format(record) self.queue.put((formatted, routing_key)) except Exception: self.channel, self.connection = None, None self.handleError(record)
def get_context_data(self, *args, **kwargs): try: self.initialize(*args, **kwargs) qs = self.get_initial_queryset() # number of records before filtering total_records = qs.count() qs = self.filter_queryset(qs) # number of records after filtering total_display_records = qs.count() qs = self.ordering(qs) qs = self.paging(qs) # prepare output data if self.pre_camel_case_notation: aaData = self.prepare_results(qs) ret = {'sEcho': int(self._querydict.get('sEcho', 0)), 'iTotalRecords': total_records, 'iTotalDisplayRecords': total_display_records, 'aaData': aaData } else: data = self.prepare_results(qs) ret = {'draw': int(self._querydict.get('draw', 0)), 'recordsTotal': total_records, 'recordsFiltered': total_display_records, 'data': data } except Exception as e: logger.exception(str(e)) if settings.DEBUG: import sys from django.views.debug import ExceptionReporter reporter = ExceptionReporter(None, *sys.exc_info()) text = "\n" + reporter.get_traceback_text() else: text = "\nAn error occured while processing an AJAX request." if self.pre_camel_case_notation: ret = {'result': 'error', 'sError': text, 'text': text, 'aaData': [], 'sEcho': int(self._querydict.get('sEcho', 0)), 'iTotalRecords': 0, 'iTotalDisplayRecords': 0, } else: ret = {'error': text, 'data': [], 'recordsTotal': 0, 'recordsFiltered': 0, 'draw': int(self._querydict.get('draw', 0))} return ret
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.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) try: tb = reporter.get_traceback_text() except: tb = "(An exception occured when getting the traceback text)" if reporter.exc_type: tb = "%s (An exception occured when rendering the traceback)" \ % reporter.exc_type.__name__ message = "%s\n\n%s" % (self.format(no_exc_record), tb) colors = { 'ERROR': 'danger', 'WARNING': 'warning', 'INFO': 'good', } attachments = { 'title': subject, 'text': message, 'color': colors.get(record.levelname, '#AAAAAA'), } attachments.update(self.kwargs) self.send_message( self.template, {'text': subject}, self.generate_attachments(**attachments), )
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.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) try: tb = reporter.get_traceback_text() except: tb = "(An exception occured when getting the traceback text)" if reporter.exc_type: tb = "%s (An exception occured when rendering the traceback)" \ % reporter.exc_type.__name__ message = "%s\n\n%s" % (self.format(no_exc_record), tb) colors = { 'ERROR': 'danger', 'WARNING': 'warning', 'INFO': 'good', } attachments = { 'title': subject, 'text': message, 'color': colors.get(record.levelname, '#AAAAAA'), } attachments.update(self.kwargs) self.send_message( self.template, {'text': subject}, self.generate_attachments(**attachments), )
def exception_email(request, e): exc_info = sys.exc_info() reporter = ExceptionReporter(request, is_email=True, *exc_info) try: subject = e.message.replace("\n", "\\n").replace("\r", "\\r")[:989] except AttributeError: subject = "Unkown Error" message = reporter.get_traceback_text() celery_admin_mail.delay(subject, message, reporter.get_traceback_html())
def celery_error_handler(task_id, exception, traceback, einfo, *args, **kwargs): if settings.DEBUG: return mail_subject = "Task exception - {}".format(exception) mail_subject = mail_subject.replace("\n", " ")[:250] reporter = ExceptionReporter(None, einfo.type, exception, traceback) mail_text = reporter.get_traceback_text() mail_admins(mail_subject, mail_text)
def exception_email(request, e): exc_info = sys.exc_info() reporter = ExceptionReporter(request, is_email=True, *exc_info) try: subject = e.message.replace('\n', '\\n').replace('\r', '\\r')[:989] except AttributeError: subject = "Unkown Error" message = reporter.get_traceback_text() mail.mail_admins(subject, message, fail_silently=True, html_message=reporter.get_traceback_html())
def get_context_data(self, request): """ Gets paginated data. Returned as json dict. """ json_response = dict( draw=0, recordsTotal=0, recordsFiltered=0, data=[] ) try: qs = self.get_initial_queryset(request) # number of records before filtering total_records = qs.count() qs = self.filter_queryset(qs) # number of records after filtering total_display_records = qs.count() qs = self.ordering(qs) qs = self.paging(qs) # prepare output data data = self.prepare_results(qs) json_response.update(dict( draw=int(self._querydict.get('draw', 0)), recordsTotal=total_records, recordsFiltered=total_display_records, data=data )) except Exception as e: logger.exception(str(e)) if settings.DEBUG: import sys from django.views.debug import ExceptionReporter reporter = ExceptionReporter(None, *sys.exc_info()) text = "\n" + reporter.get_traceback_text() else: text = "\nAn error occured while processing an AJAX request." json_response['error'] = text return json_response
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 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_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) text = reporter.get_traceback_text() self.assertIn('ValueError', text) self.assertIn("Can't find my keys", text) self.assertNotIn('Request Method:', text) self.assertNotIn('Request URL:', text) self.assertIn('Exception Type:', text) self.assertIn('Exception Value:', text) self.assertIn('Traceback:', text) self.assertIn('Request data not supplied', text)
def render_to_dict(response, *args, **kwargs): """ Creates the main structure of the JSONResponse as a dict. """ data = {} # determine the status code if hasattr(response, 'status_code'): status_code = response.status_code if issubclass(type(response), HttpResponseRedirectBase): data['HttpResponse'] = response.url elif issubclass(type(response), TemplateResponse): data['HttpResponse'] = response.rendered_content elif issubclass(type(response), HttpResponse): data['HttpResponse'] = response.content elif issubclass(type(response), Exception) \ or isinstance(response, bytes): return force_text(response) elif issubclass(type(response), Http404): status_code = 404 data['HttpResponse'] = response elif issubclass(type(response), Exception): status_code = 500 logger.exception(str(response), extra={'request': kwargs.pop('request', None)}) if settings.DEBUG: import sys reporter = ExceptionReporter(None, *sys.exc_info()) data['HttpResponse'] = reporter.get_traceback_text() else: data['HttpResponse'] = "An error occured while processing an AJAX \ request." else: status_code = 200 data.update(response) # creating main structure data.update({ 'status': status_code, 'statusText': REASON_PHRASES.get(status_code, 'UNKNOWN STATUS CODE'), }) return data
def emit(self, record): self.acquire() try: if not self.connection or self.connection.is_closed or not self.channel or self.channel.is_closed: self.open_connection() if self.routing_key_formatter: routing_key = self.routing_key_formatter(record) else: routing_key = self.routing_key_format.format( name=record.name, level=record.levelname) if hasattr(record, 'request'): no_exc_record = copy(record) del no_exc_record.exc_info del no_exc_record.exc_text del no_exc_record.request if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) reporter = ExceptionReporter(record.request, is_email=False, *exc_info) no_exc_record.traceback = reporter.get_traceback_text() formatted = self.format(no_exc_record) else: formatted = self.format(record) self.channel.basic_publish(exchange=self.exchange, routing_key=routing_key, body=formatted, properties=pika.BasicProperties( delivery_mode=2, headers=self.message_headers)) except Exception: self.channel, self.connection = None, None self.handleError(record) finally: if self.close_after_emit: self.close_connection() self.release()
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) text = reporter.get_traceback_text() self.assertIn('ValueError at /test_view/', text) self.assertIn("Can't find my keys", text) self.assertIn('Request Method:', text) self.assertIn('Request URL:', text) self.assertIn('Exception Type:', text) self.assertIn('Exception Value:', text) self.assertIn('Traceback:', text) self.assertIn('Request information:', text) self.assertNotIn('Request data not supplied', text)
def test_template_exception(self): request = self.rf.get('/test_view/') try: render(request, 'debug/template_error.html') except Exception: exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(request, exc_type, exc_value, tb) text = reporter.get_traceback_text() templ_path = Path(Path(__file__).parent.parent, 'templates', 'debug', 'template_error.html') self.assertIn( 'Template error:\n' 'In template %(path)s, error at line 2\n' ' \'cycle\' tag requires at least two arguments\n' ' 1 : Template with error:\n' ' 2 : {%% cycle %%} \n' ' 3 : ' % {'path': templ_path}, text )
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 test_request_and_exception(self): "A simple exception report can be generated" try: request = self.rf.get("/test_view/") request.user = User() 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) text = reporter.get_traceback_text() self.assertIn("ValueError at /test_view/", text) self.assertIn("Can't find my keys", text) self.assertIn("Request Method:", text) self.assertIn("Request URL:", text) self.assertIn("USER: jacob", text) self.assertIn("Exception Type:", text) self.assertIn("Exception Value:", text) self.assertIn("Traceback:", text) self.assertIn("Request information:", text) self.assertNotIn("Request data not supplied", text)
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 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 test_reporting_of_nested_exceptions(self): request = self.rf.get('/test_view/') try: try: raise AttributeError('Top level') except AttributeError as explicit: try: raise ValueError('Second exception') from explicit except ValueError: raise IndexError('Final exception') 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() self.assertIn(explicit_exc.format("Top level"), html) self.assertIn(implicit_exc.format("Second exception"), html) text = reporter.get_traceback_text() self.assertIn(explicit_exc.format("Top level"), text) self.assertIn(implicit_exc.format("Second exception"), text)
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) text = reporter.get_traceback_text()
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) text = reporter.get_traceback_text()
def test_disallowed_host(self): "An exception report can be generated even for a disallowed host." request = self.rf.get('/', HTTP_HOST='evil.com') reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn("http://evil.com/", text)
def report_traceback(self): if settings.DEBUG: reporter = ExceptionReporter(None, *sys.exc_info()) return "\n" + reporter.get_traceback_text() return "\nAn error occured while processing an AJAX request."
from __future__ import unicode_literals
def test_message_only(self): reporter = ExceptionReporter(None, None, "I'm a little teapot", None) text = reporter.get_traceback_text()
def emit(self, record): if record.exc_info: exc_info = record.exc_info reporter = ExceptionReporter(record.request, *exc_info) # Create the SnowyEvening stack trace frames = [ { "file" : i['filename'], "line" : i['lineno'], "function" : i['function'] } for i in reporter.get_traceback_frames()[::-1] ] error_type = exc_info[0].__name__ error_message = exc_info[0].__name__ + ": " + unicode(exc_info[1]) file_path = frames[0]['file'] line = str(frames[0]['line']) else: exc_info = (None, record.getMessage(), None) reporter = ExceptionReporter(record.request, *exc_info) frames = [] error_type = "Logger" error_message = "Logger: " + record.getMessage() file_path = record.pathname line = str(record.lineno) # Find visitor IP x_forwarded_for = record.request.META.get('HTTP_X_FORWARDED_FOR') if x_forwarded_for: visitor_ip = x_forwarded_for.split(',')[0] else: visitor_ip = record.request.META.get('REMOTE_ADDR') # prepare request payload = { "application" : self.APPLICATION, "version_complete" : self.VERSION_COMPLETE, "version" : self.VERSION, "build" : self.BUILD, "date" : strftime("%Y-%m-%d %H:%M:%S"), "gmdate" : strftime("%Y-%m-%d %H:%M:%S", gmtime()), "visitor_ip" : visitor_ip, "referrer_url" : record.request.META.get("HTTP_REFERER", ""), "request_uri" : record.request.path, "user_agent" : record.request.META.get("HTTP_USER_AGENT", ""), "error_type" : error_type, "error_message" : error_message, "error_no" : 500, "file" : file_path, "line" : line, "trace" : frames, "additional_info" : reporter.get_traceback_text(), } # Optionally, you may provide a custom hash of the error that Snowy will # use to determine if it's a duplicate or not. By default, Snowy hashes # the application, error number, and error message and if that hash # matches existing errors, we append the error to that issue instead of # making a new one. # You may provide your own custom hash that we'll check against your # existing issues. The hash may be up to 255 characters long. # For example, this will require errors come from the same application, # file, and exact line. payload['hash'] = sha1(self.APPLICATION + file_path + line).hexdigest() params = { 'payload' : json.dumps(payload), 'api_key' : self.API_KEY, 'project_id' : self.PROJECT_ID, } # post urllib.urlopen(self.SNOWY_ERROR_URL, urllib.urlencode(params))
def test_disallowed_host(self): "An exception report can be generated even for a disallowed host." request = self.rf.get('/', HTTP_HOST='evil.com') reporter = ExceptionReporter(request, None, None, None) text = reporter.get_traceback_text() self.assertIn("http://evil.com/", text)