2011-04-18 16 views
54

Sto utilizzando log4j per registrare l'errore e altre informazioni di sistema. ma vengono delle informazioni registrate due volte al livello INFO.log4j registrazione due volte

public static void main(final String... args) throws Exception { 

    LOGGER.info("program started"); 
    try { 
     // try body codes 
    } catch (Exception ex) { 
     LOGGER.info("program start-up failed.",ex); 
    } 
} 

tuttavia quando il programma si avvia o non ha le informazioni registrate due volte, qualcuno mi può aiutare a trovare ciò che potrebbe essere la ragione di questo.

+0

Potrebbe essere un problema di configurazione o un problema di inizializzazione. Dove inizializzi il registratore? Non chiami Logger.getLogger (SomeClass.class) due volte? Alcuni codici aggiuntivi potrebbero fornirci ulteriori informazioni per aiutarti. – MaSEL

risposta

75

Sembra che i messaggi vengano registrati una volta dal logger principale e nuovamente dal logger specifico in quanto è possibile che entrambe le appendici siano configurate (possono trovarsi in posizioni diverse, in un file di proprietà e quindi nel codice).

Questo può essere risolto impostando additività false sul logger. Log4j manual menziona l'additività nella sezione Appendici e Layout. Verificare che

+2

È così che dovresti * risolvere * o un cerotto mascherare un problema di configurazione più grande? –

+1

Senza il logger, non viene registrato nulla. Quando aggiungo il logger, viene registrato due volte. Quando imposto l'additività su false, viene registrato una volta. Cosa sta succedendo qui? –

+0

@DanielKaplan Se i logger hanno una struttura gerarchica, si. Parafrasando dal collegamento manuale, dì che vuoi solo messaggi ERROR per tutte le classi tranne Foo, di cui vuoi vedere tutti i messaggi. Avresti impostato l'additività del registratore Foo su false, quindi tutti i messaggi ERROR non proseguono fino a root e vengono nuovamente stampati. Senza additività, la configurazione sarebbe molto più complicata e meno manutenibile, quindi direi che è corretto. – whrrgarbl

29

Accetto con atlantis.

log4j.rootCategory=INFO, console 
log4j.logger.org.hibernate=INFO 

Le suddette impostazioni di proprietà causeranno la doppia registrazione.

Tuttavia aggiungendo

log4j.additivity.org.hibernate=false 

risolto il problema.

Check out page 62 di questo libro. http://books.google.com/books?id=hZBimlxiyAcC&printsec=frontcover#v=onepage&q&f=false

+6

non dovrebbe essere 'falso', non 'vero'? –

+0

Google books sembra nascondere in modo casuale determinate pagine. [Ecco qui] (http://veerasundar.com/blog/2009/08/log4j-tutorial-additivity-what-and-why/) un post sul blog che ho trovato utile. Include un esempio più ampio che include alcune voci ** log4j.category ... ** –

28

Per coloro formato XML uso:

<logger name="package.class" additivity="false"> 
    <level value="info" /> 
    <appender-ref ref="file" /> 
    <appender-ref ref="console" /> 
</logger> 

Nota: per impostazione predefinita, Abbattitori hanno la loro bandiera additività impostata su true.

2

Se è possibile eseguire il programma con un debugger Java, inserire un punto di interruzione nel programma in cui si verifica una di queste doppie chiamate di registrazione.

Esaminare l'oggetto del logger nel debugger. Se è un org.apache.log4j.Logger (v 1.2.x), allora potrebbe avere un AppenderAttachableImpl. Puoi richiedere AppenderAttachableImpl per l'elenco di appender.

Se trovi più di un appender, questo potrebbe essere il problema e un indizio per risolverlo.

2

Basta semplicemente aggiungere

logger.setadditivity(false); 

al codice (Reference).

Abbiamo due risultati nella console, perché gli appendici non sono singleton, sono additivi. Significato, una categoria eredita tutti gli appendici dai suoi antenati (per impostazione predefinita). Se aggiungiamo un appender a una categoria e esso scrive nello stesso flusso sottostante (console, stesso file, ecc.) Come altri utenti, lo stesso messaggio di log comparirà due volte (o più) nel registro. Inoltre, se due categorie in una gerarchia sono configurate per utilizzare lo stesso nome di appender, Log4j scriverà due volte su quell'appender. Configurato per quella categoria

0

Una possibile alternativa alla regolazione della proprietà additivity consiste nell'esaminare i registri dal più specifico al più generico. Nell'esempio seguente, ci si aspetterebbe di vedere la doppia registrazione nella console per tutti gli eventi di registro che si verificano in foo.bar.LoggingExampleClass. Sarebbe sicuro rimuovere l'appender Console extra da foo.bar.LoggingExampleClass Logger poiché è già coperto dal logger principale.

<Logger name="foo.bar.LoggingExampleClass" level="DEBUG"> 
    <AppenderRef ref="Console" /> <!-- THIS APPENDER COULD BE REMOVED --> 
    <AppenderRef ref="FooBarPackageLogging" /> 
</Logger> 

<Root level="WARN"> 
    <AppenderRef ref="Console" /> 
    <AppenderRef ref="MainLogFile" /> 
</Root> 

Non ci sono compromessi sia per l'approccio di regolazione dell'additività e l'approccio di regolazione appender. Disattivare l'additività potrebbe inavvertitamente impedire l'utilizzo di un appender del registratore di livelli generico desiderabile. Nell'esempio sopra, l'impostazione della proprietà additivity="false" su foo.bar.LoggingExampleClass Logger significherebbe che l'evento di registrazione non verrà aggiunto al file MainLog a cui si fa riferimento nel logger principale.

D'altra parte, basandosi su appenders genitore potrebbe essere problematico se i appenders genitore vengono modificate senza esaminare gli effetti sul logger più granulari. Ad esempio, supponiamo vi sia un requisito per cui gli eventi di registrazione foo.bar.LoggingExampleClass devono essere scritti sulla console. Attualmente sono nella configurazione di esempio di cui sopra a causa di additività, anche se viene rimosso l'appender della console del logger foo.bar.LoggingExampleClass. Tuttavia, se l'appender della console è stato rimosso dal logger principale senza ulteriori aggiustamenti, il requisito non sarebbe più soddisfatto.