Najlepsze praktyki dotyczące rejestrowania i śledzenia w .NET

53

Dużo czytałem o śledzeniu i logowaniu, próbując znaleźć złotą zasadę najlepszych praktyk w tej sprawie, ale nie ma żadnej. Ludzie mówią, że dobrzy programiści produkują dobre śledzenie, ale ujmując to w ten sposób, musi to wynikać z doświadczenia.

Czytałem również podobne pytania tutaj i przez Internet i nie są one tak naprawdę tym samym pytaniem lub nie mają satysfakcjonującej odpowiedzi, być może dlatego, że pytania nie zawierają pewnych szczegółów.

Tak więc ludzie mówią, że śledzenie powinno w pewnym sensie powtórzyć doświadczenie debugowania aplikacji w przypadkach, w których nie można dołączyć debugera. Powinien zapewniać wystarczający kontekst, aby można było zobaczyć, która ścieżka jest pobierana w każdym punkcie kontrolnym w aplikacji.

Idąc głębiej, możesz nawet rozróżnić śledzenie od rejestrowania zdarzeń, ponieważ „rejestrowanie zdarzeń różni się od śledzenia tym, że przechwytuje główne stany, a nie szczegółowy przepływ kontroli”.

Teraz powiedz, że chcę wykonywać śledzenie i rejestrowanie przy użyciu tylko standardowych klas .NET, tych w System.Diagnosticsprzestrzeni nazw. Doszedłem do wniosku, że klasa TraceSource jest lepsza dla zadania niż statyczna klasa Trace, ponieważ chcę rozróżnić poziomy śledzenia i za pomocą klasy TraceSource mogę przekazać parametr informujący o typie zdarzenia, używając klasy Trace, której muszę użyć Trace.WriteLineIfa następnie zweryfikuj rzeczy takie jak SourceSwitch.TraceInformationi SourceSwitch.TraceErrors, a nawet nie ma właściwości takich jak TraceVerboselub TraceStart.

Mając to na uwadze, czy warto rozważyć dobrą praktykę, aby wykonać następujące czynności:

  • Śledzenie zdarzenia „Start” podczas rozpoczynania metody, która powinna reprezentować pojedynczą operację logiczną lub potok, wraz z ciągiem reprezentującym wartości parametrów przekazanych do metody.
  • Śledź zdarzenie „Informacje” podczas wstawiania elementu do bazy danych.
  • Śledź zdarzenie „Informacja”, wybierając jedną lub drugą ścieżkę w ważnej instrukcji if / else.
  • Śledź „Krytyczny” lub „Błąd” w bloku catch w zależności od tego, czy jest to błąd możliwy do odzyskania.
  • Śledź zdarzenie „Stop” po zakończeniu wykonywania metody.

Ponadto wyjaśnij, kiedy najlepiej śledzić typy zdarzeń Pełne i Ostrzeżenie. Jeśli masz przykłady kodu z ładnym śledzeniem / rejestrowaniem i chcesz się nim podzielić, byłoby to doskonałe.

Uwaga: znalazłem tutaj kilka dobrych informacji, ale wciąż nie to, czego szukam: http://msdn.microsoft.com/en-us/magazine/ff714589.aspx

Levidad
źródło
jakaś aplikacja pełnego kodu źródłowego korzystająca z dobrych wzorców do logowania?
Kiquenet
Szczerze mówiąc ... Gdybym pracował z .NET, prawdopodobnie po prostu zainstalowałbym coś takiego jak New Relic i nazwałbym to gotowym. (Być może nie jest to dobra opcja w momencie, gdy został opublikowany)
svidgen

Odpowiedzi:

17

Ważność typów śledzenia musi być wybrana nie ze względu na to, gdzie śledzenie znajduje się w kodzie, ale dlatego, że śledzony komunikat jest mniej lub bardziej ważny. Przykład:

Śledzenie zdarzenia „Start” podczas rozpoczynania metody, która powinna reprezentować pojedynczą operację logiczną lub potok, wraz z ciągiem reprezentującym wartości parametrów przekazanych do metody.

Użyj typu początkowego podczas uruchamiania operacji logicznej. Nie oznacza to, że ślad początkowy musi znajdować się na początku metody, ani nie oznacza, że ​​metoda musi mieć ślad początkowy.

To powiedziawszy, w większości przypadków logiczna operacja faktycznie rozpocznie się na początku metody. W przeciwnym razie należy zadać sobie pytanie, czy kod jest poprawnie refaktoryzowany.

Śledzenie parametrów może być złym pomysłem . Musisz pomyśleć, co prześledzić, przypadek po przypadku. Na przykład bardzo źle jest prześledzić parametry metody void Authenticate(string userName, string plainPassword).

Śledź zdarzenie „Informacje” podczas wstawiania elementu do bazy danych.

To zależy. Niektóre przedmioty muszą być śledzone, ale nie każdy przedmiot.

  • Wyobraź sobie na przykład, że wstawiasz element dziennika do bazy danych. Czy śledziłbyś dzienniki? A potem rejestrować ślady? A następnie śledzić rejestrowanie śladu?
  • Kolejny przykład: wstawiasz poufne dane. Wymaga to audytu. Skoro sprawdziłeś wstawienie, po co je śledzić?

Śledź zdarzenie „Informacja”, wybierając jedną lub drugą ścieżkę w ważnej instrukcji if / else.

Znowu to zależy.

Śledzenie „krytycznego” lub „błędu” w bloku catch w zależności od pogody jest to błąd, który można naprawić.

Działanie podjęte po nieusuwalnym błędzie może być czymś więcej niż śledzeniem. Na przykład po stronie serwera chcesz zapisać wyjątek w bazie danych do dalszej analizy. Ponadto niektóre wyjątki są mniej ważne niż inne i nie wymagają śledzenia.

Śledź zdarzenie „Stop” po zakończeniu wykonywania metody.

Zobacz pierwszy punkt.

wyjaśnij, kiedy najlepiej śledzić typy zdarzeń Pełne i Ostrzeżenie.

Gadatliwy:

Verbose służy do śledzenia tego, co należy śledzić, gdy coś naprawdę się nie powiedzie. Oznacza to, że w większości przypadków wyłączysz śledzenie pełnych wiadomości, ale czasami musisz debugować niektóre części kodu, aby zrozumieć, dlaczego coś nie działa w przypadku krawędzi.

Zwykle masz wiele pełnych komunikatów, które pozwalają naprawdę dobrze zrozumieć przepływ aplikacji. Oznacza to również, że te wiadomości muszą być wyłączone przez większość czasu, ponieważ:

  • w przeciwnym razie dziennik będzie się bardzo szybko rozwijać,
  • nie potrzebujesz ich przez większość czasu,
  • mogą zawierać poufne dane na temat przepływu aplikacji.

Pomyśl o gadatliwości jako narzędziu, którego musisz używać, gdy nie masz dostępu do debugera.

Ostrzeżenie:

Śledzenie typu ostrzeżenia jest używane, gdy dzieje się coś złego i ważnego, ale nie jest zbyt istotne, aby traktować go jako błąd. Na przykład niska pamięć RAM może emitować ostrzeżenie, ale nie ma powodu, aby śledzić błąd, ponieważ aplikacja może być kontynuowana, nawet jeśli będzie wolniejsza niż zwykle.

Przykłady:

  • Przykład 1: aplikacja nie otworzyła pliku, który użytkownik chciał otworzyć. Plik istnieje i nie jest używany, uprawnienia są ustawione poprawnie, ale coś blokuje otwarcie pliku. W takim przypadku wyśledzisz błąd , ponieważ aplikacja nie może zarządzać tą sprawą i nadal działa zgodnie z oczekiwaniami użytkownika (tzn. Faktycznie odczytuje plik).

  • Przykład 2: po sprawdzeniu błędu w pierwszym przykładzie okazuje się, że błąd jest spowodowany faktem, że ścieżka do pliku ma więcej niż 259 znaków. Więc refaktoryzuj swój kod, aby go złapać PathTooLongException. Gdy następnym razem użytkownik spróbuje otworzyć ten sam plik, nowa wersja aplikacji wyświetla komunikat wyjaśniający, że plik jest za długi i musi zostać przeniesiony do innego folderu, aby skrócić pełną ścieżkę w celu otwarcia tego pliku w ta aplikacja. Śledzisz także wiadomość .

  • Przykład 3: aplikacja spędziła dwadzieścia sekund na otwieraniu i analizowaniu małego pliku, podczas gdy większość plików potrzebuje dziesięć do stu milisekund na otwarcie i parsowanie. Śledzisz ostrzeżenie z odpowiednimi informacjami: typ dysku, na którym faktycznie znajduje się plik, system plików, rozmiar pliku, dokładny czas spędzony, czas pracy komputera itp. Gdy użytkownik skarży się, że zajmuje to dwadzieścia sekund, aby otworzyć plik, weź ślad, aby dowiedzieć się, co się stanie. Na przykład okazuje się, że ładowanie plików z udziału sieciowego trwa tak długo, jak komputer właśnie się uruchomił. Wyjaśniasz użytkownikowi, że opóźnienie wynika z sieci i nie jest związane z twoją aplikacją.

  • Przykład 4: otwarty plik jest wyświetlany niepoprawnie. Włączyć opisowy ślad gdzie rzeczywiście zobaczyć, w jaki sposób dane są ładowane z pliku, a następnie przetwarzany, krok po kroku.

Arseni Mourzenko
źródło
Jednym z wzorców, których używamy w miejscu pracy, jest rejestrowanie „Znanych błędów” jako ostrzeżeń i „Nieznanych błędów” jako błędów. Może nie być odpowiednie w zależności od infrastruktury i sposobu postępowania z ostrzeżeniami, ale działa dobrze dla nas.
Andrew Piliser
5
 > say I want to do my tracing and logging using only the standard .NET classes

System.Diagnostics jest świetny, ponieważ możesz skonfigurować, gdzie, które informacje śledzenia powinny iść, gdzie (plik, dziennik zdarzeń, baza danych, ...)

Niestety, jeśli chcesz korzystać System.Diagnostics, musisz wiedzieć z góry ( w wyznaczonym czasie ), które strumienie śledzenia powinny być możliwe do śledzenia. (W przykładowym artykule są to Transfer, Resume, Suspend, ...). Można je skonfigurować jako Wyłączone, Poziom debugowania lub Poziom błędu.

Wolę mieć system rejestrowania, w którym w czasie wykonywania mogę decydować na poziomie klasy / nazwach poziomów , jak szczegółowe powinno być rejestrowanie. Na przykład wszystkie Debugowanie i powyżej z, MyNamespace.Business.*ale nie MyNamespace.Business.Calculations.

Jeśli korzystasz z log4net (lub Common.logging), każda klasa otrzymuje własny rejestrator, dzięki czemu możesz łatwo zdecydować, które klasy mają być rejestrowane na danym poziomie.

Ponieważ operacje na bazach danych należą do osobnej klasy, nie ma już potrzeby ustanawiania odrębnej reguły

Trace an "Information" event when inserting an item into the database.

Zamiast tego wolę mieć te wytyczne:

  • Tracelevel powinien pokazywać podstawowy przepływ pracy
  • Poziom debugowania powinien pokazywać szczegółowe dane i przetwarzanie w przepływie pracy, w tym decyzje w przepływie programu z uzasadnieniem (Tworzenie nowego elementu, ponieważ element nie istniał w DB)
  • Infolevel dla uruchamiania / zatrzymywania usług i jeden wpis dla każdej rozpoczętej akcji / GUI
k3b
źródło
Rozumiem, to dobra informacja, dzięki! Ale czy tak, jak zadaję w moim pierwotnym pytaniu, czy mógłbyś wyjaśnić zastosowania typów zdarzeń Pełne i Ostrzeżenie? A także proszę innych, aby wnieśli swój wkład w ich punkt widzenia, ponieważ ten temat zasługuje na głębsze zbadanie, niż widziałem w Internecie.
Levidad
4

Możesz wypróbować strukturę Story , która ma unikalne podejście do rejestrowania, ponieważ „sprawia”, że zapisujesz wszystkie logi (i dodajesz inne istotne informacje) w kontekście, więc kiedy będziesz musiał je przeczytać później, otrzymasz wszystko, czego potrzebujesz.

Automatycznie doda pojęcia „start” i „stop” jako początek i koniec historii.

Za pomocą systemu opartego na regułach możesz kontrolować, co zrobić z każdą historią (kontekstem) na podstawie posiadanych informacji, na przykład wydrukować wszystkie historie, które zawierają błąd lub pochodzą od użytkownika „admin”.

Również więcej informacji na temat tego postu na blogu

Amit Apple
źródło
1
zaktualizowana odpowiedź z dodatkowymi informacjami
Amit Apple