E 'un buon approccio per raccogliere tutti i registri in memoria di una richiesta e scaricare una volta?

-1

Cosa voglio ottenere ?

Voglio scaricare tutti i registri in una singola riga che è stata raccolta durante una richiesta.

Perché lo sto facendo?

  • Approccio generale, ad esempio logger.info (), esegue il dump del file di accesso contemporaneamente quando si chiama la funzione. A causa di ciò, i log vengono confusi e non possono leggerli in sequenza poiché più thread utilizzano lo stesso file.

    By my approach, all logs will get collected in memory during request, will dump once just before we are returning response. Now I can read log easily as all logs belong to the request are in single line.

    Non è un buon approccio, quali possono essere i problemi?

  • Meno IO, sto memorizzando tutti i registri in memoria e scaricando immediatamente.

    What I believe IO contribute some part of response time, also IO is more costly then Memory. My approach somehow contributing to improve performance.

    Mi sbaglio?

Come sto cercando di fare?

Creazione di una classe di registrazione personalizzata che sarà singleton (per richiesta) sulla base del nome file del registro. Ha i suoi metodi proprio come il logger, ad esempio informazioni, errori, ecc. Ma memorizzerà solo i registri in memoria (raccogliendo i registri nell'elenco). Abbiamo bisogno di chiamare il metodo dump per effettuare il log in realtà (chiamando i metodi .info, .error quando l'intera richiesta è completa).

È un approccio sbagliato?

Frammenti di codice

Presupposti: Per raggiungere, apriremo multiprocessi solo in uwsgi e non nel multi-thread.

file: customlogging.py

import logging

class MyLogging(object):
    """This will return singleton object as per filename."""
    _instance = {}
    def __new__(cls, file_name):
        if not cls._instance.get(file_name):
            cls._instance = super(MyLogging, cls).__new__(cls, file_name)
        return cls._instance

    def __init__(self, file_name):
        self.logger = logging.getLogger(file_name')
        self.info_log = []
        self.error_log = []

    def log_append(self, logtype, msg):
        """
        Appending into log .
        """
        d = getattr(self, '%s_log' % logtype)
        d.append(msg)

    def info(self, msg):
        self.log_append('info', msg)

    def error(self, msg):
        self.log_append('error', msg)

    def dump(self):
        self.logger.info(",".join(self.info_log))
        self.logger.info(",".join(self.error_log))

file: app / abc.py

mylogger = MyLogging('app.abc')

def abc(request):
    mylogging.info(request.data)
    # doing something.
    mylogging.error("something")
    return httpresponse

file: utils.py

mylogger = MyLogging('app.abc')

def abc_util(arg):
    mylogging.info(arg)

file: middleware / dump_log.py

mylogger = MyLogging('app.abc')

class LogDumpMiddleware(object):
    def process_response(self, request, response):
        mylogger.dump()
        # Assumption: Multi Processes not multi threaded.
        mylogger._instance = None
        return response
    
posta Anurag 11.12.2016 - 08:54
fonte

1 risposta

2

Certo, qualcosa del genere funzionerà. Vorrei ancora sconsigliarlo.

Non hai bisogno di registri quando tutto funziona come previsto. Hai bisogno di registri per capire perché qualcosa è andato storto. Qualsiasi soluzione che rimandi alla scrittura in un file di log deve pensare a come il log verrà salvato nel caso in cui qualcosa di inaspettato si verifichi, ad esempio dimenticare di chiamare logger.dump() o incontrare un'eccezione prima di poter chiamare logger.dump() , o peggio di tutto bug all'interno del sistema di registrazione.

Rimandare le scritture del registro significa anche che il file di registro non è più esattamente in ordine cronologico. In effetti, lo schizzo del progetto memorizzerebbe solo il timestamp quando il registro è stato scaricato, non per ogni singolo elemento del registro. Ciò rende impossibile ricostruire la sequenza e i tempi effettivi degli eventi.

Un buon sistema di registrazione ha le seguenti proprietà:

  • Il registro è leggibile dalla macchina. Posso quindi scrivere script per analizzare un file di registro, ad es. estrai tutte le voci del registro che hanno avuto origine da una determinata richiesta, estrai tutte le voci del registro da un modulo specifico, converti il file di registro in un altro formato, ....

  • Se un file di registro è condiviso tra processi / thread: le scritture sul registro sono atomiche. Ciò garantisce che due voci di registro non siano mai interfogliate ma che vengano scritte una dopo l'altra nel file di registro. Senza questa proprietà, potresti visualizzare file di log corrotti e quindi potenzialmente inutili con alto carico.

  • Ogni voce del registro contiene abbastanza metadati per ricostruire la sequenza di eventi nel programma e per aiutare nel debug. Oltre al messaggio di log, questi campi potrebbero essere un timestamp con risoluzione almeno al millisecondo, il livello di log (errore / avvertenza / info / debug), file + riga dell'istruzione del registro, process- / thread- / request-ID, nome della classe e del metodo di inclusione, ....

  • Il file di log sarà comunque utile nel caso in cui il programma si blocchi improvvisamente. Vorresti sapere quali eventi portano a quel fallimento. Ciò significa che qualsiasi buffer di output deve essere svuotato dopo ogni voce di registro (nella funzione C: fflush ()). Se sei preoccupato per crash di sistema completi o interruzioni di corrente, dovrai anche assicurarti che i dati siano stati scritti su disco (in sistemi Posix: chiamata di sistema fsync ()).

  • La registrazione dovrebbe avere un sovraccarico minimo se il livello di registrazione è disattivato. Questo è in realtà abbastanza difficile da usare elegantemente in Python. La più grande fonte di lentezza legata al logging che ho visto non era da IO, proveniva da una formattazione non necessaria delle stringhe per voci di log che non sarebbero mai state scritte.

Se IO è attualmente il tuo fattore limitante, dovrai analizzarlo un po 'di più prima di giungere alla conclusione che dovresti mutilare il sistema di registrazione. Ad esempio, mi aspetto di vedere problemi di prestazioni dovuti a lunghi tempi di ricerca se si utilizzano unità disco fisso e si memorizzano il registro e un database sulla stessa unità fisica. Ti consiglio di profilare la tua candidatura per capire dove è trascorso il maggior tempo. È inoltre possibile eseguire il benchmark dell'applicazione in diversi livelli di registrazione: quanto è più veloce il programma quando una registrazione è disabilitata, rispetto alle normali impostazioni? È quindi possibile calcolare quanto tempo è possibile risparmiare differendo le scritture del registro.

    
risposta data 11.12.2016 - 12:38
fonte

Leggi altre domande sui tag