2011-03-02 6 views
0

Python 로깅의 HTTPHandler를 사용하여 고객 django 앱에 메시지를 푸시하는 데 몇 가지 문제가 있습니다. 필자는 필자의 인프라의 일부인 별도의 데몬을 사용하여 로그를 장고로 푸시하여 모든 것을 한 곳에서 얻을 수있게했습니다.파이썬 로깅 HTTPHandler 장고와의 깨진 파이프 오류

내가 사용 : 우분투 10.04 장고 1.2.4 PostgreSQL의 8.4 파이썬 2.6.5

을이이 뷰

# 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") 
에게 있습니다

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 

모델에게 있습니다

그리고 이것은 파이썬 코드에서 메시지를 보내기위한 호출입니다.

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 테이블에 여분의 행을 삽입하지 않았다. 그래서 나는 왜 이것이 현재 왜 일어나고 있는지 알지 못합니다.

나는 주변을 둘러 보았고 브로큰 파이프 추적은 문제가 아니라 브라우저가하는 것처럼 보였다. 하지만 브라우저를 사용하지 않아서 문제가 무엇인지 잘 모릅니다.

답변

0

예외로 인해 트랜잭션이 롤백하고 변경 사항을 실행 취소 할 수 있습니다. TransactionMiddleware을 사용하고 있습니까? 보기에 transaction.autocommit 데코레이터를 사용해보세요.

"깨진 파이프"오류가 계속 발생하면 그 이유를 알아내는 것이 좋습니다. HTTPHandler은 정상적인 POST를 수행하고 emit() 호출에서 응답 (사용자의보기에서 "확인")을 기다리고 이후까지 연결을 끊어서는 안됩니다.

httpliburllib을 사용하여 테스트 스크립트에서보기와 동일한 게시물을 시도 할 수 있습니다 (예 : HTTPHandler). 기본적으로 POST 데이터의 주소는 LogRecord's dict 인 것처럼 urlencode합니다.