Tworzenie logów działania aplikacji w .NET

Prędzej czy później w życiu każdego programisty przychodzi czas, kiedy zaczyna pisać oprogramowanie coraz bardziej rozbudowane, realizujące całą masę różnych zadań. Co za tym idzie, prędzej czy później zajdzie też potrzeba śledzenia poczynań takich aplikacji. Przyczyn takiego stanu rzeczy może być wiele, od najbardziej banalnych (sprawdzanie poprawności działania aplikacji i co za tym idzie ułatwione diagnozowanie błędów) po bardziej „wyrafinowane” (tworzenie logów z działania serwera, co dostarcza często ważnych informacji o jego pracy). Jednak czy każda trochę bardziej rozbudowana aplikacja powinna tworzyć logi ze swojego działania? Kiedy warto poświęcić swój czas i wysiłek w implementację mechanizmu rejestrującego logi, a kiedy zwyczajnie tworzenie czegoś takiego mija się z celem? Ostatnio trochę się nad tym zastanawiałem, a efektem moich przemyśleń jest właśnie ten wpis. Zapraszam do lektury 🙂

Po co właściwie tworzyć logi?

Na samym początku warto zastanowić się, jakie zastosowanie właściwie logi mają. Można je spotkać najczęściej w przypadku różnorakich serwerów. Powiadamiają o tym, kto, skąd i kiedy się do nich logował, jakie czynności wykonał itd. Są nieocenionym źródłem informacji dla administratorów, pozwalają zajrzeć w przeszłość, przechowując dane o wykonanych wcześniej operacjach. Pozwala to na przykład namierzyć adres, z którego złodziej zalogował się na konto w banku i sprawdzić jakie czynności na nim wykonał. Gdyby takie zdarzenia nie były logowane, to po ewentualnej kradzieży nie zostałby żaden ślad. Tak, więc pierwszym zadaniem logów jest zapisywanie informacji o wszystkich wykonywanych przez aplikację operacjach (np. logowanie, przelewy, różnorakie transfery danych). Takie informacje zazwyczaj będą przydatne dla użytkownika, który z oprogramowania korzysta. Logi mogą jednak pełnić również funkcję diagnostyczną, wskazywać na funkcje, które aktualnie wykonuje program i informować o ewentualnych problemach w jego działaniu. Takie informacje z kolei mogą okazać się bardzo przydatne w diagnozowaniu i naprawianiu błędów w tworzonym oprogramowaniu. Wiadomo – podczas tworzenia aplikacji nie da się przewidzieć absolutnie wszystkiego, zawsze może dojść do sytuacji, kiedy u jakiegoś użytkownika „coś nie działa”, a my nie jesteśmy stwierdzić dlaczego. Wtedy takie logi mogą nieść nieocenioną pomoc w zdiagnozowaniu i rozwiązaniu problemu.

Kiedy tworzyć logi?

No dobrze. Powiedzieliśmy już sobie, że logi mogą pełnić funkcję informującą o przebiegu działania jakiejś aplikacji. Nie ulega więc wątpliwości, że kiedy specyfika działania programu tego wymaga, to powinna je rejestrować. Aplikacją o takiej specyfice będzie najczęściej (jak wcześniej wspominałem) serwer. W takim przypadku bez logów obejść się nie da (widział ktoś serwery nietworzące logów? 🙂 ).  Jednak nie oznacza to, że tylko takie aplikacje powinny tworzyć logi ze swojego działania – w końcu to czy istnieje taka potrzeba, wynika bezpośrednio z pełnionych przez nie zadań. Myślę, że jeżeli chodzi o logowanie czysto „informacyjne”, to sprawa w tym momencie jest całkowicie jasna. Jednak logi mogą pełnić także inną rolę… ułatwiającą diagnozowanie błędów w oprogramowaniu. Czy w takiej sytuacji zasadnym jest śledzić przebieg działania całego programu w sposób, w jaki zrobiłem to ja?

No… może jakoś bardzo nie przedobrzyłem. W końcu pomiędzy tymi linijkami można upchnąć jeszcze kilka linijek informujących o przebiegu działania aplikacji. Jednak czy nawet te trzy linijki mają jakąkolwiek wartość w przypadku diagnostyki jakiegoś nieznanego mi błędu? Raczej nie… W takim razie, po co je zapisywać do logu? Ani to wygodne (w końcu trzeba to dopisać w poszczególnych klasach/metodach), ani potrzebne (po co tworzyć zbędne pliki?). Do takich konkluzywnych wniosków doszedłem niestety już po implementacji w/w mechanizmu, ale… nic straconego. Przynajmniej ogarnąłem sobie podstawy podstaw NLog’a. Z kolei co się dodało, można przecież usunąć 🙂 . No dobrze, ale skoro takie podejście jest dosyć bezsensowne, to co w końcu logować? Moja odpowiedź brzmi: tylko i wyłącznie nieobsłużone wyjątki. Znanych też raczej logować nie trzeba. No, bo po co skoro je przewidzieliśmy? Przynajmniej w przypadku aplikacji takiego typu jak moja. Wiadomo, inny projekt może wymagać innego podejścia i jest to zupełnie normalne (błędy [niekoniecznie wyjątki!] mogą pojawić się przecież w różnych miejscach). Tylko jak logować takie nieobsłużone wyjątki? Sam do niedawna nie wiedziałem, że w ogóle istnieje taka (jakże użyteczna) opcja:

Nic więcej, nic mniej… Każdy nieobsłużony wyjątek zostanie wychwycony, a jego treść zapisana do pliku. A to wszystko bez żadnych wspomagaczy typu „NLog”. No, bo po co instalować taki kombajn, żeby zapisać dane w jedym miejscu? 🙂 Czego chcieć więcej, w przypadku tak prostych aplikacji?

Narzędzia ułatwiające tworzenie logów w .NET

No dobrze, mimo że doszedłem do wniosku, że tworzenie rozbudowanych logów w mojej aplikacji mija się z celem i tylko marnuje cenny czas, to nie oznacza to, że tobie się to nie przyda. Może właśnie pracujesz nad czymś, co logi zwyczajnie tworzyć powinno. Co zrobić w takim przypadku? Oczywiście, jeżeli logi mają być zapisywane z różnych miejsc w kodzie, to raczej nie warto wynajdować koła od nowa i użyć gotowego rozwiązania. Jednym z nich z pewnością będzie biblioteka NLog (tworzona zresztą przez naszego rodaka 🙂 ). Dostępna dla prawie wszystkich technologii, gdzie używa się C#. Pozwala ona na bardzo łatwe tworzenie logów działania aplikacji. Jeżeli potrzebujemy, możemy je zapisywać do kilku miejsc jednocześnie, np. w lokalizacji sieciowej, pliku, przekazywać do konsoli i wiele, wiele więcej. Osobiście korzystałem tylko z opcji zapisywana logów do pliku, bo nie miałem innej potrzeby. Wszystko można łatwo ustawić w pliku konfiguracyjnym. No, ale najpierw należałoby dodać bibliotekę do projektu. W tym celu należy zainstalować pakiet NuGeta:

Po zakończeniu instalacji, do projektu zostanie dodany plik NLog.config. W dużym uproszczeniu, to właśnie tutaj możemy ustawić sobie, gdzie mają być kierowane logi. W przypadku, kiedy chcemy tylko zapisywać je do pliku, plik config będzie prezentował się następująco:

Po modyfikacji w/w pliku, można właściwie przejść do istoty rzeczy – czyli logowania zdarzeń występujących w kodzie. W tym celu w każdej z klas, których działanie ma być logowanie, należy stworzyć statyczne pole typu Logger. Następnie przy użyciu jego metod, możemy zacząć zapisywać logi:

Logger udostępnia kilka poziomów logowania. Są to:

Fatal Poziom najwyższy. Powinien rejestrować błędy uniemożliwiające dalsze działanie aplikacji.
Error Tutaj powinny być rejestrowane błędy i wyjątki, które nie unieruchamiają aplikacji „na amen”.
Warn Po prostu ostrzeżenia.
Info Informacje typu „zalogowano użytkownika” etc.
Debug Informacje wyświetlane w przypadku debugowania.
Trace Najbardziej szczegółowe informacje o przebiegu działania aplikacji. Np. metoda a, wywołała metodę b z parametrem c. (swoją drogą… używa ktoś tego? Moim zdaniem kod zaciemnia momentalnie :P). Z drugiej strony ułatwia diagnostykę…

No i to właściwie na tyle, jeżeli chodzi o NLog’a. Używanie tego cudeńka jest naprawdę bardzo proste. Oczywiście jego możliwości na tym się nie kończą, jednak główna funkcjonalność prezentuje się właśnie w taki sposób.

A wy jak podchodzicie do tematu logowania działania aplikacji? Kiedy go używacie, a kiedy sobie odpuszczacie? Jakie rzeczy logujecie, a jakie nie? Jestem ciekawy waszego zdania 🙂

326 total views, 2 views today

Jedno przemyślenie nt. „Tworzenie logów działania aplikacji w .NET

  1. Pingback: dotnetomaniak.pl

Możliwość komentowania jest wyłączona.