2017-06-23 61 views
3

尋找一種方法來在我views.pyDjango的錯誤記錄:添加請求頭,身體和用戶信息

與異常的堆棧跟蹤一起添加標題,正文和用戶的電子郵件地址,在我的錯誤日誌

經過幾個小時的網絡衝浪後,許多人建議編寫自己的中間件,有人建議將這類信息記錄到單獨的日誌中。然而,知道你的代碼出錯的地方解決了這個問題的一部分,確定了它影響到哪個可憐的靈魂,以及在這個異常期間發送了什麼請求數據,這在糾正這個問題方面有很長的路要走。將這些信息放在同一個日誌文件中對我來說很有意義。

目前在我的views.py,我有這個簡單的設置:

from django.db.models import Min, Max, Q, F, Count, Sum 
from django.db import connection 
from django.conf import settings 
from django.http import HttpResponse, HttpResponseRedirect 
from myapp.models import * 
import logging 

logging.basicConfig(filename="errors.log", 
        level=logging.ERROR, 
        format='%(asctime)s: %(message)s') 


def random_view(request): 
    if request.user.is_authenticated() and request.user.is_active: 
     # generic view code goes here. 
    else: 
     return HttpResponse(status=401) 

此設置了一段時間運作良好。每次出現異常時,它都會註銷時間,異常錯誤消息和堆棧跟蹤。

我該如何添加request.META,request.user.id和request.body以及堆棧跟蹤?

任何建議都會有幫助。一個解決的答案,甚至更好!

謝謝

+0

你嘗試https://stackoverflow.com/questions/35152435/how-to-ignore-the-exception-which-are-generated-during-the-logging-in-python –

+0

我想你應該看看現有的解決方案,如哨兵https://stackoverflow.com/a/44688358/3627387 –

回答

3

我認爲您的日誌記錄問題的完整解決方案是實現中間件。中間件可以使用任何類型的視圖實現,而不管它是基於類的視圖,基於函數的視圖還是來自DRF的APIView。

您可以定義完整日誌記錄的中間件。請確保您將中間件認證的中間件後,適當地 -

MIDDLEWARE = [ 
    ..., 
    'django.contrib.auth.middleware.AuthenticationMiddleware', 
    ..., 
    'path.to.your.middleware.LogMiddleware' 
] 

在日誌中間件,你將有機會獲得請求和響應。您可以通過記錄器存儲請求,用戶(如果通過身份驗證)和所有來自請求的META屬性,或者您可以根據需要將其存儲在數據庫中。雖然,請注意,在數據庫中存儲需要付出代價。您可以通過閱讀Django middleware documentation來了解如何編寫中間件。

import traceback 

class LogMiddleware(): 
    def __init__(self, get_response): 
     self.get_response = get_response 

    def __call__(self, request): 
     try: 
      return self.get_response(request) 
     except: 
      if request.user.is_authenticated(): 
       # Log the user 
      path = request.get_full_path() # Get the URL Path 
      tb = traceback.format_exc() # Get the traceback 
      meta = request.META # Get request meta information 
      # Log everything 
      raise # Raise exception again after catching 

你可以閱讀從HttpRequest Django文檔目前所有的元屬性。讓我知道你是否需要澄清這一點。

2

我會在這裏使用一個裝飾。直切到代碼...

import logging 
from functools import wraps 
from django.http import HttpResponse, HttpRequest 

logging.basicConfig(filename="errors.log", 
        level=logging.ERROR, 
        format='%(asctime)s: %(message)s') 
log = logging.getLogger(__name__) 

def log_exceptions(wrapped): 
    @wraps(wrapped) 
    def wrapper(*args, **kwargs): 
     try: 
      return wrapped(*args, **kwargs) 
     except: 
      # log and re-raise 
      request = args[0] if len(args) > 0 and isinstance(args[0], HttpRequest) else None 
      msg = ("\nuser.id/email: {}/{}\nMETA: {}...\nbody: {}" 
        .format(request.user.id, 
          getattr(request.user, 'email','?'), 
          str(request.META)[:80], 
          request.body) 
        if request 
        else "not a HttpRequest") 
      log.exception(msg) 
      raise 
    return wrapper 

@log_exceptions 
def random_view(request): 
    raise ValueError("simulate a crash") 
    if request.user.is_authenticated() and request.user.is_active: 
     return HttpResponse('hi') 
     # generic view code goes here. 
    else: 
     return HttpResponse(status=401) 

和errors.log應抓住像

2017-06-27 20:48:09,282: 
user.id/email: 1/[email protected] 
META: {'SESSION_MANAGER': 'local/acb:@/tmp/.ICE-unix/4255,unix/acb:/tmp/.ICE-unix/4255... 
body: b'' 
Traceback (most recent call last): 
    File "/home/rod/pyves/rangetest/rangetest/data/views.py", line 14, in wrapper 
    return wrapped(*args, **kwargs) 
    File "/home/rod/pyves/rangetest/rangetest/data/views.py", line 31, in random_view 
    raise ValueError("simulate a crash") 
ValueError: simulate a crash 

注意,你也可能會看到在你的errors.log Django的崩潰日誌爲好。您可以使用Django的文檔將日誌拆分爲單獨的文件,但仍然複雜logging config

相關問題