把 Django 的异常自动发送到 Trac,使其在 Trac 上生成 Ticket

需求是这样的,当一个django应用中抛出未被捕获的异常时,希望有个中间件可以提取这个异常的一些重要信息,并把这些信息告诉开发者或是维护人员。

可以想到的一些方法是,报警邮件,log记录等,在查了一些资料后发现,利用django的middleware可以和现在比较流行的trac结合起来,达到的效果是这样的,django这边抛出异常,通过middleware收集信息,然后利用python的xmlrpclib和trac的xmlrpc插件,把在这些信息在trac上生成ticket。

一些关键的代码,首先是在现有的django中新建一个app,在这个app下新建一个models

import datetime
from django.db import models

class AutoTicket(models.Model):
    subject = models.CharField(max_length=100)
    message = models.CharField(max_length=5000)
    depth = models.IntegerField(default=1)
    time = models.DateTimeField(default=datetime.datetime.now)

    class Meta:
        app_label = "trac"

然后新建一个middleware

import sys
import xmlrpclib
import datetime
from django import http
from django.conf import settings
from trac.conf import TRAC_AUTOTICKET, TRAC_URL, TRAC_TIME_LIMIT, TRAC_TICKET_VERSION, TRAC_OWNER
from django.core import exceptions
from trac.models import AutoTicket

class TracTicketMiddleware(object):
    """ This middleware will catch exceptions and creates a ticket in an existing
    Trac environment.
    """

    IGNORE_EXCEPTIONS = (http.Http404, SystemExit, exceptions.PermissionDenied)

    def process_exception(self, request, exception):
        if not TRAC_AUTOTICKET:
            return
        if not TRAC_URL:
            return
        if isinstance(exception, self.IGNORE_EXCEPTIONS) or \
                exception in self.IGNORE_EXCEPTIONS:
            return

        try:
            subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
            try:
                request_repr = repr(request)
            except:
                request_repr = "Request repr() unavailable"

            message = "{{{\n%s\n}}}\n\n{{{\n%s\n}}}" % (self._get_traceback(sys.exc_info()), request_repr)
            attrs = {
                'type': 'defect/bug',
                'status': 'new',
                'priority': 'major',
                'version': TRAC_TICKET_VERSION,
                'owner': TRAC_OWNER,
                'milestone': 'ROMA 0.4.1',
            }
            try:
                autot = AutoTicket.objects.get(message=exception.message, depth=len(message.split('\n')))
                if datetime.datetime.now() - autot.time > datetime.timedelta(days=TRAC_TIME_LIMIT or 10):
                    server = xmlrpclib.ServerProxy(TRAC_URL)
                    server.ticket.create(subject, message, attrs)
            except AutoTicket.DoesNotExist:
                autot = AutoTicket(subject=subject, message=exception.message, depth=len(message.split('\n')))
                autot.save()
                server = xmlrpclib.ServerProxy(TRAC_URL)
                server.ticket.create(subject, message, attrs)
        except:
            pass

        return

    def _get_traceback(self, exc_info=None):
        "Helper function to return the traceback as a string"
        import traceback
        return '\n'.join(traceback.format_exception(*(exc_info or sys.exc_info())))

一些配置就不详细说了。


在trac这里,我们要做的是,为你的trac安装一个xmlrpc插件,链接如下 http://trac-hacks.org/wiki/XmlRpcPlugin ,然后在trac的admin页面上打开这个plugin,并把这个权限发放出去

一切都准备好了,其实调用是这样的

server = xmlrpclib.ServerProxy(TRAC_URL)

其中的TRAC_URL就是trac的根url+/rpc

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。