Search
Jak takové logování vypadá?
Jistě znáte a používáte System.err.print(). To umožňuje samozřejmě vypisovat libovolné hlášky v libovolných místech, ale neumožňuje efektivně vypínat či přepínat způsob výpisu, přesměrovávat výpis do více než dvou (out, err) výstupů, nebo nastavovat úroveň důležitosti.
System.err.print()
Existuje více logovacích frameworků (můžete si napsat i svůj), ale pro jednoduchost zůstaneme u tohoto defaultního (java.util.logging), který poskytuje vše, co zatím potřebujeme.
java.util.logging
Vytvoříme si statický logger v naší třídě (podle které dostane i jméno - je to konvence)
private static final Logger LOG = Logger.getLogger(<your-class>.class.getName());
LOG.log(<level>,<msg>,[<object>]) LOG.severe/warning/info/config/fine/finer/finest(<msg>)
Na obrázku výše vidíme základní rozlišení logovacího frameworku java.util.logging. Je třeba odlišovat několik typů:
Ideálně (doporučuje se) má každá třída svůj logger. Každý nový logger používá defaultně handlery svého rodiče (odvozeného právě díky konvenci v pojmenovávání podle balíčků - tříd). To lze nastavit pomocí LOG.setUseParentHandlers(<boolean>);.
LOG.setUseParentHandlers(<boolean>);
Vždy existuje kořenový (root) logger, který má jméno “” (prázdný string), ke kterému se dostaneme pomocí Logger.getLogger(“”);. Tento “root” logger defaultně vypisuje na System.err. Jakýkoli další vytvořený logger tedy defaultně přebírá handlery rodiče, kterými se rekurzivně dostaneme až k root loggeru, a tudíž se defaultně vypisuje na System.err, ikdyž jsme žádný handler nenastavovali.
Logger.getLogger(“”);
System.err
Každý logger má nastavený svůj Level (defaultně je to Level.INFO), který označuje, že se zprávami, které mají význam menší než INFO (tzn. CONFIG, FINE, FINER, FINEST) se vůbec neobtěžuje (není tak úplně pravda - bude objasněno později) a nepošle je dále.
Stejně tak i handler má nastavený svůj Level (defaultně je to Level.INFO), který funguje stejně jako u loggerů. Obojí se dá nastavit pomocí <logger/handler>.setLevel(<level>):
<logger/handler>.setLevel(<level>)
Level.ALL
Level.OFF
Nakonec, pokud chceme i jiný výstup z loggeru než přes System.err, musíme vytvořit a přiřadit loggeru jiný handler. Pokud používáme (což bychom měli) jiný logger než root (“”), můžeme se zbavit defaultního přesměrovávání na System.err pomocí
LOG.setUseParentHandlers(false);
Nyní můžemee experimentovat s vlastními handlery:
LOG.addHandler(new ConsoleHandler()) //pozn.: ConsoleHandler využívá System.err a nejde změnit
System.out
Handler stdout = new StreamHandler(System.out, new SimpleFormatter()); LOG.addHandler(stdout);
ConsoleHandler (extends StreamHandler)
public class ConsoleHandler extends StreamHandler { ... @Override public void publish(LogRecord record) { super.publish(record); flush(); }
Handler stdout = new StreamHandler(System.out, new SimpleFormatter()) { @Override public void publish(LogRecord record) { super.publish(record); flush(); } };
LOG.addhandler(new FileHandler(<filename.log>));
Každý logger může mít více handlerů a naopak.
Kromě logovacího frameworku v Java JDK existují ještě další. Za zmínku stojí například Log4j anebo SLF4J, což je společný interface (wrapper) pro více logovacích frameworků (včetně Log4j). SLF4J má zároveň nativní implementaci Logback. Který z nich použijete je pak na Vás, každý má nějaké výhody/nevýhody.