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_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 emit(self, record): exc_type, exc_value, traceback = record.exc_info request = record.request reporter = ExceptionReporter(request, exc_type, exc_value, traceback, is_email=True) exc = reporter.format_exception() message = '*%s* at `%s`\n\n```%s```' % ( exc[-1].strip(), request.path_info, ''.join(exc[:-1]), ) slack_debug(message)
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 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): 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 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 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 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 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(object): 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 exception_email_format(request, exc_info): ''' This function is used to encrypt the sensitive input data and send email to notify server administrator ''' if settings.DEBUG is False: reporter = ExceptionReporter(request, is_email=True, *exc_info) subject = r'Error:: IP %s : %s ' % (request.META.get('SERVER_ADDR'), reporter.exc_value) input_data = get_request_body(request) trace_data = reporter.get_traceback_data() if input_data: data_encrypt = response_output(input_data) trace_data['input_data'] = data_encrypt html_message = render_to_string('error_report.html', trace_data) ### send exception email through celery exception_email.delay_or_eager(subject, 'ERROR MAIL', fail_silently=True, html_message=html_message) return
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 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 _send_email(self, subject, message, exc_info=None, attachments=None, extra_recipients: Optional[List[str]] = 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, extra_recipients=extra_recipients)
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): 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 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 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 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 )
def error_handler(self, e, request, meth, em_format): """ Override this method to add handling of errors customized for your needs """ if isinstance(e, FormValidationError): return self.form_validation_response(e) elif isinstance(e, Http404): return rc.NOT_FOUND elif isinstance(e, HttpStatusCode): return e.response else: """ On errors (like code errors), we'd like to be able to give crash reports to both admins and also the calling user. There's two setting parameters for this: Parameters:: - `PISTON_EMAIL_ERRORS`: Will send a Django formatted error email to people in `settings.ADMINS`. - `PISTON_DISPLAY_ERRORS`: Will return a simple traceback to the caller, so he can tell you what error they got. If `PISTON_DISPLAY_ERRORS` is not enabled, the caller will receive a basic "500 Internal Server Error" message. """ exc_type, exc_value, tb = sys.exc_info() rep = ExceptionReporter(request, exc_type, exc_value, tb.tb_next) if self.email_errors: self.email_exception(rep) if self.display_errors: return HttpResponseServerError( format_error('\n'.join(rep.format_exception()))) else: raise
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 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() self.assertIn( "BrokenEvaluation", ExceptionReporter(request, exc_type, exc_value, tb).get_traceback_html(), "Evaluation exception reason not mentioned in traceback" )
def create_from_exception(sender, request=None, *args, **kwargs): """ Handles the exception upon receiving the signal. """ kind, info, data = sys.exc_info() if not issubclass(kind, Http404): error = Error.objects.create( kind=kind.__name__, html=ExceptionReporter(request, kind, info, data).get_traceback_html(), path=request.build_absolute_uri(), info=info, data='\n'.join(traceback.format_exception(kind, info, data)), ) if request and hasattr(request, 'user') and request.user and \ request.user.is_authenticated(): error.user = request.user error.save() if request and hasattr(request, 'session') and request.session: request.session['error_id'] = error.pk
def template_debug_output(): """ Usage: try: self.client.get(...) except: template_debug_output() """ import sys import html from django.views.debug import ExceptionReporter reporter = ExceptionReporter(None, *sys.exc_info()) reporter.get_template_exception_info() info = reporter.template_info print() print("Exception Message: " + info["message"]) print("Template: " + info["name"]) print() for line in info["source_lines"]: if line[0] == info["line"]: print("-->" + html.unescape(line[1])[3:-1]) else: print(html.unescape(line[1])[:-1])
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 preview_scribble(request): "Render scribble content or return error information." if not request.user.is_authenticated(): return HttpResponseForbidden() can_edit = request.user.has_perm('scribbler.change_scribble') can_create = request.user.has_perm('scribbler.add_scribble') if not (can_edit or can_create): return HttpResponseForbidden() results = { 'valid': False, 'html': '', } form = PreviewForm(request.POST) if form.is_valid(): results['valid'] = True if hasattr(template, 'engines'): scribbler_template = template.engines['django'].from_string(form.cleaned_data.get('content', '')) else: scribbler_template = template.Template(form.cleaned_data.get('content', '')) context = build_scribble_context(form.instance) results['html'] = scribbler_template.render(context, request) results['variables'] = get_variables(RequestContext(request, context)) else: if hasattr(form, 'exc_info'): exc_type, exc_value, tb = form.exc_info reporter = ExceptionReporter(request, exc_type, exc_value, tb) reporter.get_template_exception_info() results['error'] = reporter.template_info else: # Not sure what to do here results['error'] = { 'message': 'Content is not valid', 'line': '', } content = json.dumps(results, cls=DjangoJSONEncoder, ensure_ascii=False) return HttpResponse(content, content_type='application/json')
def emit(self, record): try: request = record.request subject = '%s %s (IP %s) | %s' % ( record.levelname, record.status_code, (request.META.get('REMOTE_ADDR')), record.getMessage(), ) reporter_filter = get_exception_reporter_filter(request) request_repr = reporter_filter.get_request_repr(request) except Exception: subject = '%s: %s' % (record.levelname, record.getMessage()) request = None request_repr = 'Request repr() is 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 is 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)