Wie sende ich java.util.logging an log4j?

84

Ich habe eine vorhandene Anwendung, die die gesamte Protokollierung gegen log4j durchführt. Wir verwenden eine Reihe anderer Bibliotheken, die entweder ebenfalls log4j verwenden oder sich gegen Commons Logging anmelden, wodurch log4j in unserer Umgebung unter dem Deckmantel verwendet wird. Eine unserer Abhängigkeiten protokolliert sogar gegen slf4j, was ebenfalls gut funktioniert, da es schließlich auch an log4j delegiert wird.

Jetzt möchte ich dieser Anwendung ehcache für einige Caching-Anforderungen hinzufügen. In früheren Versionen von ehcache wurde die Commons-Protokollierung verwendet, was in diesem Szenario perfekt funktioniert hätte. Ab Version 1.6-Beta1 wurde jedoch die Abhängigkeit von der Commons-Protokollierung aufgehoben und stattdessen durch java.util.logging ersetzt.

Da ich mit der integrierten JDK-Protokollierung, die mit java.util.logging verfügbar ist, nicht wirklich vertraut bin, gibt es eine einfache Möglichkeit, Protokollnachrichten an JUL zu protokollieren, die gegen log4j protokolliert werden, sodass ich meine vorhandene Konfiguration verwenden und für jede kommende Protokollierung einrichten kann von ehcache?

Wenn ich mir die Javadocs für JUL anschaue, könnte ich eine Reihe von Umgebungsvariablen einrichten, um zu ändern, welche LogManagerImplementierung verwendet wird, und diese möglicherweise verwenden, um log4js Loggerin die JUL- LoggerKlasse einzuschließen . Ist das der richtige Ansatz?

Ein bisschen ironisch, dass die Verwendung der integrierten JDK-Protokollierung in einer Bibliothek solche Kopfschmerzen verursachen würde, wenn (fast) der Rest der Welt stattdessen Bibliotheken von Drittanbietern verwendet.

matt b
quelle

Antworten:

37

Ein Ansatz, den ich erfolgreich verwendet habe, ist die Verwendung von slf4j als meine primäre Protokollierungs-API. Ich habe dann slf4j an log4j binden. Abhängigkeiten von Drittanbietern, die andere Frameworks (wie JUL) verwenden, können mit slf4j überbrückt werden .

überdenken
quelle
2
Guter Link, aber ich denke du
meintest
Das klingt nach einem guten Ansatz, außer dass ich ihn scheinbar nicht zum
matt b
2
Ich kann auch nicht glauben, dass eine so beliebte Bibliothek wie ehcache zu java.util.logging wechseln würde - scheint sehr ohne Kopf zu sein
matt b
1
@matt b, JUL ist in der Java-Laufzeit immer vorhanden, sodass die geringsten externen Abhängigkeiten erforderlich sind. In meinen Augen ist es jedoch ein echtes Beispiel für Code, der von Personen geschrieben wurde, die mit der Verwendung dieses Codes nicht vertraut sind. Das Konfigurationssystem ist ziemlich unpraktisch.
Thorbjørn Ravn Andersen
1
Das Problem, das Sie haben, ist, dass die Protokollierungsleistung erschreckend ist, wenn Sie SLF4J mit JUL verbinden. Insbesondere führt jede von Ihnen erstellte Protokollzeile zu einer Ausnahme, um zu bestimmen, welcher Logger-Kontext verwendet werden soll. Das verursacht viel Overhead und verlangsamt Prozesse
Egwor
19

Wir verwenden SLF4J für unser aktuelles Projekt und es hat für uns sehr gut funktioniert. SLF4J wurde von Ceki Gülcü, dem Schöpfer von Log4J, geschrieben und hat wirklich gute Arbeit geleistet. In unserem Code verwenden wir die SLF4J-Protokollierungs-APIs direkt und konfigurieren SLF4J so, dass Aufrufe der Jakarta Commons Logging- (JCL), java.util.logging- (JUL) und Log4J- APIs alle mit den SLF4J-APIs verbunden werden. Wir müssen dies tun, da wir wie Sie Bibliotheken von Drittanbietern (Open Source) verwenden, die unterschiedliche Protokollierungs-APIs ausgewählt haben.

Im unteren Bereich von SLF4J konfigurieren Sie es für die Verwendung einer bestimmten Logger-Implementierung. Es wird mit einem internen oder "einfachen" Logger geliefert, den Sie mit Log4J, JUL oder Logback überschreiben können . Die Konfiguration erfolgt einfach durch Ablegen verschiedener JAR-Dateien in Ihrem Klassenpfad.

Ursprünglich haben wir die Logback-Implementierung verwendet, die ebenfalls von Ceki Gülcü geschrieben wurde. Das ist sehr mächtig. Wir haben uns dann jedoch entschlossen, unsere Anwendung auf dem Glassfish Java EE-Anwendungsserver bereitzustellen, dessen Protokollanzeige JUL-formatierte Nachrichten erwartet. Also habe ich heute von Logback zu JUL gewechselt und in nur wenigen Minuten zwei Logback-Gläser durch ein SLF4J-Glas ersetzt, das es mit der JUL-Implementierung verbindet.

Wie bei @overthink würde ich die Verwendung von SLF4J in Ihrem Setup wärmstens empfehlen.

Jim Ferrans
quelle
8
Wie oft muss Ceki ein Protokollierungs-Framework / eine Protokollierung neu erfinden?
mP.
@mP: Die Protokollierung mag nicht glamourös sein, aber es ist ein entscheidender Bedarf an umfangreicher kommerzieller Software. Und SLF4J löst das Problem der Integration von Code, der unterschiedliche Protokollierungsframeworks verwendet (was Sun durch die Entscheidung, java.utils.logging zu entwickeln, anstatt Log4J zu übernehmen, dringlicher gemacht hat).
Jim Ferrans
3
@mP, slf4j war notwendig, weil Sun schlechte Arbeit mit JUL geleistet hat. Logback ist eine Abzweigung von log4j, kein neues Projekt.
Thorbjørn Ravn Andersen
3
Ich fand Logback notwendig, wenn es für nichts anderes nicht Apache ist und es tatsächlich dokumentiert ist.
Spencer Kormos
13

Es gibt eine einfachere Alternative als SLF4J, um JUL mit log4j zu verbinden, siehe http://people.apache.org/~psmith/logging.apache.org/sandbox/jul-log4j-bridge/examples.html

Sie müssen nur die jul-log4j-Brücke in den Klassenpfad einfügen und eine Systemeigenschaft hinzufügen:

-Djava.util.logging.manager=org.apache.logging.julbridge.JULBridgeLogManager

jul-log4j-bridge befindet sich nicht in Maven Central und kann aus diesem Repository abgerufen werden:

<repository>
  <id>psmith</id>
  <url>http://people.apache.org/~psmith/logging.apache.org/repo</url>
  <releases>
    <enabled>false</enabled>
  </releases>
</repository>

und dann verwendet mit:

<dependency>
  <groupId>org.apache.logging</groupId>
  <artifactId>apache-jul-log4j-bridge</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <scope>test</scope>
  <exclusions>
    <exclusion>
      <groupId>log4j</groupId>
      <artifactId>apache-log4j-component</artifactId>
    </exclusion>
  </exclusions>
</dependency>

Es ist auch möglich, es aus Quellen mit den folgenden Schritten neu zu erstellen:

  1. svn co http://svn.apache.org/repos/asf/logging/sandbox/jul-to-log4j-bridge/
  2. Bearbeiten Sie die Datei pom.xml, ersetzen Sie die Abhängigkeit von log4j: log4j: 1.2.15 durch log4j: apache-log4j-extras: 1.2.17 und entfernen Sie die Abhängigkeit von der apache-log4j-Komponente
  3. MVN-Paket
Emmanuel Bourg
quelle
4
Ich denke, es ist einfacher, weil es möglich ist, ohne Ihren Code zu ändern. Sie müssen nur eine Systemeigenschaft hinzufügen. SLF4J schlägt noch keinen ähnlichen Mechanismus vor. Sie ändern entweder den Code oder die logging.propertiesDatei.
Emmanuel Bourg
1
Dies existiert leider nicht in log4j2 :(
BeepDog
JulLog4jBridge.assimilate();o_0
Bastian Voigt
2
WARNUNG! jul-log4j-bridgeverwendet das nie freigegebene apache-log4j-companionsBundle (ein Backport von den verlassenen log4j 1.3). Es wird dir schwer fallen, es zu bauen. Natürlich wird auch die Brücke selbst vor der Freigabe aufgegeben.
ivan_pozdeev
@ivan_pozdeev Guter Punkt, danke. Ich habe Anweisungen zum Erstellen hinzugefügt.
Emmanuel Bourg
9

OKTOBER 2014

Seit Version 2.1 von log4j existiert die Komponente log4j-jul, die genau dies ermöglicht. Wenn Sie jedoch log4j 1 verwenden, muss ein Upgrade auf log4j2 möglich sein, um diesen Ansatz verwenden zu können.

JDK-Protokollierungsadapter

Klasse LogManager

Migrieren Sie von log4j 1.x zu log4j 2

AdrianRM
quelle
2
Ab sofort (Mitte 2018) sollte dies die akzeptierte Antwort sein
rmuller
Für zukünftige Leser: Ich bestätige, dass dies funktioniert. Fügen Sie dies also grundsätzlich (1) zu Ihrem pom mvnrepository.com/artifact/org.apache.logging.log4j/log4j-jul hinzu und (2) fügen Sie die Systemeigenschaft im ersten Link hinzu (z. B. fügen Sie in den JVM-Parametern -Djava hinzu. util.logging.manager = org.apache.logging.log4j.jul.LogManager)
Hossam El-Deen
3

Ich glaube, die slf4j-Site verfügt über eine Brücke zum Übergeben von java.util.logging-Ereignissen über slf4j (und damit an log4j).

Ja, der SLF4J-Download enthält jul-to-slf4j, von dem ich glaube, dass es genau das tut. Es enthält einen JUL-Handler zum Übergeben von Datensätzen an SLF4J.

araqnid
quelle
2

@Yishai - Danke, dass du den Link zu meinem Wiki gepostet hast. Das dortige Beispiel leitet JUL an Log4J weiter und ich habe es einige Jahre lang in einem Produktionssystem ausgeführt. JBoss 5.x leitet JUL bereits an Log4J weiter, daher habe ich es beim Upgrade entfernt. Ich habe eine neuere, die zu SLF4J umleitet, die ich jetzt für einige Dinge verwende. Ich werde das posten, wenn ich eine Chance bekomme.

SLF4J hat es jedoch bereits:

http://mvnrepository.com/artifact/org.slf4j/jul-to-slf4j

Joshua Davis
quelle