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 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): 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 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 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 template = Template(form.cleaned_data.get('content', '')) context = build_scribble_context(form.instance, request) results['html'] = template.render(context) results['variables'] = get_variables(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, (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 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 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): 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 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 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 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 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 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 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 format(self, record): """Format exception object as a string""" data = record._raw.copy() data['extra'] = self.prepare_data(data.get('extra')) if 'exc_info' in data and data['exc_info']: if DJANGO_ENABLE: er = ExceptionReporter(None, *data['exc_info']) data['exc_extra_info'] = self.prepare_data(er.get_traceback_frames()) data['exc_info'] = self.formatException(data['exc_info']) data['msg'] = logging.Formatter.format(self, record) data['format'] = data['msg'] del data['args'] # hack for normalize unicode data for soap fault for key in ['exc_info', 'format']: if isinstance(data[key], basestring): try: data[key] = data[key].decode("unicode_escape") except UnicodeEncodeError: pass return data
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): 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 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 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 __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 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 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, self.determine_emitter(request)) elif isinstance(e, TypeError): result = rc.BAD_REQUEST msg = "Method signature does not match.\n\n" try: hm = HandlerMethod(meth) sig = hm.signature except TypeError: msg += "Signature could not be determined" else: if sig: msg += "Signature should be: %s" % sig else: msg += "Resource does not expect any parameters." if self.display_errors: msg += "\n\nException was: %s" % str(e) result.content = format_error(msg) return result 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 create_from_exception(self, exception=None, traceback=None, **kwargs): """ Creates an error log from an exception. """ if not exception: exc_type, exc_value, traceback = sys.exc_info() elif not traceback: warnings.warn('Using just the ``exception`` argument is deprecated, send ``traceback`` in addition.', DeprecationWarning) exc_type, exc_value, traceback = sys.exc_info() else: exc_type = exception.__class__ exc_value = exception def to_unicode(f): if isinstance(f, dict): nf = dict() for k, v in f.iteritems(): nf[str(k)] = to_unicode(v) f = nf elif isinstance(f, (list, tuple)): f = [to_unicode(f) for f in f] else: try: f = smart_unicode(f) except (UnicodeEncodeError, UnicodeDecodeError): f = '(Error decoding value)' return f def shorten(var): if not isinstance(var, basestring): var = to_unicode(var) if len(var) > 500: var = var[:500] + '...' return var reporter = ExceptionReporter(None, exc_type, exc_value, traceback) frames = varmap(shorten, reporter.get_traceback_frames()) data = kwargs.pop('data', {}) or {} data['__sentry__'] = { 'exc': map(to_unicode, [exc_type.__class__.__module__, exc_value.args, frames]), } if isinstance(exc_value, TemplateSyntaxError) and hasattr(exc_value, 'source'): origin, (start, end) = exc_value.source data['__sentry__'].update({ 'template': (origin.reload(), start, end, origin.name), }) tb_message = '\n'.join(traceback_mod.format_exception(exc_type, exc_value, traceback)) kwargs.setdefault('message', to_unicode(exc_value)) return self._create( class_name=exc_type.__name__, traceback=tb_message, data=data, **kwargs )
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 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 create_from_exception(self, exception=None, traceback=None, **kwargs): """ Creates an error log from an exception. """ if not exception: exc_type, exc_value, traceback = sys.exc_info() elif not traceback: warnings.warn( "Using just the ``exception`` argument is deprecated, send ``traceback`` in addition.", DeprecationWarning, ) exc_type, exc_value, traceback = sys.exc_info() else: exc_type = exception.__class__ exc_value = exception def to_unicode(f): if isinstance(f, dict): nf = dict() for k, v in f.iteritems(): nf[str(k)] = to_unicode(v) f = nf elif isinstance(f, (list, tuple)): f = [to_unicode(f) for f in f] else: try: f = smart_unicode(f) except (UnicodeEncodeError, UnicodeDecodeError): f = "(Error decoding value)" except Exception: # in some cases we get a different exception f = smart_unicode(type(f)) return f def shorten(var): if not isinstance(var, basestring): var = to_unicode(var) if len(var) > 500: var = var[:500] + "..." return var reporter = ExceptionReporter(None, exc_type, exc_value, traceback) frames = varmap(shorten, reporter.get_traceback_frames()) data = kwargs.pop("data", {}) or {} data["__sentry__"] = {"exc": map(to_unicode, [exc_type.__class__.__module__, exc_value.args, frames])} if isinstance(exc_value, TemplateSyntaxError) and hasattr(exc_value, "source"): origin, (start, end) = exc_value.source data["__sentry__"].update({"template": (origin.reload(), start, end, origin.name)}) tb_message = "\n".join(traceback_mod.format_exception(exc_type, exc_value, traceback)) kwargs.setdefault("message", to_unicode(exc_value)) return self.process(class_name=exc_type.__name__, traceback=tb_message, data=data, **kwargs)
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 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 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) # 导出多少条日志 download_numbers = self.request.DATA.get("download_numbers", 0) if download_numbers != 0: qs = qs[:int(download_numbers)] else: qs = self.paging(qs) if self.enable_es: self.es_result = self.search_from_es(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.error(e.message, exc_info=True) if settings.DEBUG: reporter = ExceptionReporter(None, *sys.exc_info()) text = "\n" + reporter.get_traceback_text() else: reporter = ExceptionReporter(None, *sys.exc_info()) err_text = "\n" + reporter.get_traceback_text() notify_administrator(content=err_text, title='Datatable错误') 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)) } if self.request.DATA.get("dts_download", 0) == 1: datatable = ret.get("data", []) or ret.get("aaData", []) filename = getattr(self.request, "filename", "数据表") filename = filename + "_%s.xls" filename = filename % int(time.time()) if self.custom_template: labels, headers = self.handle_custom_template() else: labels = getattr(self.request, "labels", ()) headers = getattr(self.request, "headers", ()) file_path = excel_export(filename, labels, headers, datatable) file_path = "http://%s/%s" % (self.request.META.get('HTTP_HOST'), file_path) # ret = dict() ret["status"] = 200 ret["msg"] = "下载成功" ret["file_path"] = file_path min_len = min(len(datatable), 10) if min_len: ret["data"] = [] return ret
def error_handler(self, response, e, request, meth): """ Override this method to add handling of errors customized for your needs """ response.status_code = 500 if isinstance(e, (PistonException, PistonBadRequestException, PistonForbiddenException, PistonMethodException, PistonNotFoundException, PistonUnauthorizedException)): response.status_code = e.status_code response.error_message = e.message response.headers.update(e.headers) elif isinstance(e, FormValidationError): response.status_code = 400 response.form_errors = e.form.errors elif isinstance(e, TypeError) and meth: hm = HandlerMethod(meth) sig = hm.signature msg = 'Method signature does not match.\n\n' if sig: msg += 'Signature should be: %s' % sig else: msg += 'Resource does not expect any parameters.' if self.display_errors: msg += '\n\nException was: %s' % str(e) response.error_message = format_error(msg) # TODO: As we start using Piston exceptions, the following 2 errors can be phased out elif isinstance(e, Http404): response.status_code = 404 response.error_message = 'Not Found' elif isinstance(e, HttpStatusCode): response.error_message = 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 message/full traceback depending on `PISTON_DISPLAY_TRACEBACK`. Default is simple message 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: if self.display_traceback: response.error_message = format_error('\n'.join( rep.format_exception())) else: response.error_message = str(e) else: raise
def get_context_data(self, *args, **kwargs): try: self.es_query_dict = dict() self.doc_type = "" # 新旧版本区分 √ self.initialize(*args, **kwargs) # 不知道要做什么先 qs = self.get_initial_queryset() # 添加过滤条件 √ self.filter_queryset() # 排序字典 √ self.ordering() # 分页 √ self.paging() # 加index self.es_query_dict["index"] = self.index # 从es获取数据 result = get_by_any(**self.es_query_dict) # 获取查询结果集 all_hits = result['hits']['hits'] qs = [ah['_source'] for ah in all_hits] # 总条数 total_records = result['hits']['total'] # 总显示条数 total_display_records = total_records # 处理数据 √ output_data = self.prepare_results(qs) if self.pre_camel_case_notation: ret = { 'sEcho': int(self.querydict.get('sEcho', 0)), 'iTotalRecords': total_records, 'iTotalDisplayRecords': total_display_records, 'aaData': output_data } else: ret = { 'draw': int(self.querydict.get('draw', 0)), 'recordsTotal': total_records, 'recordsFiltered': total_display_records, 'data': output_data } except (Exception, elasticsearch.TransportError, elasticsearch.NotFoundError) as e: logger.exception(str(e)) if settings.DEBUG: reporter = ExceptionReporter(None, *sys.exc_info()) text = "\n" + reporter.get_traceback_text() else: reporter = ExceptionReporter(None, *sys.exc_info()) err_text = "\n" + reporter.get_traceback_text() notify_administrator(content=err_text, title='Datatable错误') 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 = { 'data': [], 'recordsTotal': 0, 'recordsFiltered': 0, 'draw': int(self.querydict.get('draw', 0)) } if settings.DEBUG: ret["error"] = text return ret
""" 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 emitter, ct = Emitter.get(em_format) srl = emitter(result, typemapper, handler, handler.fields, anonymous) try: """ Decide whether or not we want a generator here, or we just want to buffer up the entire result
def get_context_data(self, *args, **kwargs): request = self.request 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(request.REQUEST.get('sEcho', 0)), 'iTotalRecords': total_records, 'iTotalDisplayRecords': total_display_records, 'aaData': aaData } else: data = self.prepare_results(qs) ret = { 'draw': int(request.REQUEST.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(request.REQUEST.get('sEcho', 0)), 'iTotalRecords': 0, 'iTotalDisplayRecords': 0, } else: ret = { 'error': text, 'data': [], 'recordsTotal': 0, 'recordsFiltered': 0, 'draw': int(request.REQUEST.get('draw', 0)) } # logger.info("RET=%s"%ret) return ret
def emit(self, record): try: request = record.request internal = 'internal' if request.META.get('REMOTE_ADDR') in \ settings.INTERNAL_IPS else 'EXTERNAL' subject = '{} ({} IP): {}'.format( record.levelname, internal, record.getMessage(), ) except Exception: subject = '{}: {}'.format( 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 = "{} (An exception occured when rendering the " \ "traceback)".format(reporter.exc_type.__name__) message = "{}\n\n{}".format(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), channel=self.channel)
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, self.determine_emitter(request)) elif isinstance(e, TypeError): result = rc.BAD_REQUEST msg = 'Method signature does not match.\n\n' try: hm = HandlerMethod(meth) sig = hm.signature except TypeError: msg += 'Signature could not be determined' else: if sig: msg += 'Signature should be: %s' % sig else: msg += 'Resource does not expect any parameters.' if self.display_errors: msg += '\n\nException was: %s' % str(e) result.content = format_error(msg) return result 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 __init__(self, request, exc_type, exc_value, frames): ExceptionReporter.__init__(self, request, exc_type, exc_value, None) self.frames = frames
def create_from_exception(self, exc_info=None, **kwargs): """ Creates an error log from an exception. """ if not exc_info: exc_info = sys.exc_info() exc_type, exc_value, exc_traceback = exc_info def to_unicode(f): if isinstance(f, dict): nf = dict() for k, v in f.iteritems(): nf[str(k)] = to_unicode(v) f = nf elif isinstance(f, (list, tuple)): f = [to_unicode(f) for f in f] else: try: f = smart_unicode(f) except (UnicodeEncodeError, UnicodeDecodeError): f = '(Error decoding value)' except Exception: # in some cases we get a different exception f = smart_unicode(type(f)) return f def shorten(var): if not isinstance(var, basestring): var = to_unicode(var) if len(var) > 200: var = var[:200] + '...' return var reporter = ExceptionReporter(None, exc_type, exc_value, exc_traceback) frames = varmap(shorten, reporter.get_traceback_frames()) if not kwargs.get('view'): # This should be cached modules = get_installed_apps() if settings.INCLUDE_PATHS: modules = set(list(modules) + settings.INCLUDE_PATHS) def iter_tb_frames(tb): while tb: yield tb.tb_frame tb = tb.tb_next def contains(iterator, value): for k in iterator: if value.startswith(k): return True return False # We iterate through each frame looking for an app in INSTALLED_APPS # When one is found, we mark it as last "best guess" (best_guess) and then # check it against SENTRY_EXCLUDE_PATHS. If it isnt listed, then we # use this option. If nothing is found, we use the "best guess". best_guess = None for frame in iter_tb_frames(exc_traceback): view = '.'.join( [frame.f_globals['__name__'], frame.f_code.co_name]) if contains(modules, view): if not (contains(settings.EXCLUDE_PATHS, view) and best_guess): best_guess = view elif best_guess: break if best_guess: view = best_guess kwargs['view'] = view data = kwargs.pop('data', {}) or {} data['__sentry__'] = { 'exc': map(to_unicode, [exc_type.__class__.__module__, exc_value.args, frames]), } if isinstance(exc_value, TemplateSyntaxError) and hasattr( exc_value, 'source'): origin, (start, end) = exc_value.source data['__sentry__'].update({ 'template': (origin.reload(), start, end, origin.name), }) kwargs['view'] = origin.loadname tb_message = '\n'.join( traceback.format_exception(exc_type, exc_value, exc_traceback)) kwargs.setdefault('message', to_unicode(exc_value)) return self.process(class_name=exc_type.__name__, traceback=tb_message, data=data, **kwargs)
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 log_event(cls, request, response=None, exception=None): from django.views.debug import ExceptionReporter stack_info = {} if exception: exc_type, exc_value, exc_traceback = sys.exc_info() summary = "{0}: {1}".format(exception.__class__.__name__, unicode(exception)) lineno = traceback.tb_lineno(exc_traceback) stack = traceback.extract_tb(exc_traceback) unique_path = "|".join(line[0] for line in stack) path = stack[-1][0] try: reporter = ExceptionReporter(request, is_email=False, *(exc_type, exc_value, exc_traceback)) django_data = reporter.get_traceback_data() stack_info["frames"] = django_data.get("frames", []) #Traceback objects aren't JSON serializable, so delete them for frame in stack_info["frames"]: if "tb" in frame: del frame["tb"] stack_info["lastframe"] = django_data.get("lastframe", {}) except Exception: logging.exception("Unable to get html traceback info for some reason") level = EVENT_LEVEL_ERROR else: summary = "{0} at {1}".format(response.status_code, request.path) lineno = 0 path = "?".join([request.path, request.META.get('QUERY_STRING')]) unique_path = path exception = HttpResponse() level = EVENT_LEVEL_WARNING if response.status_code == 404 else EVENT_LEVEL_INFO exception_name = exception.__class__.__name__ # unique_path is either the full URL or the combined paths from the # entire stack trace. path_hash = Error.hash_for_file_path(unique_path) #We try to get from the cache first because on the App Engine datastore #we'll get screwed by eventual consistency otherwise CACHE_KEY = "|".join([exception_name, path_hash, str(lineno)]) error = cache.get(CACHE_KEY) if error: created = False else: try: error, created = Error.objects.get_or_create( exception_class_name=exception_name, hashed_file_path=path_hash, line_number=lineno, defaults={ 'file_path': path, 'level': level, 'summary': summary, 'exception_class_name': exception.__class__.__name__ if exception else "" } ) except MultipleObjectsReturned: #FIXME: Temporary hack for App Engine If we created dupes, this de-dupes them errors = Error.objects.filter(exception_class_name=exception_name, hashed_file_path=path_hash, line_number=lineno).all() max_errors = 0 to_keep = None to_remove = [] for error in errors: num_events = error.events.count() if max_errors < num_events: # Store the error with the most events to_keep = error max_errors = num_events else: #this error doesn't have the most events, so mark it for removal to_remove.append(error) assert to_keep logging.warning("Removing {} duplicate errors".format(len(to_remove))) for error in to_remove: error.events.all().update(error=to_keep) error.delete() error = to_keep cache.set(CACHE_KEY, error) @db.transactional(xg=True) def txn(_error): _error = Error.objects.get(pk=_error.pk) event = Event.objects.create( error=_error, request_repr=repr(request).strip(), request_method=request.method, request_url=request.build_absolute_uri(), request_querystring=request.META['QUERY_STRING'], logged_in_user_email=getattr(getattr(request, "user", None), "email", ""), stack_info_json=json.dumps(stack_info), app_version=os.environ.get('CURRENT_VERSION_ID', 'Unknown'), request_json=construct_request_json(request) ) _error.last_event = timezone.now() _error.event_count += 1 _error.save() return event return txn(error)
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 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 test_message_only(self): reporter = ExceptionReporter(None, None, "I'm a little teapot", None) reporter.get_traceback_text()
def emit(self, record): if not switch_is_active("LOG_TO_DISCORD"): return 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 = subject.replace("\n", "\\n").replace("\r", "\\r") if record.exc_info: exc_info = record.exc_info else: exc_info = (None, record.getMessage(), None) reporter = ExceptionReporter(request, *exc_info) data = reporter.get_traceback_data() location = f" at {request.path_info}" if request else "" heading = f"{data.get('exception_type', 'Report')}{location}" exception_value = data.get("exception_value", "No exception message supplied") fields = [ { "name": "Subject", "value": subject, "inline": True }, { "name": heading, "value": exception_value, "inline": False }, ] if request: if request.GET != {}: fields.append({ "name": "GET parameters", "value": str(dict(request.GET)), "inline": False, }) if request.POST != {}: fields.append({ "name": "POST parameters", "value": str(dict(request.POST)), "inline": False, }) json = { "embeds": [{ "title": "SC2 Ladder Exception", "fields": fields, "footer": { "text": "" }, }] } requests.post(settings.DISCORD_WEBHOOK, json=json)
def create_from_exception(self, exc_info=None, **kwargs): """ Creates an error log from an exception. """ if not exc_info: exc_info = sys.exc_info() exc_type, exc_value, exc_traceback = exc_info reporter = ExceptionReporter(None, exc_type, exc_value, exc_traceback) frames = varmap(shorten, reporter.get_traceback_frames()) if not kwargs.get('view'): # This should be cached modules = get_installed_apps() if settings.INCLUDE_PATHS: modules = set(list(modules) + settings.INCLUDE_PATHS) def iter_tb_frames(tb): while tb: yield tb.tb_frame tb = tb.tb_next def contains(iterator, value): for k in iterator: if value.startswith(k): return True return False # We iterate through each frame looking for an app in INSTALLED_APPS # When one is found, we mark it as last "best guess" (best_guess) and then # check it against SENTRY_EXCLUDE_PATHS. If it isnt listed, then we # use this option. If nothing is found, we use the "best guess". best_guess = None view = None for frame in iter_tb_frames(exc_traceback): try: view = '.'.join( [frame.f_globals['__name__'], frame.f_code.co_name]) except: continue if contains(modules, view): if not (contains(settings.EXCLUDE_PATHS, view) and best_guess): best_guess = view elif best_guess: break if best_guess: view = best_guess if view: kwargs['view'] = view data = kwargs.pop('data', {}) or {} if hasattr(exc_type, '__class__'): exc_module = exc_type.__class__.__module__ else: exc_module = None data['__sentry__'] = { 'exc': map(transform, [exc_module, exc_value.args, frames]), } if (isinstance(exc_value, TemplateSyntaxError) and \ isinstance(getattr(exc_value, 'source', None), (tuple, list)) and isinstance(exc_value.source[0], LoaderOrigin)): origin, (start, end) = exc_value.source data['__sentry__'].update({ 'template': (origin.reload(), start, end, origin.name), }) kwargs['view'] = origin.loadname tb_message = '\n'.join( traceback.format_exception(exc_type, exc_value, exc_traceback)) kwargs.setdefault('message', transform(force_unicode(exc_value))) return self.process(class_name=exc_type.__name__, traceback=tb_message, data=data, **kwargs)
def process_exception(self, request, exception): exc_type, exc_value, tb = sys.exc_info() reporter = ExceptionReporter(request, exc_type, exc_value, tb) html = reporter.get_traceback_html() return HttpResponse(html, status=500, content_type='text/html')
def get_exception_info(request): # We use Django's debug reporter, even though we are doing our own template. # This is because it has a great way of collecting all the useful info we # need, so no reason not to leverage it exc_info = sys.exc_info() reporter = ExceptionReporter(request, *exc_info) ctx = reporter.get_traceback_data() # This is a refactor of what the technical_500_template contains, just # doing the logic in Python rather than in a template. We collect all this # information so that we can log it. exception_type = ctx[ 'exception_type'] if 'exception_type' in ctx else "No exception supplied" exception_value = ctx[ 'exception_value'] if 'exception_value' in ctx else "No exception supplied" django_version = ctx["django_version_info"] python_executable = ctx['sys_executable'] python_version = ctx['sys_version_info'] python_path = ctx['sys_path'] server_time = str(ctx['server_time']) unicode_hint = None if 'unicode_hint' in ctx: unicdoe_hint = ctx['unicode_hint'] last_frame = None if 'lastframe' in ctx: frame_info = ctx['lastframe'] last_frame = "%s in %s, line %s" % (frame_info['filename'], frame_info['function'], frame_info['lineno']) loaders = [] if 'template_does_not_exist' in ctx and 'loader_debug_info' in ctx and ctx[ 'loader_debug_info']: for loader in ctx['loader_debug_info']: loader_info = {"name": loader['loader'], "templates": []} for tmpl in loader['templates']: loader_info['templates'].append({ "file": tmpl['name'], "exists": tmpl['exists'] }) loaders.append(loader_info) template_errors = None if 'template_info' in ctx and ctx['template_info']: template_info = ctx['template_info'] template_errors = { "name": template_info['name'], "line": template_info['line'], "message": template_info['message'] } exception_info = [] if 'frames' in ctx: frames = ctx['frames'] for frame in frames: frame_info = { "filename": frame['filename'], "function": frame['function'], "line": frame['lineno'], "context_line": frame['context_line'], "vars": [] } if 'vars' in frame: for var in frame['vars']: frame_info['vars'].append({ "variable": str(var[0]), "value": format(var[1]) }) exception_info.append(frame_info) request_info = { "path_info": request.path_info, "method": request.META['REQUEST_METHOD'], "url": request.build_absolute_uri(), "GET": {}, "POST": {}, "FILES": {}, "COOKIES": {}, "META": {} } if hasattr(request, "GET"): for key, value in request.GET.iteritems(): request_info['GET'][key] = format(value) if "filtered_POST" in ctx: for key, value in ctx['filtered_POST'].iteritems(): request_info['POST'][key] = format(value) if hasattr(request, "FILES"): for key, value in request.FILES.iteritems(): request_info['FILES'][key] = format(value) if hasattr(request, "COOKIES"): for key, value in request.COOKIES.iteritems(): request_info['COOKIES'][key] = format(value) if hasattr(request, "META"): for key, value in request.META.iteritems(): request_info['META'][key] = format(value) settings_info = {} for key, value in ctx['settings'].iteritems(): settings_info[key] = format(value) ctx['errorid'] = errorid = uuid.uuid4().hex full_info = dict(__time=datetime.datetime.now().isoformat(), __uuid=errorid, settings=settings_info, request=request_info, traceback=exception_info, stack=traceback.format_exc(exc_info[2]), last_frame=last_frame, template_loaders=loaders, template_errors=template_errors, unicode_hint=unicdoe_hint, exception_type=exception_type, exception_value=exception_value, django_version=django_version, python_version=python_version, python_executable=python_executable, python_path=python_path, server_time=server_time) return (errorid, ctx, full_info)
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 emit(self, record, *args, **kwargs): # original AdminEmailHandler "emit" method code (but without actually sending email) 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) # this is where original "emit" method code ends # construct slack attachment detail fields attachments = [ { 'title': subject, 'color': 'danger', 'fields': [ { "title": "Level", "value": record.levelname, "short": True, }, { "title": "Method", "value": request.method if request else 'No Request', "short": True, }, { "title": "Path", "value": request.path if request else 'No Request', "short": True, }, { "title": "User", "value": ((request.user.username + ' (' + str(request.user.pk) + ')' if request.user.is_authenticated else 'Anonymous') if request else 'No Request'), "short": True, }, { "title": "Status Code", "value": record.status_code, "short": True, }, { "title": "UA", "value": (request.META['HTTP_USER_AGENT'] if request and request.META else 'No Request'), "short": False, }, { "title": 'GET Params', "value": json.dumps(request.GET) if request else 'No Request', "short": False, }, { "title": "POST Data", "value": json.dumps(request.POST) if request else 'No Request', "short": False, }, ], }, ] # add main error message body # slack message attachment text has max of 8000 bytes # lets split it up into 7900 bytes long chunks to be on the safe side split = 7900 parts = range(math.ceil(len(message.encode('utf8')) / split)) for part in parts: start = 0 if part == 0 else split * part end = split if part == 0 else split * part + split # combine final text and prepend it with line breaks # so the details in slack message will fully collapse detail_text = '\r\n\r\n\r\n\r\n\r\n\r\n\r\n' + message[start:end] attachments.append({ 'color': 'danger', 'title': 'Details (Part {})'.format(part + 1), 'text': detail_text, 'ts': time.time(), }) # construct main text main_text = 'Error at ' + time.strftime("%A, %d %b %Y %H:%M:%S +0000", time.gmtime()) # construct data data = { 'payload': json.dumps({ 'main_text': main_text, 'attachments': attachments }), } # setup channel webhook webhook_url = settings.SLACK_WEBHOOK_URL # send it def func(): requests.post(webhook_url, data=data) r = asyncExec(func)
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 wrapped_contest_view(request, contestid=None, **kwargs): try: token_container.set_token( request.COOKIES.get(settings.SATORI_TOKEN_COOKIE_NAME, '')) except: token_container.set_token('') page_info = None try: if contestid is not None: try: page_info = Web.get_page_info(Contest(int(contestid))) except: page_info = Web.get_page_info() raise else: page_info = Web.get_page_info() page_info.url = urlquote(request.path) res = func(request, page_info, **kwargs) if request.COOKIES.get(settings.SATORI_TOKEN_COOKIE_NAME, '') != token_container.get_token(): res.set_cookie(settings.SATORI_TOKEN_COOKIE_NAME, token_container.get_token(), domain=settings.SATORI_TOKEN_COOKIE_DOMAIN, path=settings.SATORI_TOKEN_COOKIE_PATH, secure=settings.SATORI_TOKEN_COOKIE_SECURE or None, httponly=settings.SATORI_TOKEN_COOKIE_HTTPONLY or None) return res except (TokenInvalid, TokenExpired): res = HttpResponseRedirect( reverse('login') + '?redir=' + urlquote(request.path)) res.set_cookie(settings.SATORI_TOKEN_COOKIE_NAME, '') return res except AccessDenied: if page_info and not page_info.role: return HttpResponseRedirect( reverse('login') + '?redir=' + urlquote(request.path)) if request.method == 'POST': info = 'You don\'t have rights to perform the requested action.' else: info = 'You don\'t have rights to view the requested object.' res = render_to_response('error.html', { 'page_info': page_info, 'message': 'Access denied', 'info': info }) res.status_code = 403 return res except ArgumentNotFound: res = render_to_response( 'error.html', { 'page_info': page_info, 'message': 'Object not found', 'info': 'The requested object does not exist.' }) res.status_code = 404 return res except TTransportException: res = render_to_response( 'error.html', { 'page_info': page_info, 'message': 'Server error', 'info': 'Communication with the core server failed.' }) res.status_code = 500 return res except Exception as e: traceback.print_exc() if settings.DEBUG: reporter = ExceptionReporter(request, *sys.exc_info()) detail = reporter.get_traceback_html() detail2 = [] in_style = False for line in detail.split('\n'): if line.startswith(' </style'): in_style = False if line == ' #summary { background: #ffc; }': line = ' #summary { background: #eee; }' if in_style: line = ' #content ' + line if line.startswith(' <style'): in_style = True detail2.append(line) detail = '\n'.join(detail2) else: detail = '' res = render_to_response( 'error.html', { 'page_info': page_info, 'message': 'Internal server error', 'info': 'The server encountered an internal error.', 'detail': detail }) res.status_code = 500 return res