Při vývoji aplikací se bez logování neobejde žádný programátor. Logování přináší základní informace o událostech, které v běžící aplikaci nastanou, a umožňuje získané informace použít pro pozdější analýzu kódu. Velmi praktické je logování v případech, kdy nemáme k dispozici debugger nebo jej nelze použít. Získaná data mohou být jednoduchého informačního charakteru i detailní výpisy.

Nejjednodušším způsobem je vypsat získané informace do výstupního streamu pomocí System.out nebo System.err. Tento způsob získávání informací má však jednu nevýhodu, a to předpoklad přístupu k systémovému oknu (konzole). U aplikací MIDP, které běží v bezdrátových zařízeních, jako jsou mobilní telefony, není konzole k dispozici. Jedním z možných způsobů je přesměrovat výstupní stream do souboru nebo soketu. Další možností, kterou nabízejí některá zařízení, je uložit informace do RMS (Record Management System).

Tento příspěvek je zaměřen spíše prakticky než teoreticky a jeden takový jednoduchý logger zde vytvoříme.

Úrovně logování

Prvním krokem, který je třeba udělat, je nadefinovat si úrovně logování. Při nastavené úrovni SEVERE získáme výpisy pouze fatálních chyb. Nastavováním nižších úrovní získáme detailnější výpisy. Pokud chceme logování vypnout, nastavíme úroveň OFF.

  • LEVEL_OFF – logování je vypnuto
  • LEVEL_FINE – velmi detailní výpisy
  • LEVEL_INFO – informační výpisy
  • LEVEL_WARNING – něco, na co je třeba se podívat
  • LEVEL_SEVERE – výpis pouze fatálních chyb

Abychom nemuseli vždy zadávat při zápisu logu úroveň, vytvoříme si ke každé úrovni metodu, která to za nás udělá. Kromě vlastní zprávy budeme předávat i odkaz na objekt, který log zapsal. V dalším kroku nadefinujeme konstanty, kterými určíme, kam budeme logy zapisovat. Příklad metody pro úroveň SEVERE:

public void fine(Object caller, String msg) {
    log(caller, LEVEL_FINE, msg);
}

Další metody pro zápis logu:

public void info(Object caller, String msg)
public void warning(Object caller, String msg)
public void severe(Object caller, String msg)

Pro zjištění, zda je možné zapsat log do výstupního streamu, nadefinujeme metodu isLoggable(int level), která vrací true, pokud je možné log zapsat, jinak vrací false. Změnu úrovně logování provedeme pomocí metody setLevel(int level).

Nastavení výstupu logování

Pro nastavení výstupu logování zavedeme následující konstanty:

  • LOG_STDOUT – zápis do systémového okna
  • LOG_RMS – zápis do databáze telefonu
  • LOG_HTTP – zápis do HTTP streamu

Pro nastavení výstupu logování zavedeme metodu setLogTo(int logTo, String url), jejíž parametry jsou logTo (určuje výstup) a url (při nastaveném flagu LOG_HTTP určuje adresu serveru, kam se budou posílat logy). Parametry LOG_STDOUT, LOG_RMS a LOG_HTTP lze kombinovat operátorem OR.

public void setLogTo(int logTo, String url)
        throws IllegalArgumentException {
    if ((logTo & LOG_TO_HTTP) != 0 &&
        (url == null || url.trim().equals(„“)))
      throw new IllegalArgumentException(
        „URL is null or empty string“);
    if ((logTo & LOG_TO_RMS) != 0)
        openLogRMS();
    else
        closeLogRMS();
    _logTo = logTo;
    _url = url;
}

Pomocné metody

Pro výpis logu do RMS a do HTTP streamu zavedeme pomocné metody, které jsou uvedeny níže:

  • public String getTimeStamp() – vrací časový údaj při zápisu logu
  • public void openLogRMS() – otevře RMS
  • public void closeLogRMS() – uzavře RMS
  • public void clearLogRMS() – vymaže obsah RMS
  • public void storeLogRMS() – uloží log do RMS
  • public String getLogRMS() – vrátí logy uložené v RMS jako objekt String
  • public void sendToHTTP() – pošle log do HTTP streamu

Vlastní logování

Teď, když máme vše připraveno, vytvoříme poslední metodu, která bude zapisovat logy do zvoleného výstupu, tj. systémové konzole, RMS a HTTP streamu. Tato metoda je volána metodami, které byli uvedeny výše v části o úrovních logování, a pokud chceme, můžeme ji volat přímo.

public void log(Object caller, int level, String msg)

Nejprve se zjistí, zda je logování zapnuto, a zjistí se, zda lze log zapsat. Pokud ano, je vytvořen vlastní log, který má následující formát:

den/mesíc/rok/hh:mm:ss level_logu [třída, která log vytvořila] : vlastní log

public void log(Object caller, int level, String msg) {
 if (level != LEVEL_OFF) {
  synchronized (this) {
   if (!isLoggable(level)) return;
   String log = getTimeStamp() +
                “ “ + LEVELS[level] + “ [“ +
                caller.getClass().getName() +
                „] : “ + msg;
   _msg = log;
   if ((_logTo & LOG_TO_STDOUT) != 0) {
    System.out.println(log);
   }
   if ((_logTo & LOG_TO_RMS) != 0) {
    storeLogToRMS(log);
   }
    if ((_logTo & LOG_TO_HTTP) != 0) {
    Thread thread = new Thread(this);
    thread.run();
   }
  }
 }
}

Pro zjednodušení byly uvedeny jen některé implementace metod. Výsledný logger je vám k dispozici v připojeném archivu. Ještě malá poznámka na konec. Pokud zvolíte logování do RMS, nastavte úroveň minimálně na warning, aby se RMS příliš rychle nezaplnilo. Tento logger není úplně to nejlepší co může být, ale jistě někomu přijde vhod.

Odkazy, zdroje

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět