Python记录HTTPHandler使用django破坏管道错误

时间:2011-03-02 06:24:35

标签: python django logging httphandler

我在使用python日志记录的HTTPHandler将消息推送到客户django应用程序时遇到了一些问题。我有一个单独的守护进程,它是我的基础结构的一部分,我希望它将日志推送到django所以我有点在一个地方得到所有。

我正在使用: Ubuntu 10.04 Django 1.2.4 PostgreSQL 8.4 python 2.6.5

这是模型

from django.db import models

# Create your models here.


class application(models.Model):
    app_name = models.CharField(max_length= 20)
    description = models.CharField(max_length = 500, null=True)
    date = models.DateField()

    def __unicode__(self):
        return ("%s logs - %s") % (self.app_name, self.date.strftime("%d-%m-%Y"))

class log_entry(models.Model):
    application = models.ForeignKey(application)
    thread_name = models.CharField(max_length = 200,null = True)
    name = models.CharField(max_length = 200,null = True)
    thread = models.CharField(max_length=50, null = True)
    created = models.FloatField(null = True)
    process = models.IntegerField(null = True)
    args = models.CharField(max_length = 200,null = True)
    module = models.CharField(max_length = 256,null = True)
    filename = models.CharField(max_length = 256,null = True)
    levelno = models.IntegerField(null = True)
    msg = models.CharField(max_length = 4096,null = True)
    pathname = models.CharField(max_length = 1024,null = True)
    lineno = models.IntegerField(null = True)
    exc_text = models.CharField(max_length = 200, null = True)
    exc_info = models.CharField(max_length = 200, null = True)
    func_name = models.CharField(max_length = 200, null = True)
    relative_created = models.FloatField(null = True)
    levelname = models.CharField(max_length=10,null = True)
    msecs = models.FloatField(null = True)

    def __unicode__(self):
        return self.levelname + " - " + self.msg

这是视图

# Create your views here.
from django.shortcuts import render_to_response, get_list_or_404, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.views.decorators.csrf import csrf_protect, csrf_exempt

from inthebackgroundSite.log.models import log_entry, application
import datetime


@csrf_exempt
def log(request):
    print request.POST

    for element in request.POST:
        print ('%s : %s') % (element, request.POST[element])

    data = request.POST
    today = datetime.date.today()
    print today
    app = application.objects.filter(app_name__iexact = request.POST["name"], date__iexact=today)
    if not app:
        print "didnt find a matching application. adding one now.."
        print data["name"]
        print today
        app = application.objects.create(app_name = data["name"],
                                         description = None,
                                         date = today)
        app.save()
        if not app:
            print "after save you cant get at it!"
        newApplication = app

    print app
    print "found application"
    newEntry = log_entry.objects.create(application = app,
                                        thread_name = data["threadName"] ,
                                        name = data["name"],
                                        thread = data["thread"],
                                        created = data["created"],
                                        process = data["process"],
                                        args = "'" + data["args"] + "'",
                                        module = data["module"],
                                        filename = data["filename"],
                                        levelno = data["levelno"],
                                        msg = data["msg"],
                                        pathname = data["pathname"],
                                        lineno = data["lineno"],
                                        exc_text = data["exc_text"],
                                        exc_info = data["exc_info"],
                                        func_name = data["funcName"],
                                        relative_created = data["relativeCreated"],
                                        levelname = data["levelname"],
                                        msecs = data["msecs"],
                                        )
    print newEntry
    #newEntry.save()
    return HttpResponse("OK")

这是在python代码中调用发送消息。

import os

import logging
import logging.handlers
import time

if __name__ == '__main__':
    formatter = logging.Formatter("%(name)s %(levelno)s %(levelname)s %(pathname)s %(filename)s%(module)s %(funcName)s %(lineno)d %(created)f %(asctime)s %(msecs)d %(thread)d %(threadName)s %(process)d %(processName)s %(message)s ")
    log = logging.getLogger("ShoutGen")
    #logLevel = "debug"
    #log.setLevel(logLevel)    
    http = logging.handlers.HTTPHandler("192.168.0.5:9000", "/log/","POST")
    http.setFormatter(formatter)
    log.addHandler(http)

    log.critical("Finished MountGen init")
    time.sleep(20)    
    http.close()

现在我第一次发送带有空表的消息。它工作正常,创建一个新的应用程序行并创建一个新的日志消息。但是我第二次打电话给我,

<QueryDict: {u'msecs': [u'224.281072617'], u'args': [u'()'], u'name': [u'ShoutGen'], u'thread': [u'140445579720448'], u'created': [u'1299046203.22'], u'process': [u'16172'], u'threadName': [u'MainThread'], u'module': [u'logtest'], u'filename': [u'logtest.py'], u'levelno': [u'50'], u'processName': [u'MainProcess'], u'pathname': [u'logtest.py'], u'lineno': [u'19'], u'exc_text': [u'None'], u'exc_info': [u'None'], u'funcName': [u'<module>'], u'relativeCreated': [u'7.23600387573'], u'levelname': [u'CRITICAL'], u'msg': [u'Finished MountGen init']}>
msecs : 224.281072617
args : ()
name : ShoutGen
thread : 140445579720448
created : 1299046203.22
process : 16172
threadName : MainThread
module : logtest
filename : logtest.py
levelno : 50
processName : MainProcess
pathname : logtest.py
lineno : 19
exc_text : None
exc_info : None
funcName : <module>
relativeCreated : 7.23600387573
levelname : CRITICAL
msg : Finished MountGen init
2011-03-02
    [sql] SELECT ...
      FROM "log_application"
      WHERE (UPPER("log_application"."date"::text) = UPPER(2011-03-02)
             AND UPPER("log_application"."app_name"::text) = UPPER(ShoutGen))
    [sql] (5.10ms) Found 1 matching rows
[<application: ShoutGen logs - 02-03-2011>]
found application
    [sql] SELECT ...
      FROM "log_log_entry" LIMIT 21
    [sql] (4.05ms) Found 2 matching rows
    [sql] (9.14ms) 2 queries with 0 duplicates
    [profile] Total time to render was 0.44s
Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/django/core/servers/basehttp.py", line 281, in run
    self.finish_response()
  File "/usr/local/lib/python2.6/dist-packages/django/core/servers/basehttp.py", line 321, in finish_response
    self.write(data)
  File "/usr/local/lib/python2.6/dist-packages/django/core/servers/basehttp.py", line 417, in write
    self._write(data)
  File "/usr/lib/python2.6/socket.py", line 300, in write
    self.flush()
  File "/usr/lib/python2.6/socket.py", line 286, in flush
    self._sock.sendall(buffer)
error: [Errno 32] Broken pipe

并且没有额外的行插入到log_log_entry表中。所以我真的不知道为什么会发生这种情况。

我环顾四周,显然Broken管道追溯不是问题,只是浏览器所做的事情。但我没有使用浏览器,所以我不确定问题是什么。

1 个答案:

答案 0 :(得分:0)

可能是异常导致事务回滚并撤消更改。你在使用TransactionMiddleware吗?您可以在视图上尝试transaction.autocommit装饰器。

如果“破管”错误不断发生,那么值得找出原因。 HTTPHandler执行正常的POST并在其emit()调用中等待响应(“视图”中的“确定”),并且在此之前不应断开连接。

您可以尝试使用httpliburllib作为HTTPHandler本身从测试脚本向您的视图发送等效帖子。基本上,只需对POST数据进行urlencode dict,就像它是LogRecord's dict一样。