Requisiti:
- La mia applicazione è sensibile alla latenza. La responsività a livello di millisecondo è importante. Non sempre, ma quando agisce, deve essere veloce.
- La mia applicazione deve registrare informazioni su ciò che è stato fatto in quei momenti.
- La scrittura effettiva dei log non deve essere così veloce, solo le azioni.
- Tuttavia, i file di registro devono essere scritti a velocità umana, in altre parole, non posso impostare
immediateFlush
su falso.
- Tuttavia, i file di registro devono essere scritti a velocità umana, in altre parole, non posso impostare
Quindi, ovviamente, alcuni tipi di registrazione vengono trasferiti su un altro thread. Sto usando logback come framework, ma per certi tipi di messaggi di log voglio comunque scaricare il lavoro su un altro thread.
Ecco come funziona attualmente il sistema:
- Ogni parte del sistema sensibile alla latenza riceve una particolare interfaccia di logger iniettata. Ognuno di questi metodi di log ha una firma specifica per il tipo di cose che so che il logger dovrà registrare.
- Un'implementazione
SimpleLogger
viene scritta per ogni caso. Questo scrive sul registro sullo stesso thread. - Ho anche scritto un
ThreadedLogger
che implementa TUTTE le interfacce di logging e ottiene l'implementazione di un logger di "backing" iniettato per ogni tipo di logger. - Ogni volta che viene chiamato un metodo di registro in
ThreadedLogger
, esso avvolge la richiesta inSomeLogObject implements LogCommand
, getta l'oggetto inLinkedBlockingQueue
e restituisce. Questo è simile al schema Comando Go4- C'è un thread di consumo che blocca su
BlockingQueue.take()
in attesa di entrare oggetti log. Quando lo fanno, chiamaLogCommand.execute()
, che chiama il metodo appropriato nel backupLogger
inThreadedLogger
.
- C'è un thread di consumo che blocca su
- Attualmente le implementazioni
LogCommand
sono molto stupide. Chiamano semplicemente il metodo appropriato nel logger corretto iniettato.
Sto cercando di decidere se devo refactoring questo sistema. Attualmente, se ho bisogno di creare un nuovo posto per fare questi log scaricati, devo creare:
- Una nuova interfaccia
- Una nuova implementazione di questa interfaccia
- Due nuovi collegamenti DI (uno per il logger semplice, uno per il
ThreadedLogger
backer) - Una nuova implementazione
LogCommand
- Un nuovo metodo per creare questo oggetto
LogCommand
- Codice per l'iniezione e la memorizzazione come campo il logger appropriato in
ThreadedLoggger
Mi sembra che sarebbe molto più semplice scaricare la creazione di LogObject
sui thread chiamanti, ma sono preoccupato che sto esponendo troppo del funzionamento interno del sistema di log se lo faccio quello. Non che questo sia necessariamente un problema, ma sembra impuro. Un'altra possibilità sarebbe quella di combinare la funzionalità delle implementazioni del logger semplice con i rispettivi oggetti log, in modo che gli oggetti cambino da "I am a object that logging when date data log" a "I am a log event che sa come registrare me stesso ", e questi oggetti possono essere creati da una fabbrica di log.