PV168/Logování: Porovnání verzí

Z FI WIKI
Přejít na: navigace, hledání
(Simple Logging Facade for Java (SLF4J) [http://www.slf4j.org/])
Řádka 1: Řádka 1:
=== java.util.logging (JUL) [http://java.sun.com/j2se/1.5.0/docs/guide/logging/] ===
+
== Přehled ==
* ve standardním API až od JDK 1.4
+
* třída Logger (instance mají asociované jméno, jehož základ by měl tvořit název balíku, protože je na něm postavena hierarchie Loggerů)
+
* Úrovně (instance třídy Level) ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF
+
* Možnost implementace vlastního Filteru
+
* Připravené handlery pro paměť, OutputStream, soubor (včetně rotování), konzolu, IP socket (i více najednou)
+
* Připravené textové a XML formátování
+
* Podpora lokalizovaných zpráv přebíraných z ResourceBundle
+
* LogManager spravující všechny Loggery a jejich konfiguraci
+
  
Když neprovedu žádnou konfiguraci, JUL loguje od úrovně INFO na konzolu pomocí SimpleFormatter,
+
Logování je ukládání informací o událostech v programu, jehož účelem je v případě potřeby dohledání činnosti systému nebo diagnostikování chyby.
protože to je konfigurace v souboru <code>$JAVA_HOME/lib/logging.properties</code>.
+
  
Pokud to chci změnit, musím vyrobit soubor ''logging.properties'' s obsahem alespoň
+
V jazyce Java existují v podstatě tyto tři hlavní implementace logování:
+
#vypis pujde na konzolu
+
handlers=java.util.logging.ConsoleHandler
+
# handler propusti vsechno od finest
+
java.util.logging.ConsoleHandler.level=FINEST
+
# loggery propusti vsechno od finest
+
.level= FINEST
+
#
+
#java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
+
#java.util.logging.ConsoleHandler.formatter=java.util.logging.XMLFormatter
+
  
a při spuštění specifikovat jeho místo:
+
* Logback [http://logback.qos.ch/ http://logback.qos.ch/]
 +
* Log4J 1.2 [http://logging.apache.org/log4j/1.2/ http://logging.apache.org/log4j/1.2/]
 +
* JUL (java.util.logging) [http://docs.oracle.com/javase/7/docs/technotes/guides/logging/overview.html Java Logging Overview]
  
  java -Djava.util.logging.config.file=/home/nekdo/nekde/logging.properties
+
Aby nemusely být aplikace a knihovny psány pro konkrétní z těchto implementací, existují dvě ''obalovací'' logovací knihovny,
 +
které neposkytují implementaci logování, jen '''rozhraní''':
 +
 
 +
* Simple Logging Facade for Java (SLF4J) [http://www.slf4j.org/ http://www.slf4j.org/]
 +
* Jakarta Commons Logging (JCL) [http://commons.apache.org/logging/ http://commons.apache.org/logging/]
 +
 
 +
Logback a Log4J jsou od stejného autora, Logback je novější, rychlejší a flexibilnější než Log4J. Log4J bylo odjakživa lepší než JUL, ale JUL byl prosazen silou firmou Sun jako standardní součást JDK.
 +
 
 +
SLF4J je nástupce JCL, odstraňuje jeho problémy s classloadery.
 +
 
 +
=== Co mám použít ? ===
 +
 
 +
Ve zdrojových textech svých programů používejte rozhraní '''SLF4J'''.
 +
 
 +
Při nasazení programů používejte implementaci '''Logback'''.
 +
 
 +
Při využití cizích knihoven nebo programů, které používají něco jiného, využijte [http://www.slf4j.org/legacy.html SLF4J legacy bridge], tj. jcl-over-slf4j, log4j-over-slf4j, jul-to-slf4j bridge.
 +
 
 +
== Logovací rozhraní ==
 +
 
 +
=== Simple Logging Facade for Java (SLF4J) [http://www.slf4j.org/] ===
 +
* náhrada za nepodařené JCL
 +
* [http://www.theserverside.com/news/thread.tss?thread_id=39369 diskuze o SLF4J na The ServerSide]
 +
 
 +
Definuje úrovně
 +
 
 +
Použití
 +
<java>
 +
public class PbsCacheImpl implements PbsCache {
 +
 
 +
    final static Logger log = LoggerFactory.getLogger(PbsCacheImpl.class);
 +
//...
 +
 
 +
  // u jednoduchých výpisů stačí uvést řetězec a až dva argumenty pro nahrazení
 +
  log.debug("Server {} má {} položek",server,numItems);
 +
 
 +
  //u složitějších výpisů je vhodné předřadit if,aby se argumenty zbytečně nevyhodnocovaly
 +
  if(log.isDebugEnabled()) {
 +
    log.debug("Měla "+babka+" "+babkaPocetJablek+" a dědoušek jen "+dedaPocetJablek);
 +
  }
 +
 
 +
  // u vyjímek pak
 +
  try {
 +
    //...
 +
  } catch(Exception ex) {
 +
    log.error("Houstone, máme problém",ex);
 +
  }
 +
</java>
 +
 
 +
Pokud používáte projekt typu [[Maven]], přidáte knihovnu pro SLF4J přidáním této závislosti:
 +
<xml>
 +
<dependency>
 +
    <groupId>org.slf4j</groupId>
 +
    <artifactId>slf4j-api</artifactId>
 +
    <version>1.7.2</version>
 +
</dependency>
 +
</xml>
 +
 
 +
nebo u spustitelného projektu můžete
 +
<xml>
 +
<dependency>
 +
  <groupId>ch.qos.logback</groupId>
 +
  <artifactId>logback-classic</artifactId>
 +
  <version>1.0.7</version>
 +
</dependency>
 +
</xml>
 +
 
 +
=== Jakarta Commons Logging (JCL) [http://jakarta.apache.org/commons/logging/] ===
 +
* jednoduchá tenká knihovna, která sama o sobě logování neprovádí, ale za cenu mírného omezení funkcionality umožňuje jednotným zůsobem pracovat s mnoha různými logovacími mechanismy (m.j. s oběma výše uvedenými)
 +
* použití: LogFactory -> Log
 +
* problémy při použití rozdílných knihoven (class loader problems)
 +
* memory leaks
 +
* [http://www.qos.ch/logging/thinkAgain.jsp o nevýhodách Commons Logging]
 +
* [http://marc.theaimsgroup.com/?t=111161823700003&r=2&w=2 true story about JCL]
 +
* [http://marc.theaimsgroup.com/?l=log4j-dev&m=111175115425820&w=2 JCL no more!]
 +
 
 +
== Implementace logování ==
  
 
=== Log4j (LS) [http://logging.apache.org/log4j/docs/] ===
 
=== Log4j (LS) [http://logging.apache.org/log4j/docs/] ===
Řádka 71: Řádka 130:
 
</xml>
 
</xml>
  
=== Jakarta Commons Logging (JCL) [http://jakarta.apache.org/commons/logging/] ===
 
* jednoduchá tenká knihovna, která sama o sobě logování neprovádí, ale za cenu mírného omezení funkcionality umožňuje jednotným zůsobem pracovat s mnoha různými logovacími mechanismy (m.j. s oběma výše uvedenými)
 
* použití: LogFactory -> Log
 
* problémy při použití rozdílných knihoven (class loader problems)
 
* memory leaks
 
* rozčarování z JCL -> návrh JCL 2.0 (JCL+Log4j)
 
* vhodné spíše pro knihovny, než pro aplikace
 
* [http://www.qos.ch/logging/thinkAgain.jsp o nevýhodách Commons Logging]
 
* [http://marc.theaimsgroup.com/?t=111161823700003&r=2&w=2 true story about JCL]
 
* [http://marc.theaimsgroup.com/?l=log4j-dev&m=111175115425820&w=2 JCL no more!]
 
  
=== Simple Logging Facade for Java (SLF4J) [http://www.slf4j.org/] ===
+
=== java.util.logging (JUL) [http://java.sun.com/j2se/1.5.0/docs/guide/logging/] ===
* původně [http://logging.apache.org/log4j/docs/ugli.html Universal and Generic Logging Interface (UGLI)]
+
* ve standardním API od JDK 1.4
* náhrada za nepodařené [http://jakarta.apache.org/commons/logging/ JCL]
+
* třída Logger (instance mají asociované jméno, jehož základ by měl tvořit název balíku, protože je na něm postavena hierarchie Loggerů)
* [http://www.theserverside.com/news/thread.tss?thread_id=39369 diskuze o SLF4J na The ServerSide]
+
* Úrovně (instance třídy Level) ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF
 +
* Možnost implementace vlastního Filteru
 +
* Připravené handlery pro paměť, OutputStream, soubor (včetně rotování), konzolu, IP socket (i více najednou)
 +
* Připravené textové a XML formátování
 +
* Podpora lokalizovaných zpráv přebíraných z ResourceBundle
 +
* LogManager spravující všechny Loggery a jejich konfiguraci
  
Použití
+
Když neprovedu žádnou konfiguraci, JUL loguje od úrovně INFO na konzolu pomocí SimpleFormatter,
<java>
+
protože to je konfigurace v souboru <code>$JAVA_HOME/lib/logging.properties</code>.
public class PbsCacheImpl implements PbsCache {
+
  
    final static Logger log = LoggerFactory.getLogger(PbsCacheImpl.class);
+
Pokud to chci změnit, musím vyrobit soubor ''logging.properties'' s obsahem alespoň
  //...
+
 +
#vypis pujde na konzolu
 +
handlers=java.util.logging.ConsoleHandler
 +
  # handler propusti vsechno od finest
 +
java.util.logging.ConsoleHandler.level=FINEST
 +
# loggery propusti vsechno od finest
 +
.level= FINEST
 +
#
 +
#java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
 +
#java.util.logging.ConsoleHandler.formatter=java.util.logging.XMLFormatter
  
  // u jednoduchých výpisů stačí uvést řetězec a až dva argumenty pro nahrazení
+
a při spuštění specifikovat jeho místo:
  log.debug("Server {} má {} položek",server,numItems);
+
  
  //u složitějších výpisů je vhodné předřadit if,aby se argumenty zbytečně nevyhodnocovaly
+
java -Djava.util.logging.config.file=/home/nekdo/nekde/logging.properties
  if(log.isDebugEnabled()) {
+
    log.debug("Měla "+babka+" "+babkaPocetJablek+" a dědoušek jen "+dedaPocetJablek);
+
  }
+
 
+
  // u vyjímek pak
+
  try {
+
    //...
+
  } catch(Exception ex) {
+
    log.error("Houstone, máme problém",ex);
+
  }
+
</java>
+
 
+
Pokud používáte projekt typu [[Maven]], přidáte knihovnu pro SLF4J s Log4J přidáním této závislosti:
+
<xml>
+
<dependency>
+
    <groupId>org.slf4j</groupId>
+
    <artifactId>slf4j-log4j12</artifactId>
+
    <version>1.6.4</version>
+
</dependency>
+
</xml>
+
 
+
=== Kterou knihovnu mám použít? ===
+
 
+
Ve svém kódu použijte '''SLF4J''' a tuto otázku nemusíte během '''vývoje''' vůbec řešit.
+
 
+
Při '''nasazení''' programu pak můžete zvolit podle následujících kritérií:
+
 
+
 
+
* [http://java.sys-con.com/read/48541.htm Log4j vs. java.util.logging]
+
 
+
* otázka 1.
+
: Do you anticipate a need for any of the clever handlers that Log4j has that JUL does not have, such as the SMTPHandler, NTEventLogHandler, or any of the very convenient FileHandlers? Pak [http://logging.apache.org/log4j/docs/ Log4j], jinak [http://java.sun.com/j2se/1.5.0/docs/guide/logging/ JUL].
+
 
+
* otázka 2.
+
: Do you see yourself wanting to frequently switch the format of your logging output? Will you need an easy, flexible way to do so? In other words, do you need Log4j's PatternLayout? Pak [http://logging.apache.org/log4j/docs/ Log4j], jinak [http://java.sun.com/j2se/1.5.0/docs/guide/logging/ JUL].
+
 
+
* otázka 3.
+
: Do you anticipate a definite need for the ability to change complex logging configurations in your applications, after they are compiled and deployed in a production environment? Does your configuration sound something like, "Severe messages from this class get sent via e-mail to the support guy; severe messages from a subset of classes get logged to a syslog deamon on our server; warning messages from another subset of classes get logged to a file on network drive A; and then all messages from everywhere get logged to a file on network drive B"? And do you see yourself tweaking it every couple of days? Pak [http://logging.apache.org/log4j/docs/ Log4j], jinak [http://java.sun.com/j2se/1.5.0/docs/guide/logging/ JUL].
+
 
+
* otázka 4.
+
: Potřebuje, aby jednotlivé části projektu používaly rozdílný logovací engine? Typicky vyvijíte knihovnu, pak [http://www.slf4j.org/ Simple Logging Facade for Java (SLF4J)].
+

Verze z 19. 2. 2013, 15:13

Přehled

Logování je ukládání informací o událostech v programu, jehož účelem je v případě potřeby dohledání činnosti systému nebo diagnostikování chyby.

V jazyce Java existují v podstatě tyto tři hlavní implementace logování:

Aby nemusely být aplikace a knihovny psány pro konkrétní z těchto implementací, existují dvě obalovací logovací knihovny, které neposkytují implementaci logování, jen rozhraní:

Logback a Log4J jsou od stejného autora, Logback je novější, rychlejší a flexibilnější než Log4J. Log4J bylo odjakživa lepší než JUL, ale JUL byl prosazen silou firmou Sun jako standardní součást JDK.

SLF4J je nástupce JCL, odstraňuje jeho problémy s classloadery.

Co mám použít ?

Ve zdrojových textech svých programů používejte rozhraní SLF4J.

Při nasazení programů používejte implementaci Logback.

Při využití cizích knihoven nebo programů, které používají něco jiného, využijte SLF4J legacy bridge, tj. jcl-over-slf4j, log4j-over-slf4j, jul-to-slf4j bridge.

Logovací rozhraní

Simple Logging Facade for Java (SLF4J) [1]

Definuje úrovně

Použití

 
public class PbsCacheImpl implements PbsCache {
 
    final static Logger log = LoggerFactory.getLogger(PbsCacheImpl.class);
 //...
 
  // u jednoduchých výpisů stačí uvést řetězec a až dva argumenty pro nahrazení
  log.debug("Server {} má {} položek",server,numItems);
 
  //u složitějších výpisů je vhodné předřadit if,aby se argumenty zbytečně nevyhodnocovaly
  if(log.isDebugEnabled()) {
     log.debug("Měla "+babka+" "+babkaPocetJablek+" a dědoušek jen "+dedaPocetJablek);
  }
 
  // u vyjímek pak
   try {
     //...
   } catch(Exception ex) {
     log.error("Houstone, máme problém",ex);
   }

Pokud používáte projekt typu Maven, přidáte knihovnu pro SLF4J přidáním této závislosti:

 
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.2</version>
</dependency>

nebo u spustitelného projektu můžete

 
<dependency> 
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.0.7</version>
</dependency>

Jakarta Commons Logging (JCL) [2]

  • jednoduchá tenká knihovna, která sama o sobě logování neprovádí, ale za cenu mírného omezení funkcionality umožňuje jednotným zůsobem pracovat s mnoha různými logovacími mechanismy (m.j. s oběma výše uvedenými)
  • použití: LogFactory -> Log
  • problémy při použití rozdílných knihoven (class loader problems)
  • memory leaks
  • o nevýhodách Commons Logging
  • true story about JCL
  • JCL no more!

Implementace logování

Log4j (LS) [3]

  • velmi komplexní a robustní logovací knihovna
  • umí vše co JUL a něco navíc
  • defacto standard logování J2EE aplikací
  • nyní součástí http://logging.apache.org/, existuje k němu prohlížeč logů Chainsaw
  • úrovně (třída Level) ALL, TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
  • handlery pro logování na konzolu, do souboru, do databáze, přes JMS, do syslogu, emailem a další

Pro správnou funkci je třeba mít v CLASSPATH soubor jménem log4j.xml s konfigurací, např.:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
    <!-- appender určuje, kam se bude logovat, v tomto případě na konzolu -->
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
        </layout>
    </appender>
    <!-- tento appender loguje do denně rotovaného souboru  v adresáři určeném obsahem systémové property catalina.base-->
    <appender name="roll" class="org.apache.log4j.DailyRollingFileAppender">
        <param name="File" value="${catalina.base}/logs/pbsmon2.log4j"/>
        <param name="DatePattern" value=".yyyy-MM-dd"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
        </layout>
    </appender>
    <!-- category určuje úroveň logování pro třídy v určitém package -->
    <category name="org.apache.log4j.xml">
        <priority value="info"/>
    </category>
    <category name="net.sourceforge.stripes">
            <priority value="info"/>
    </category>
    <category name="cz.muni.fi.pa165.cv5">
            <priority value="debug"/>
    </category>
    <!-- root definuej hlavní konfiguraci, tedy které z appenderů se mají použít -->
    <root>
        <priority value="info"/>
        <appender-ref ref="STDOUT"/>
    </root>
</log4j:configuration>


java.util.logging (JUL) [4]

  • ve standardním API od JDK 1.4
  • třída Logger (instance mají asociované jméno, jehož základ by měl tvořit název balíku, protože je na něm postavena hierarchie Loggerů)
  • Úrovně (instance třídy Level) ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF
  • Možnost implementace vlastního Filteru
  • Připravené handlery pro paměť, OutputStream, soubor (včetně rotování), konzolu, IP socket (i více najednou)
  • Připravené textové a XML formátování
  • Podpora lokalizovaných zpráv přebíraných z ResourceBundle
  • LogManager spravující všechny Loggery a jejich konfiguraci

Když neprovedu žádnou konfiguraci, JUL loguje od úrovně INFO na konzolu pomocí SimpleFormatter, protože to je konfigurace v souboru $JAVA_HOME/lib/logging.properties.

Pokud to chci změnit, musím vyrobit soubor logging.properties s obsahem alespoň

#vypis pujde na konzolu
handlers=java.util.logging.ConsoleHandler
# handler propusti vsechno od finest
java.util.logging.ConsoleHandler.level=FINEST
# loggery propusti vsechno od finest
.level= FINEST
#
#java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
#java.util.logging.ConsoleHandler.formatter=java.util.logging.XMLFormatter

a při spuštění specifikovat jeho místo:

java -Djava.util.logging.config.file=/home/nekdo/nekde/logging.properties