Hlavní menu

Nástroje

SlovnikTerminologie / JemnyUvodDoLogovani

View (print) - Edit page | Recent changes - Page history

Updated 31 October 2009, 18:09 by JanSobisek

Logování

Vyjmuto z me BP. (TP)

Motivace

Použití logovacího frameworku log4j namísto klasického System.out.println() má mnoho výhod. Mezi nimi jsou různé typy výstupů(xml soubor, příkazová řádka, log soubor, GUI komponenta, vzdálený socket server, JMS, NT Event Loggers, a vzdálený UNIX Syslog daemon). Možnost centrální konfigurace přes properties soubor. Předdefinovaná hiearchie úrovní logování(TRACE, DEBUG, INFO, WARN, ERROR a FATAL) s možností vytvoření vlastní úrovně logování pro nějaké speciální případy. Snadná implementace do aplikace. Poslední výhodou je snadno nastavitelný formát záznamů, do kterého můžeme snadno zanést mnoho rozličných informací.

Přestože nám logování pomocí logovacích frameworků poskytuje možnosti, které se s System.out.println() nedají srovnávat, stále se setkávám s tím, že valná část studentů používá zásadně System.out.println(). Bohužel o takovýchto frameworcích ještě neslyšeli a v případě, že slyšeli, tak povětšinou tvrdí, že použití je příliš složité. Při tom ale bez logování se na profesionální úrovni neobejde žádný projekt. Použitím logovacího frameworku můžeme zrychlit vývoj aplikace a vlastní kód logování je přímý a přehledný.

Při psaní logů jsem se rozhodl použít 4 úrovně logování:

  • DEBUG - používám pro logování informací potřebných pro vývoj aplikace.
  • INFO - používám pro logování aktivity uživatelů a informativní hlášky, o kterých si myslím, že by se v logu mohly vyskytnout.
  • WARN - používám pro logování méně významných exceptions chycených v try-catch blocích, které nevedou k omezení funkčnosti aplikace.
  • ERROR - používám pro logování exceptions chycených v try-catch blocích, při kterých dojde k omezení funkčnosti, případně spadnutí aplikace.

Realizace

Implementace logování pomocí framework log4j není nijak složitá. Stačí mít správně nakonfigurovaného listenera a připravený property soubor log4j.properties a pak už programátor může psát vlastní logování uvnitř tříd aplikace. Na následujích řádcích je popsáno, jak snadno lze logování aplikace zprovoznit.

Nejdříve jsem si připravil logování aplikace v souboru web.xml.

 <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/properties/log4j.properties</param-value>
 </context-param>

 <listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
 </listener>

První context-param určuje umístění, kde se nachází konfigurační soubor pro log4j log4j.properties. Logování by ale nefungovalo bez potřebného listeneru. Tento Log4jConfigListener nám zajišťuje načtení konfigurace a následné zapisování do patřičných lokací uvedených v konfiguračním souboru.

Dále je třeba zanést konfiguraci do souboru:

log4j.category.cz.zcu.kiv.spot=DEBUG, stdout, R
log4j.category.cz.zcu.kiv.spot.controllers.LogoutController=INFO, U
log4j.category.cz.zcu.kiv.spot.controllers.LoginController=INFO, U

#log4j.logger.org.springframework.web.servlet=DEBUG, stdout, R
#log4j.logger.org.springframework=DEBUG, stdout, R

# Nastaveni logovani pro konsoli
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C{1}:%M(line %L):%m%n

# Nastaveni logovani pro vystup do souboru
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=logs/spot-commons.log
log4j.appender.R.MaxFileSize=5MB
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%5p %d %c{1}:%M(line %L) : %m%n

# Appender pro logovani prihlaseni a odhlaseni uzivatelu
log4j.appender.U=org.apache.log4j.RollingFileAppender
log4j.appender.U.File=logs/spot-users.log
log4j.appender.U.MaxFileSize=5MB
log4j.appender.U.layout=org.apache.log4j.PatternLayout
log4j.appender.U.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} - %m%n

Na začátku souboru se definují balíky, které chci logovat. První řádek říká, že budu logovat celý balík cz.zcu.kiv.spot, který se bude logovat od úrovně DEBUG a výše, a tomuto logování jsou přiřazeny appendery R a stdout. Na dalších dvou řádcích přiřazuji konkrétní dvě třídy LoginController a LogoutController appenderu U a logování od úrovně INFO.

Rozdělení appenderů má ten smysl, že například můžu zmiňované controllery logovat do souboru, kam se zapisuje pouze přihlašování a odhlašování uživatelů. Zbylé dva appendery slouží k běžnému logování, R appender slouží k logování do souboru a stdout k výpisu do příkazové řádky.

Dále je třeba nakonfigurovat konkrétní appendery. První řádka specifikuje způsob výstupu. V rámci aplikace se používá ConsoleAppender a RollingFileAppender. U RollingFileAppenderu se musí nakonfigurovat výstupní soubor, buď absolutně nebo relativně. Dále se určí maximální velikost souboru. Maximální velikost neznamená, že se soubor při dosažení maximální velikosti začne od konce přepisovat, ale vytvoří se nový soubor, do kterého přenese data ze souboru původního a nové záznamy dále ukládá do původního souboru. Pak se konfiguruje, u obou výstupů stejně, vzor výstupu a poslední je ConversionPattern, tedy formát výstupu.

Nyní je aplikace připravena pro logování. Následuje příklad logování v java kódu. Nejdříve se musí vytvořit instance Loggeru:

private Logger logger = Logger.getLogger(getClass());

Tento Logger si drží informaci o třídě, ve které je vytvořen. Pokud by bylo třeba použití statického logger, pak jen nahradíme getClass() za Trida.class.

Nyní už jen stačí na patřičném místě v kódu vytvořit logovací zprávu. Následují 2 příklady:

catch (Exception e) {
    logger.error("Nastala chyba v aplikaci. " + e);
    mv.addObject("errorImportMsg", "db.access-error");
}

Kód představuje zachycení vyjímky v try-catch bloku uvnitř controlleru.

logger.info("Prihlaseni uzivatele: " + sessionUser.getLogin() 
             + " IP: " + request.getRemoteAddr());

Instance Loggeru může volat několik metod. Jména metod jsou závislá na úrovni logu, který chceme vytvořit. Můžeme volit z dostupné škály uvedené na začátku kapitoly. Parametrem metod je Object, tedy můžeme logovat vše co potřebujeme. Jen je potřeba myslet na to, aby z logu vystupovala smysluplná data.

Odkazy