2014-09-15 20 views
7

Sto facendo un progetto in Scala e sto utilizzando slf4j con Logback per la registrazione. Ora, l'inizializzazione della registrazione non sembra essere thread-safe. Come soluzione, slf4j sta creando logger sostitutivi, ad esempio NoOp-logger, che ingoiano le istruzioni del registro eseguite durante l'inizializzazione. The slf4j homepage membri in materia: forestaleInizializzazione SLF4J - Registratori sostitutivi

sostitutivi stati creati durante la fase di configurazione di default del sistema di registrazione sottostante

sistemi di registrazione altamente configurabili come logback e log4j possono creare componenti che invocano forestale durante la loro inizializzazione. Vedere il problema LOGBACK-127 per un evento tipico. Tuttavia, poiché il processo di associazione con SLF4J non è ancora completato (poiché il sistema di registrazione sottostante non è stato ancora completamente caricato in memoria), non è possibile onorare tali richieste di creazione del logger.

Per evitare questo problema di gallina e uova, SLF4J crea logger sostitutivi durante questa fase (inizializzazione). Le chiamate fatte ai registratori sostitutivi durante questa fase vengono semplicemente abbandonate. Al termine dell'inizializzazione, il registratore sostitutivo delegherà le chiamate di registrazione all'implementazione del logger appropriato e funzionerà altrimenti come qualsiasi altro logger restituito da LoggerFactory.

Se è stato creato un qualsiasi registratore sostitutivo, SLF4J emetterà un elenco di tali registratori. Questo elenco ha lo scopo di farti sapere che tutte le chiamate di registrazione effettuate su questi logger durante l'inizializzazione sono state eliminate.

C'è anche un issue non ancora risolto che descrive il problema.

Per me, il problema si è verificato durante il test su come le parti dell'applicazione funzionano insieme. Le dichiarazioni di registro di un produttore, eseguite nel proprio thread, sono state perse perché inviate a un registratore sostitutivo. L'aggiunta di una dichiarazione di registro appena prima della creazione del thread di produzione sembrava aiutare a inizializzare il logger in tempo. Tuttavia, vorrei sapere se una chiamata arbitraria a LoggerFactory.getLogger come prima affermazione nell'applicazione garantisce che non accedo mai a un logger sostitutivo.

In breve, le mie domande sono:

  • fa LoggerFactory.getLogger (classOf [A]) un'istanza di tutti i registratori, o potrebbe essere che due più tardi, chiamate simultanee a LoggerFactory.getLogger (classOf [B ]) produrrà un registratore sostitutivo?

  • C'è un modo per ottenere una garanzia, vale a dire, per verificare, che un logger è stata inizializzata (non posso controllare il tipo di logger, dal momento che è nascosto dalla facciata slf4j) Modifica: In realtà, Ho appena capito che potrei essere in grado di controllare il tipo di logger. Potrebbero i seguenti pensieri portare a una soluzione utile ?:

    def logger(context: Class[_]) = { 
        log = LoggerFactory.getLogger(context) 
        if (log.isInstanceOf[SubstituteLogger]) logger(context) else log 
    

    Il problema che vedo con questo approccio è che esso dipende dalla classe specifica un'implementazione, vale a dire, NOPLogger SubstituteLogger.

Addendum: Non sono sicuro se questo è di importanza a questa domanda, ma sto avvolgendo il registratore slf4j in una classe che viene creata un'istanza per ogni contesto di registrazione (context = la classe che sta chiamando il logger).Inoltre, esiste un oggetto che crea istanze di questo wrapper, che viene passato come argomento implicito del costruttore a ogni classe che vuole fare il logging. Passo il logger come argomento piuttosto che loggarmi su un oggetto statico (o mixare in un tratto) per abilitare il passaggio di un logger speciale nei test di unità.

+0

Sono appena questo utilizzando Akka ... E 'stato perché l'inizializzazione logger è stato fatto più volte in concomitanza (prima volta l'accesso a un logger). Quindi l'aggiunta di un dummy log all'avvio dell'app lo ha risolto. – LMeyer

risposta

0

Mi sono imbattuto nello stesso problema perché dipendenze multiple portati con le proprie copie duplicate del NoOp Logger. La soluzione, nel mio caso è stato quello esplicitamente la depencency inhereted su slf4j-log4j12 via:

libraryDependencies = Seq(
    ... 
).map(_.exclude("org.slf4j", "slf4j-log4j12"))