Hlavní navigace

Síťování v Javě: Logování

Martin Majer 25. 5. 2006

Dnes mírně odbočíme od zaměření seriálu. Podíváme se na téma, které se síťováním úzce souvisí - logování. Ukážeme si, jaké jsou možnosti vytváření logů. Od výpisu na konzoli, až po java.util.logging API.

Výpis na konzoli

Výstup na konzoli lze považovat za nejprimitivnější formu vytváření logu. V případě potřeby prostě zavoláme System.out.prin­tln() a odešleme zprávu na standardní výstupní proud. Můžeme použít i standardní chybový proud, System.err.

Tato forma logování se pochopitelně pro větší aplikace vůbec nehodí. Proud System.out lze sice přesměrovat do souboru, ovšem pořád existují mnohem vhodnější způsoby.

Zápis do souboru pomocí PrintWriter

Zápis do souboru pomocí java.io je na téměř stejné úrovni jako výpis na konzoli. Přesto si však ukážeme, jak ho naprogramovat:

import java.io.*;

public class FileLogger {
    public static final String FILE = "log.txt";
    public static void main(String[] args) throws IOException {
        PrintWriter logger = null;
        try {
            //otevřít proud pro zápis na konec souboru
            logger = new PrintWriter(new FileOutputStream(FILE, true));
            //zkusíme si logovat
            logger.println("FileLogger test");
        }
        catch(IOException e) {}
        finally {
            if(logger != null) logger.close();
        }
    }
} 

Důležitý je druhý parametr v konstruktoru FileOutputStream. Pokud bychom ho neuvedli nebo nastavili na false, soubor by se přepsal a přišli bychom o celý předcházející log.

Logovací API

Ve drtivé většině případů je nejvhodnější volbou API specializované přímo na logování. V praxi se nejčastěji používají dvě – jednoduché logging API z balíku java.util.logging, které je přímo součástí JDK, a složitější log4j od Apache Software Foundation. Samozřejmě vám nic nebrání napsat si vlastní, ovšem použitím již hotových si ušetříte mnoho práce.

V tomto článku si popíšeme pouze API z balíku java.util.logging. Vybral jsem ho především kvůli jeho jednoduchosti. Log4j je naopak tak rozsáhlé, že by vystačilo na celý další seriál.

java.util.logging API

Toto jednoduché logovací API je umístěno v přímo knihovnách J2SE, a to od verze 1.4. Nebudu se rozepisovat o teorii a jeho architektuře, pojďme se rovnou podívat, jak ho použít.

Logger

Základem je třída Logger z balíku java.util.logging. Její instanci získáme pomocí statického továrního konstruktoru getLogger(). Jako parametr uvedeme jméno loggeru. Pokud již nějaký logger se stejným jménem existuje, getLogger() nebude vytvářet nový, ale vrátí ten stávající.

Logger logger = Logger.getLogger("test"); 

Handler

Dalším krokem je nastavení handleru. Handler je objekt, který má na starosti zpracování příchozích zpráv od loggeru, např. jejich uložení do souboru.

Handlery se dělí do dvou základních skupin – MemoryHandlery a StreamHandlery. MemoryHandler nejdříve ukládá zprávy do vyrovnávací paměti. Pak je přeposílá jinému handleru. StreamHandlery zase zapisují log do nějakého výstupního proudu. Patří mezi ně ConsoleHandler, FileHandler a SocketHandler.

K přidání nového handleru slouží metoda loggeru addHandler(). Odebrání provádíme metodou removeHandler() a getHandlers() vrátí pole všech handlerů příslušného loggeru.

Handler handler = new FileHandler("log.txt", true);
logger.addHandler(handler); 

Tímto kódem vytvoříme nový handler pro zápis do souboru (FileHandler). První parametr jeho konstruktoru určuje jméno souboru s logem, podle druhého handler pozná, jestli má soubor přepsat nebo pokračovat na jeho konci.

Jakmile dokončíme práci s handlerem, musíme ho pochopitelně uzavřít metodou close().

Formatter

Formattery mají na starosti formátování příchozích zpráv od loggeru. V balíku java.util.logging jsou pouze dva – SimpleFormatter a XMLFormatter. Jak zprávy formátují, je zcela zřejmé z jejich názvů.

handler.setFormatter(new SimpleFormatter()); 

Je možné, že vám ani jeden ze dvou formatterů nebude vyhovovat. V tomto případě není problém vytvořit si vlastní odvozením z abstraktní třídy Formatter. Informace o jejím API jsou uvedené v dokumentaci.

Logování

Logování probíhá pomocí instance třídy Logger a několika jejich metod:

  • entering(String sourceClass, String sourceMethod) – Zaznamená vstup do metody.
  • exiting(String sourceClass, String sourceMethod) – Informuje o opuštění metody.
  • fine/finer/fi­nest(String msg) – Odešle do logu zprávy typu fine, finer nebo finest (nejméně důležité).
  • log(Level level, String msg) – Pošle do logu zprávu se specifikovanou úrovní závažnosti.
  • severe(String msg) – Pošle do logu zprávu typu severe. Tato úroveň je nejzávažnější, většinou se jedná o kritické chyby.
  • throwing(String sourceClass, String sourceMethod, Throwable thrown) – vloží záznam o vyvolání nějaké výjimky.
  • warning(String msg) – Pošle varování.

Metody entering(), exiting() a log() jsou ještě několikrát přetížené. Více informací o nich se dozvíte v dokumentaci.

Příklad logování

import java.util.logging.*;

public class LoggingTest {
    public static void main(String[] args) throws java.io.IOException {
        Logger logger = Logger.getLogger("test"); //vytvoříme logger s názvem test
        Handler handler = new FileHandler("log.txt", true); //vytvoříme handler pro zápis na konec souboru log.txt
        handler.setFormatter(new SimpleFormatter()); //nastavíme jednoduché formátování (výchozí je XML)
        logger.addHandler(handler); //přidáme handler

        //logujeme
        logger.log(Level.INFO, "zprava");
        logger.log(Level.SEVERE, "chyba");
        logger.finest("v pohodě");

        handler.close(); //uzavřeme handler
    }
} 

Když příklad spustíte, zjistíte že zpráva „v pohodě“ typu finest se do souboru nezapsala. Tyto nevýznamné zprávy jsou totiž loggerem ve výchozí konfiguraci ignorovány. Pokud o ně ale nechcete přijít, nakonfigurujte logger příkazem logger.setLevel(Le­vel.FINEST);

Takto vypadá log s úrovní Level.FINEST:

20.5.2006 19:00:25 LoggingTest main
INFO: zprava
20.5.2006 19:00:25 LoggingTest main
SEVERE: chyba
20.5.2006 19:00:25 LoggingTest main
FINEST: v pohodě 

A takto by vypadal log, pokud bychom nastavili XMLFormatter:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
  <date>2006-05-22T14:42:24</date>

  <millis>1148301744258</millis>
  <sequence>0</sequence>
  <logger>test</logger>
  <level>INFO</level>

  <class>LoggingTest</class>
  <method>main</method>
  <thread>10</thread>
  <message>zprava</message>

</record>
<record>
  <date>2006-05-22T14:42:24</date>
  <millis>1148301744426</millis>
  <sequence>1</sequence>

  <logger>test</logger>
  <level>SEVERE</level>
  <class>LoggingTest</class>
  <method>main</method>

  <thread>10</thread>
  <message>chyba</message>
</record>
</log> 

Závěr

Dnes jsme si řekli o možnostech logování v Javě a ukázali jsme si, jak používat logovací API obsažené v balíku java.util.logging. Příště se zase vrátíme k síťování – naučíme se používat UDP protokol.

Našli jste v článku chybu?

28. 5. 2006 18:10

Karel (neregistrovaný)
ajo, to jsem prehledl, tak to jo

26. 5. 2006 14:24

Nešlo, metoda setOutputStream() v StreamHandleru by musela být public, jenže ona je protected.
Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Podnikatel.cz: EET: Totálně nezvládli metodologii projektu

EET: Totálně nezvládli metodologii projektu

DigiZone.cz: ČRo rozšiřuje DAB do Berouna

ČRo rozšiřuje DAB do Berouna

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

DigiZone.cz: NG natáčí v Praze seriál o Einsteinovi

NG natáčí v Praze seriál o Einsteinovi

Podnikatel.cz: Babiše přesvědčila 89letá podnikatelka?!

Babiše přesvědčila 89letá podnikatelka?!

Vitalia.cz: „Připluly“ z Německa a možná obsahují jed

„Připluly“ z Německa a možná obsahují jed

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

DigiZone.cz: ČT má dalšího zástupce v EBU

ČT má dalšího zástupce v EBU

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

Podnikatel.cz: Na poslední chvíli šokuje vyjímkami v EET

Na poslední chvíli šokuje vyjímkami v EET

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Podnikatel.cz: Prodává přes internet. Kdy platí zdravotko?

Prodává přes internet. Kdy platí zdravotko?

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0