Jest wiele sposobów na znajdowanie błędów w aplikacji: dowody matematyczne, testy jednostkowe, ręczne testowanie i debugowanie. Niestety debugowanie może być bardzo czasochłonne jeśli nie wiemy, w którym miejscu znajduje się problem. Tworzenie logów może nam pomóc zlokalizować ten problem.
Istnieje kilka .NETowych frameworków do logowania, m.in. log4net, WisdomCloud.Log i NLog, który postanowiłem użyć w moim projekcie. Można go pobrać z NuGet:NLog.
Pierwsza rzecz jaką należy zrobić po zainstalowaniu paczki to utworzenie pliku konfiguracyjnego. Jego szablon jest dostępny z drugiej paczki NuGet:NLog.Config.
Otrzymujemy plik ,,NLog.config” w XMLu. Mój wygląda tak:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false" >
<targets>
<target xsi:type="File" name="logfile" fileName="SharpOffice.log" lineEnding="CRLF"
layout="[${date:format=yyyy-MM-dd HH\:mm\:ss}] ${uppercase:${level}} - (${logger}) ${message}"
footer="----------"/>
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logfile" />
<!-- Comment below on production -->
<logger name="*" minlevel="Trace" maxlevel="Debug" writeTo="logfile" />
</rules>
</nlog>
Wewnątrz <targets>
określamy cel naszych logów. Może to być plik, konsola, eventlog, mail, NLogViewer i wiele innych. Za pomocą atrybutu layout
określamy jak ma wyglądać nasza wiadomość. Moje ustawienie produkuje coś takiego:
[2016-05-16 12:32:04] DEBUG - (Container) Starting container initialization...
Dalej definiujemy zasady, czyli w jakim przypadku generować logi. name="*"
oznacza wszystkich loggerów, ale można określić jednego konkretnego lub grupę mającą ten sam prefix. [min|max]level
określa jaki poziom wiadomości akceptować. W kolejności rosnącej są to:
- Trace
- Debug
- Info
- Warn
- Error
- Fatal
Na koniec writeTo
określa target do którego mamy pisać.
Logi w kodzie
Aby tworzyć logi wystarczy dodać prywatne statyczne pole typu NLog.Logger
do naszej klasy, a następnie poprosić NLog.LogManager
o Logger o żądanej nazwie. Np. mój ContainerWrapper posiada taki Logger:
private static readonly Logger Logger = LogManager.GetLogger("Container");
A następnie w kodzie aby wypisać jakąś wiadomość do logu, używamy jednej z metod o nazwie takiej jako poziom:
Logger.Debug("Starting container initialization...");
Dodatkowo możemy przekazywać parametry w formacie String.Format
, które nie będą przerabiane na string jeśli nie będzie potrzeby użycia (wynikającego z reguł).
Logger.Warn("DLL file \"{0}\" is not a .NET assembly.", assemblyFile);
W sumie logowanie jest proste, ale też nie można przesadzić z ilością logów, bo kod stanie się nieczytelny.
Mój przykładowy output
Jeszcze nie wprowadziłem logowania do każdej klasy gdzie chciałbym je mieć, ale kilka podstawowych daje ładny efekt:
[2016-05-16 13:17:00] DEBUG - (Container) Starting container initialization...
[2016-05-16 13:17:00] DEBUG - (Container) Registering types from "ApplicationRegistrationModule"
[2016-05-16 13:17:00] DEBUG - (Container) Registering types from "ConfigurationProviderRegistrationModule"
[2016-05-16 13:17:00] DEBUG - (Container) Registering types from "ConfigurationsRegistrationModule"
[2016-05-16 13:17:00] DEBUG - (Container) Registering types from "MenuComposerRegistrationModule"
[2016-05-16 13:17:00] DEBUG - (Container) Registering types from "MenuProviderRegistrationModule"
[2016-05-16 13:17:00] DEBUG - (Container) Finished container initialization.
[2016-05-16 13:17:01] DEBUG - (Runtime.Eto.Main) Creating MainWindow...
[2016-05-16 13:17:01] DEBUG - (Runtime.Eto.MenuBuilder) Composing menu...
[2016-05-16 13:17:01] DEBUG - (Runtime.Eto.MenuBuilder) Building menu...
[2016-05-16 13:17:01] DEBUG - (Runtime.Eto.Main) Starting application...
[2016-05-16 13:17:03] DEBUG - (Runtime.Eto.Main) Stopping application...
[2016-05-16 13:17:03] DEBUG - (Container) Disposing the container...
Jeśli chcesz dostawać powiadomienia na maila kiedy dodaję nowy post, możesz zasubskrybować mój blog wypełniając formularz poniżej.