CourseWare Wiki
Switch Term
Summer 2023 / 2024
Summer 2022 / 2023
Summer 2021 / 2022
Summer 2020 / 2021
Summer 2019 / 2020
Summer 2018 / 2019
Summer 2017 / 2018
Older
Search
Log In
b232
courses
b0b36pjv
tutorials
07
logovani
Differences
This shows you the differences between two versions of the page.
View differences:
Side by Side
Inline
Go
Link to this comparison view
Go
Go
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