2012-11-11 10 views
7

Ho un progetto abbastanza grande in Django, che è un framework abbastanza grande, e sto usando un numero ragionevolmente elevato di app, middleware, processori di contesto, ecc. La scala indica che quando una parte del codebase viene eseguita per richieste in cui non lo desidero, identificare il motivo per cui è stata eseguita è difficile. L'ispezione di codice dritto richiede troppo tempo, così come il single-stepping attraverso l'intera richiesta in un debugger.Tracciamento da un effetto alla sua causa in una grande base di codice Python

In questo caso particolare, il mio problema è che ricevo "Vary: Cookie" impostato su ogni risposta, compresi alcuni che voglio pesantemente memorizzati nella cache e dove non dovrei aver bisogno di alcun cookie. Sospetto, ma non so come provare, che alcuni middleware o context processor stiano accedendo a request.session anche quando non utilizza il risultato, anche se potrebbe essere un accesso indiretto, ad esempio tramite request.user. E naturalmente potrebbe essere qualcos'altro interamente.

In Python, come si traccia da un effetto ("l'intestazione di Vary è stata aggiunta alla risposta") alla sua causa in una base di codice di grandi dimensioni?

+1

Ciao. Non ho familiarità con Django, ma se hai bisogno di trovare cosa ha fatto 'A ['x'] = y' e' A' non è un oggetto incorporato, puoi semplicemente sostituire A .__ setitem__ con il tuo che sarà controlla se l'intestazione "Vary: Cookie" è comparsa dopo l'esecuzione di '__setitem__', e in tal caso, stampa stack di chiamate che ti guideranno alla cosa che lo ha causato. Un'altra variante è scrivere un debugger che eseguirà il programma riga per riga e controllerà ogni volta, se l'intestazione di cui hai bisogno è stata aggiunta ad un particolare oggetto. –

+0

Grazie, @alex_jordan, è un buon inizio. Come si stampa lo stack di chiamata in modo programmatico? E in questo caso credo che l'intestazione sarebbe aggiunta se un flag è impostato altrove, quindi lo stack di chiamate mi dirà quale flag lo ha attivato; ma posso rintracciare le assegnazioni di campo per trovare quando è stata impostata la bandiera? Infine, gli oggetti in questione sono assegnati per richiesta. Posso applicare la patch della classe da cui provengono per fare questo per tutte le istanze? –

+0

Jamey, la soluzione fornita di seguito fa proprio questo e utilizza la segnalazione degli errori di django in modo da non doversi preoccupare dei dettagli della stampa della traccia dello stack. – BenTrofatter

risposta

3

Ecco un pensiero: patch di scimmia la classe HttpResponse di django in modo che il suo metodo __setitem__ sollevi un'eccezione se l'intestazione impostata è Vary. Puoi occupartene da un middleware altrimenti inutile quando viene creato. Dovrebbe darti un bel traceback dalla linea che sta impostando l'intestazione.

class MonkeyPatchMiddleware(object): 

    def __init__(self): 
     from django.http import HttpResponse 

     original_set_item = HttpResponse.__setitem__ 

     def __setitem__(self, header, value): 
      if header == "Vary": 
       raise ValueError 
      original_set_item(self, header, value) 

     HttpResponse.__setitem__ = __setitem__ 

Installa il middleware come la prima cosa nel tuo stack middleware nel tuo file di impostazioni django.

+0

Grazie! Ho trovato più comodo provare questo in 'views.py 'della mia app piuttosto che aggiungere un middleware. Il traceback mi ha detto che era 'SessionMiddleware.process_response' che stava chiamando' patch_vary_headers', ma poi per scoprire perché, avevo bisogno di scoprire cosa stava impostando 'request.session.accessed'. Scimmia patching in 'SessionBase.accessed = proprietà (lambda self: False, raise_on_true)' mi ha ottenuto un traceback con la vera causa principale. –

Problemi correlati