Регистрация Python HTTPHandler Ошибка сломанной трубы с django

У меня есть несколько проблем с использованием HTTPHandler ведения журнала python для отправки сообщений в клиентское приложение 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 pipe не является проблемой, просто это то, что делают браузеры. Но я не использую браузер, поэтому я не уверен, в чем проблема.


person Mark Lakewood    schedule 02.03.2011    source источник


Ответы (1)


Возможно, исключение вызывает откат транзакции и отмену ваших изменений. Вы используете TransactionMiddleware? Вы можете попробовать декоратор transaction.autocommit в своем представлении.

Если ошибка «сломанная труба» повторяется, стоит выяснить, почему. HTTPHandler выполняет обычный POST и ожидает ответа («ОК» с вашей точки зрения) в своем вызове emit(), и он не должен разрывать соединение до тех пор, пока это не произойдет.

Вы можете попробовать сделать эквивалентную публикацию для вашего представления из тестового скрипта, используя httplib и urllib, как это делает сам HTTPHandler. По сути, просто urlencode dict для данных POST, как если бы это был LogRecord's dict.

person Vinay Sajip    schedule 02.03.2011