Veľmi dôležitou vecou, ktorú musí mať každá aplikácia, je logovanie chýb. Pre .NET aplikácie existuje výborná knižnica log4net. Síce jej chýba priamo zabudovaný výstup do XML dokumentu, obsahuje generovanie XML fragmentov do textového súboru a ten je možné potom vložiť ako externú entitu do XML dokumentu.
log4net obsahuje dobrý základ pre logovanie chýb pomocou vlastných, špecializovaných, objektov. Pomocou nich je možné napr. zalogovať podrobne chyby v SQL príkaze, alebo všetky SQL príkazy, ktoré boli asociované s DataAdapter-om, v ktorom nastala chyba. Takto je možné zistiť aj v akom stave bolo spojenie s databázou.
Logovací systém log4net sa skladá z týchto základných objektov:
-
Layout – stará sa o formát, v akom budú logované záznamy uložené.
-
Appender – ukladá záznamy do logovacieho výstupu. Výstup môže byť súbor, databáza, konzola, logovací server a pod.
-
Filter – filtruje úroveň (Level) záznamov a iné vlastnosti, na základe ktorých logovaný záznam predá appenderu, alebo nepredá.
-
ILog – interface ktorý ukladá záznamy. Je vytvorený na základe konfiguračného XML súboru, alebo programovo.
Všetky logovacie metódy rozhrania ILog prijímajú ako prvý parameter object, druhý, nepovinný, je Exception. Napr.:
ILog.Error(object message, Exception exception);
Pri spracovaní logovaného objektu (väčšinou v metóde LayoutBase.Format(), v prípade XmlLayout-u vo FormatXml()) sa zavolá message.ToString(). Štandardne sa do metódy posiela string (zložitejší text sa formátuje napr. pomocou ErrorFormat(string format, params object[] args)). Nič nám však nebráni si napísať vlastný logovací objekt, ktorý bude preťažovať metódu ToString().
Prvá trieda je celkom jednoduchá: do textového logu vypisuje len chybovú správu. (Zdrojový kód SimpleLogItem)
public class SimpleLogItem
{
private string _message;
public SimpleLogItem()
: this("")
{ }
public SimpleLogItem(string message)
: this (message, null)
{ }
public SimpleLogItem(string message, params object[] args)
{
if (message != null)
_message = String.Format(message, args);
else
_message = message;
}
public string Message
{
get { return this._message == null ? "" : _message; }
}
public override string ToString()
{
return String.Concat("[Log message] ", Message);
}
}
Konštruktor SimpleLogItem priamo podporuje formátovanie textu pre väčšie pohodlie. Celkovo však táto trieda nerobí nič, čo by sa nedalo dosiahnuť „Format“ metódami v ILog. Slúži však ako veľmi jednoduchý základ pre sofistikovanejšiu triedu: SimpleSqlLogItem.
Zdrojový kód triedy SimpleSqlLogItem je celkom veľký takže na neho uvádzam len linku. Uvediem len použitie a výstup logu.
SqlCommand cmd;
SqlConnection conn;
// …
try
{
SqlDataReader reader = cmd.ExecuteReader();
// …
}
catch (SqlException ex)
{
log.Warn(new SimpleSqlLogItem(cmd, „Nepodarilo sa získať informácie o užívateľovi.“));
}
finally
{
conn.Close();
}
SimpleSqlLogItem môže naformátovať výstup napríklad takto:
[Log message] Nepodarilo sa získať informácie o užívateľovi.
[SQL Command] SELECT id, meno, email FROM uzivatelia WHERE id = @ID AND meno = @meno
[param] int @ID = 1
[param] varchar @meno = ‚Administáror‘
[Connection] DBSERVER\SQLEXPRESS:UkazkovaDB (Open)
Btw: v tomto príklade sa nepodarilo získať informácie o užívateľovi pretože dátový typ parametru @meno by mal byť nvarchar. Takéto logovanie dokáže zachytiť aj aktuálny stav pripojenia do databázy, pretože získanie stavu objektu SqlCommand.Connection sa vykoná pred uzavretím spojenia v kóde finally.
Nabudúce popíšem spôsob vytvorenia vylepšeného LogItem-u, ktorý bude používať XmlWriter na zápis údajov.