2013-07-01 9 views
11

Log4j2 verwendet auch Herunterfahren-Hooks, um seine Dienste zu beenden. Aber natürlich möchte ich den gesamten Lebenszyklus meiner Anwendung protokollieren - Herunterfahren inbegriffen. Mit Log4j war das kein Problem. Jetzt scheint es unmöglich zu sein. Die Protokollierung wird beendet, während meine Anwendung noch daran arbeitet. Hat jemand Hoffnung für mich?Wie loggen Sie sich in Shutdown-Hooks mit Log4j2 ein?

Mit freundlichen Grüßen Martin

+0

Logging, oder in Abhängigkeit von anderen Diensten in Shutdown-Hooks, war die ganze Zeit schlechte Praxis, und jetzt holt es auf. –

+0

@MarkoTopolnik Wenn es eine schlechte Übung ist, wie Sie sagen, was schlagen Sie vor, wenn die Ausgabe eines Shutdown-Hook-Threads eine Aufzeichnung/Protokollierung benötigt? – vegemite4me

+0

Da im Shutdown-Hook man nicht darauf zählen kann, dass irgendein Teil des initialisierten Zustands noch existiert, ist das einzige, was ich als halb-zuverlässig erachte, ein vollständig in sich geschlossenes Stück Code, das eine Datei erstellt und darauf schreibt. Ähnlich wie ein Core-Dump gemacht wird. –

Antwort

19

Ab 2.0-beta9 dies in xml jetzt konfigurierbar ist

<configuration ... shutdownHook="disable"> 

In Anbetracht seiner jetzt deaktiviert, ich glaube, ich brauche meine das Logging-System am Ende zur manuellen Abschaltung Herunterfahren des Hooks Allerdings konnte ich nicht ein Mittel gründlich die externe Schnittstelle finden, nur in der internen api

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

Haben Sie das jemals herausgefunden? – user671731

+1

Problem ist, dass die Shutdown-Hooks von Java parallel gestartet werden. Um wirklich zu gewährleisten, dass Sie sich überall einloggen können, müssen Sie vermeiden, dass Sie nur Ihre Hooks zu der gegebenen Runtime.getRuntime() addShutdownHook (Thread) -API hinzufügen, sondern einen eigenen Workflow erstellen, der log4j 2.0 manuell stoppt, nachdem alles nicht mehr läuft. Aber das Hauptproblem wurde gelöst, als Log4j den ShutdownHook-Trigger anbot. – Martin

+0

Ich stimme zu, dass Sie Ihren eigenen Workflow erstellen müssen. Normalerweise starte ich meine App auf Linux und stoppe über ein Signal an die JVM, also ist ein Shutdown-Hook für diesen Zweck geeignet (ich habe das Code-Snippet aktualisiert, um diesen Kontext anzuzeigen).Ich konnte keine ShutdownHookTrigger-Referenzen nach einem kurzen Google finden, würde es Ihnen etwas ausmachen, zu verlinken? – Chomeh

7

antwortete ich im Grunde nur die gleiche Frage und ich hart werde ich meine Antwort hier teilen. Ich ermutige Sie, die complete answer available here zu lesen. Ich werde versuchen, hier eine Zusammenfassung zu geben und meine Antwort dem aktuellen Kontext anzupassen.

In der ersten Version stellte Log4j eine API bereit, um die Abschaltprozedur manuell aufzurufen. Aus Gründen, die wir nicht kennen, it was removed from the second version. Nun, der richtige Weg, dies zu tun (gemäß der nicht existenten Dokumentation), ist es, eine eigene Implementierung der ShutdownCallbackRegistry Schnittstelle bereitzustellen, die für das Herunterfahren verantwortlich ist.

vorgeschlagene Lösung

Was ich tat, um dieses Problem zu beheben, ist, dass ich meine eigene Version der ShutdownCallbackRegistry Schnittstelle implementiert. Es macht meistens die gleichen Dinge wie die Standardimplementierung, aber anstatt sich selbst als Shutdown-Hook für die JVM zu registrieren, wartet es, bis es manuell aufgerufen wird.

Sie können die komplette Lösung und die Anweisungen auf GitHub/DjDCH/Log4j-StaticShutdown finden und in Ihren eigenen Projekten verwenden. Grundsätzlich am Ende haben Sie nur so etwas wie dies in Ihrer Anwendung zu tun:

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(); 
     } 
    } 
})); 

ich nicht ohne Zweifel sagen, dass dies die perfekte Lösung ist und dass meine Implementierung ist perfekt, aber ich versuchte, um es richtig zu machen. Ich freue mich über Feedback von Ihnen, entweder wenn Sie diese Lösung passend finden oder nicht.

Verwandte Themen