2013-07-01 13 views
11

Log4j2 utilizza anche hook di chiusura per terminare i suoi servizi. Ma ovviamente voglio registrarmi durante l'intero ciclo di vita della mia applicazione, incluso lo spegnimento. Con Log4j questo non è stato un problema. Ora sembra impossibile. La registrazione si interrompe, mentre la mia applicazione sta ancora lavorando su di essa. Qualcuno ha qualche speranza per me?Come accedere ai ganci di arresto con Log4j2?

migliori saluti Martin

+0

La registrazione o, a seconda di altri servizi in ganci di arresto, è stata una pratica scorretta per tutto il tempo, e ora sta recuperando il ritardo. –

+0

@MarkoTopolnik Se è una cattiva pratica come dici tu, cosa suggerisci di fare se l'output di un thread di hookdown ha bisogno di registrazione/registrazione? – vegemite4me

+0

Dato che nel gancio di arresto non è possibile contare su alcuna parte dello stato inizializzato per esistere ancora, l'unica cosa che vedo come semi-affidabile è un pezzo di codice completamente autonomo che crea un file e scrive su di esso. Simile al modo in cui viene creato un core dump. –

risposta

19

A partire dal 2.0-beta9 questo è ora configurabile in xml

<configuration ... shutdownHook="disable"> 

Considerando la sua ora disattivato, credo che ho bisogno di manualmente lo spegnimento del sistema di registrazione, alla fine del mio gancio di arresto. Tuttavia, non sono riuscito a trovare un modo approfondito l'interfaccia esterna, solo nel api interna

import org.apache.logging.log4j.LogManager; 
import org.apache.logging.log4j.core.config.Configurator; 
import org.apache.logging.log4j.core.LoggerContext; 
... 

public static void main(String[] args) { 
    final AnnotationConfigApplicationContext springContext = new AnnotationConfigApplicationContext(AppConfig.class) 

    Runtime.getRuntime().addShutdownHook(new Thread() { 
     public void run() { 
      //shutdown application 
      LOG.info("Shutting down spring context"); 
      springContext.close(); 

      //shutdown log4j2 
      if(LogManager.getContext() instanceof LoggerContext) { 
       logger.info("Shutting down log4j2"); 
       Configurator.shutdown((LoggerContext)LogManager.getContext()); 
      } else 
       logger.warn("Unable to shutdown log4j2"); 
     } 
    }); 

    //more application initialization 
} 
+0

lo hai mai capito? – user671731

+1

Il problema è che gli hook di shutdown di Java vengono avviati in parallelo. Quindi per assicurarti di poter accedere ovunque devi evitare di aggiungere i tuoi hook al dato Runtime.getRuntime(). AddShutdownHook (Thread) -API ma crea il tuo flusso di lavoro che arresta manualmente log4j 2.0 dopo che tutto è inattivo. Ma il problema principale è stato risolto quando Log4j ha offerto il trigger shutdownHook. – Martin

+0

Sono d'accordo sul fatto che è necessario creare il proprio flusso di lavoro. Di solito eseguo la mia app su linux e shutdown tramite un segnale alla JVM, quindi un hook di shutdown è adatto a questo scopo (ho aggiornato lo snippet di codice per mostrare questo contesto).Non sono riuscito a trovare riferimenti shutdownHookTrigger dopo un breve google, ti dispiacerebbe collegare? – Chomeh

7

ho praticamente appena risposto la stessa domanda e io duro io condividere la mia risposta qui. Vi incoraggio a leggere il complete answer available here. Cercherò di fornire un riassunto qui e adattare la mia risposta al contesto attuale.

Nella prima versione, Log4j forniva un'API per chiamare manualmente la procedura di arresto. Per ragioni di cui non abbiamo conoscenza, it was removed from the second version. Ora, il modo corretto di farlo (secondo la documentazione inesistente), è quello di fornire la propria implementazione dell'interfaccia ShutdownCallbackRegistry, che è responsabile della procedura di spegnimento.

Soluzione proposta

Quello che ho fatto per risolvere il problema è che ho implementato la mia versione dell'interfaccia ShutdownCallbackRegistry. Principalmente fa le stesse cose che fa l'implementazione di default, ma invece di registrarsi come un hook di shutdown per la JVM, aspetta che venga invocato manualmente.

È possibile trovare la soluzione completa e le istruzioni su GitHub/DjDCH/Log4j-StaticShutdown e utilizzarlo nei propri progetti. In sostanza, alla fine, devi solo fare qualcosa di simile nella vostra applicazione:

Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 
    @Override 
    public void run() { 
     try { 
      // Do your usual shutdown stuff here that need logging 
     } finally { 
      // Shutdown Log4j 2 manually 
      StaticShutdownCallbackRegistry.invoke(); 
     } 
    } 
})); 

Non posso dire senza alcun dubbio che questa è la soluzione perfetta e che la mia esecuzione è perfetta, ma ho provato farlo nel modo giusto Sarò lieto di ricevere feedback da voi, sia se trovate questa soluzione appropriata o meno.