Miglior modello creativo per i logger in un sistema multi-thread?

6

Questa è una domanda di follow-up sulle mie passate domande: Pattern di concorrenza del logger nell'applicazione multithread

Come suggerito da altri, sto ponendo questa domanda separatamente.

Come l'apprendimento dall'ultima domanda. In un ambiente multi-thread, il logger dovrebbe essere reso thread-safe e probabilmente asincrono (dove nei messaggi vengono accodati mentre un thread in background scrive scrivendo il thread dell'oggetto richiedente). Il logger potrebbe essere signleton o può essere un logger per gruppo che è una generalizzazione di quanto sopra.

Ora, la domanda che sorge è come deve essere assegnato il logger all'oggetto? Ci sono due opzioni che posso pensare:

1. Oggetto che richiede il logger:

Ogni oggetto dovrebbe chiamare qualche API globale come get_logger() ? Tale API restituisce "il" singleton o il logger di gruppo. Tuttavia, ritengo che ciò implichi l'assunzione di un ambiente applicativo per implementare il logger, che credo sia una sorta di accoppiamento. Se lo stesso oggetto deve essere utilizzato da un'altra applicazione, anche questa nuova applicazione deve implementare tale metodo.

2. Assegna il logger attraverso alcune API conosciute L'altro approccio alternativo consiste nel creare un tipo di classe virtuale che viene implementata dall'applicazione in base alla propria struttura dell'app e assegnare l'oggetto a volte nel costruttore.

Questo è un metodo più generalizzato. Sfortunatamente, quando ci sono così tanti oggetti - e piuttosto un albero di oggetti che passa sugli oggetti logger ad ogni livello è abbastanza disordinato.

My question is there a better way to do this? If you need to pick any one of the above, which approach is would you pick and why?

Altre domande rimangono aperte su come configurarle:

  1. Come vengono assegnati i nomi degli oggetti o l'ID in modo da essere utilizzati per la stampa sui messaggi di registro (come i nomi dei moduli)

  2. In che modo questi oggetti trovano le proprietà appropriate (come i livelli di registro e altri parametri)

Nel primo approccio, l'API centrale deve affrontare tutte queste varietà. Nel secondo approccio, è necessario un lavoro aggiuntivo.

Quindi, voglio capire dalla reale esperienza delle persone, su come scrivere efficacemente il registratore in un tale ambiente.

    
posta Dipan Mehta 16.10.2012 - 06:11
fonte

1 risposta

3

Questa non è una domanda facile a cui rispondere in modo sintetico.

In primo luogo, l'approccio che scegli dipende da obiettivi e vincoli molto specifici. In che misura registrerai messaggi o attività oggetto? E sta registrando un'attività intrinseca (qualcosa che è una chiave, una responsabilità integrale degli oggetti, o è un'attività secondaria, davvero piacevole da avere, tenuta da libri)?

Ci sono situazioni in cui la registrazione è intrinseca e pervasiva, ma spesso è una preoccupazione secondaria (un'attività di mantenimento della contabilità). Questo suggerisce che non vuoi accoppiare il logger con forza ad ogni oggetto che stai monitorando.

Un approccio da considerare è qualcosa sulla falsariga di una coda di messaggi globali dell'applicazione o di un bus di servizio aziendale. Qualcosa che è più vicino alla prima alternativa piuttosto che alla seconda alternativa che hai suggerito.

Ogni oggetto a cui sei interessato nel tracciamento con un registratore produrrebbe messaggi specifici di oggetti o attività che implementano ciascuna un'interfaccia di messaggio comune che supporta le proprietà comuni a cui sei interessato nella registrazione di ogni oggetto nel registro per l'identificazione. In ogni oggetto o messaggio specifico dell'attività, definire e aggiungere i dettagli specifici a quella struttura del messaggio. Infine, invia il messaggio alla coda del listener dei messaggi dell'applicazione. Se è richiesta la conferma di ricezione, consegnarla al mittente, in modo che possa continuare. Generalmente in un sistema chiuso, ad host singolo, non è richiesta la conferma esplicita della ricezione del messaggio.

Nel processore di messaggi con scope dell'applicazione (disponibile globalmente nell'applicazione), si dovrebbero "registrare" i gestori di messaggi. Questo potrebbe essere fatto "pigramente", come necessario, o in maniera preventiva all'avvio, come parte del "bootstrap". Forse includerebbe un gestore generico che funziona su qualsiasi messaggio che riceve. Potrebbe avere un gestore per quel messaggio di logger comune. Può anche avere un gestore per diversi o tutti i messaggi specifici del logger, se altre attività devono verificarsi in concomitanza con quel messaggio. In ogni caso, l'elaboratore di messaggi accoderebbe in successione i messaggi, gestirà i messaggi con i gestori di messaggi registrati, li scarterà in modo appropriato e quindi catturerà il messaggio successivo.

Una parte dell'implicazione di un processore di messaggi con scope dell'applicazione in un'applicazione multithread è che l'unica garanzia per l'ordine dei messaggi è che l'ordine in cui il messaggio entra nella coda dei messaggi avrà un ruolo importante nell'ordine in cui appare in un registro particolare.

Esistono strategie per rendere l'ordine dei messaggi più deterministico, ma nessuno sarà perfetto in tutti i casi. Un modo è quello di aggiungere un sequencer di messaggi globale e 'get_next' dal sequencer quando si creano tutti i messaggi, quindi inserirli in una coda indicizzata e attendere fino alla rimozione della coda del messaggio successivo nella sequenza. Anche questo ha implicazioni, in particolare i messaggi persi o scartati che bloccano la coda dei messaggi.

    
risposta data 25.10.2012 - 18:56
fonte

Leggi altre domande sui tag