Differences

This shows you the differences between two versions of the page.

Link to this comparison view

courses:b0b36pjv:tutorials:07:logovani [2018/02/06 08:43]
courses:b0b36pjv:tutorials:07:logovani [2022/04/21 08:46] (current)
Line 1: Line 1:
 +===== Logování =====
 +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.
 +
 +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.
 +
 +==== Minimální kód ====
 +Vytvoříme si statický logger v naší třídě (podle které dostane i jméno - je to konvence)
 +<code java>
 +private static final Logger logger = Logger.getLogger(<​your-class>​.class.getName());​
 +</​code>​
 +Pak máme k dispozici několik způsobů logování hlášek dělené hlavně podle úrovně důležitosti:​
 +<code java>
 +logger.log(<​level>,<​msg>,​[<​object>​])
 +logger.severe/​warning/​info/​config/​fine/​finer/​finest(<​msg>​)
 +</​code>​
 +
 +==== Struktura frameworku ''​java.util.logging''​ ====
 +{{:​courses:​a0b36pr2:​labs:​loggingblockdiagram.png?​nolink|}}
 +
 +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ů:
 +  * Level - určuje významnost zprávy
 +  * Logger - aplikace skrze Logger zprávy vytváří a posílá do Handlerů
 +  * Handler - přijímá zprávy a zpracovává je (tiskne na konzoli, do souboru, do paměti,​...)
 +  * Filter - umožňuje omezit množství zpráv (jak odesílaných z Loggeru, tak zpracovávaných Handlerem)
 +  * Formatter - umožňuje formátovat zprávy (nebudeme se jím zabývat)
 +
 +==== Propojení Logger - Handler ====
 +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>​);''​.
 +
 +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.
 +
 +==== Level - {SEVERE/​WARNING/​INFO/​CONFIG/​FINE/​FINER/​FINEST} ====
 +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>​)'':​
 +  * ''​Level.ALL''​ znamená výpis všech zpráv
 +  * ''​Level.OFF''​ znamená výpis žádných zpráv
 +
 +==== Handler - {Console/​File/​Stream/​Socket/​Memory} ====
 +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í
 +<code java>
 +logger.setUseParentHandlers(false);​
 +</​code>​
 +
 +Nyní můžemee experimentovat s vlastními handlery:
 +  * Pro výstup na ''​System.err'': ​
 +<code java> ​
 +logger.addHandler(new ConsoleHandler()) //pozn.: ConsoleHandler využívá System.err a nejde změnit
 +</​code>​
 +  * Pro výstup na ''​System.out'':​
 +<code java>
 +Handler stdout = new StreamHandler(System.out,​ new SimpleFormatter());​
 +logger.addHandler(stdout);​
 +</​code>​
 +''​ConsoleHandler (extends StreamHandler)''​ volá po každém logu flush():
 +<code java>
 +public class ConsoleHandler extends StreamHandler {
 +...
 +@Override
 +public void publish(LogRecord record) {
 +   ​super.publish(record);​
 +   ​flush();​
 +}
 +</​code>​
 +Musíme při vytváření handleru tuto metodu také přepsat
 +<code java>
 +Handler stdout = new StreamHandler(System.out,​ new SimpleFormatter()) {
 +    @Override
 +    public void publish(LogRecord record) {
 +        super.publish(record);​
 +        flush();
 +    }
 +};
 +</​code>​
 +  * Pro výstup do souboru:
 +<code java>
 +logger.addhandler(new FileHandler(<​filename.log>​));​
 +</​code>​
 +
 +Každý logger může mít více handlerů a naopak.
 +
 +==== Další frameworky ====
 +Kromě logovacího frameworku v Java JDK existují ještě další. Za zmínku stojí například [[https://​logging.apache.org/​log4j/​2.x/​index.html|Log4j]] anebo [[http://​www.slf4j.org/​|SLF4J]],​ což je společný interface (wrapper) pro více logovacích frameworků (včetně Log4j). SLF4J má zároveň nativní implementaci [[http://​logback.qos.ch/​|Logback]]. Který z nich použijete je pak na Vás, každý má nějaké výhody/​nevýhody.
 +
 +
  
courses/b0b36pjv/tutorials/07/logovani.txt · Last modified: 2022/04/21 08:46 by zidekja2