Rejestrowanie najlepszych praktyk [zamknięte]

323

Chciałbym poznać historie o tym, jak ludzie radzą sobie ze śledzeniem i logowaniem prawdziwych aplikacji. Oto kilka pytań, które mogą pomóc wyjaśnić twoją odpowiedź.

Ramy

Z jakich ram korzystasz?

  • log4net
  • System.Diagnostics.Trace
  • System.Diagnostics.TraceSource
  • Blok aplikacji do rejestrowania
  • Inny?

Jeśli korzystasz ze śledzenia, czy korzystasz z Trace.Correlation.StartLogicalOperation?

Czy piszesz ten kod ręcznie, czy używasz do tego jakiejś formy programowania aspektowego? Chcesz udostępnić fragment kodu?

Czy zapewniasz jakąkolwiek formę szczegółowości w stosunku do źródeł śledzenia? Np. TraceSources WPF pozwalają skonfigurować je na różnych poziomach:

  • System.Windows - ustawienia dla wszystkich WPF
  • System.Windows.Animation - przesłonięcie specjalnie dla animacji.

Słuchacze

Jakich wyników dziennika używasz?

  • Pliki tekstowe
  • Pliki XML
  • Dziennik zdarzeń
  • Inny?

Jeśli używasz plików, czy używasz dzienników kroczących, czy tylko jednego pliku? W jaki sposób udostępniasz dzienniki użytkownikom?

Przeglądanie

Jakich narzędzi używasz do przeglądania dzienników?

  • Notatnik
  • Ogon
  • Podgląd zdarzeń
  • Systems Center Operations Manager / Microsoft Operations Manger
  • Przeglądarka śledzenia usługi WCF
  • Inny?

Jeśli budujesz rozwiązanie ASP.NET, czy używasz również monitorowania kondycji ASP.NET? Czy dołączasz dane wyjściowe śledzenia do zdarzeń monitorowania kondycji? Co z Trace.axd?

Co z niestandardowymi licznikami wydajności?

Paul Stovell
źródło
3
Byłoby pomocne, gdyby osoby zamykające takie pytania za pomocą 300 upvotes mogły zasugerować albo format wiki, albo zamieścić post na programmers.stackexchange, albo Quora, jeśli tego typu pytania nie są mile widziane. Oczywiście pytanie jest bardzo konstruktywne, po prostu nie spełnia kryteriów, które chce StackOverflow. programmers.stackexchange.com/questions/57064/... ma 24 głosy poparcia. Być może StackOverflow czegoś brakuje?
Niall Connaughton
Jeśli to pytanie narusza format pytań i odpowiedzi, oznacza to, że TO Coś NIEPRAWIDŁOWEGO z formatem pytań i odpowiedzi, a nie z tym pytaniem. Czasami decyzja, czy pytanie powinno zostać zamknięte, powinna zależeć od udzielonych odpowiedzi, niektóre pytania otwarte zapraszają do debaty, ale inne zachęcają użytkowników do dostarczania cennych treści, takich jak ta!
Matthias Wolf,
1
To pytanie - szczególnie najlepsza odpowiedź - prawdopodobnie stanowiłoby doskonałą podstawę do wpisu na blogu, gdyby ktoś chciał użyć go jako takiego ... Jako obiektywne pytanie, nie pasuje do niego - ma wyraźną strukturę ankiety - ale poniżej jest kilka dobrych informacji, stąd blokada.
Shog9 10.10.13

Odpowiedzi:

232

Aktualizacja: Aby uzyskać rozszerzenia System.Diagnostics, podając niektóre brakujące nasłuchiwania, których możesz chcieć, zobacz Essential.Diagnostics w CodePlex ( http://essentialdiagnostics.codeplex.com/ )


Ramy

P: Z jakich ram korzystasz?

Odp .: System.Diagnostics.TraceSource, wbudowany w .NET 2.0.

Zapewnia potężne, elastyczne i wydajne rejestrowanie aplikacji, jednak wielu programistów nie zdaje sobie sprawy z jego możliwości i nie korzysta z nich w pełni.

Istnieje kilka obszarów, w których dodatkowa funkcjonalność jest przydatna lub czasami funkcjonalność istnieje, ale nie jest dobrze udokumentowana, jednak nie oznacza to, że cała struktura rejestrowania (która ma być rozszerzalna) powinna zostać wyrzucona i całkowicie zastąpiona, jak niektóre popularne alternatywy (NLog, log4net, Common.Logging, a nawet rejestrowanie EntLib).

Zamiast zmieniać sposób dodawania instrukcji rejestrowania do aplikacji i ponownego wynalezienia koła, po prostu rozszerzyłem platformę System.Diagnostics w kilku potrzebnych miejscach.

Wydaje mi się, że inne frameworki, nawet EntLib, po prostu cierpią na syndrom Nie wymyślony tutaj i myślę, że zmarnowali czas na ponowne opracowanie podstaw, które już działają doskonale w System.Diagnostics (takich jak pisanie instrukcji dziennika), zamiast uzupełniać kilka istniejących luk. Krótko mówiąc, nie używaj ich - nie są potrzebne.

Funkcje, których możesz nie znać:

  • Korzystanie z przeciążeń TraceEvent, które pobierają ciąg formatu i argumenty, może pomóc w wydajności, ponieważ parametry są przechowywane jako osobne odwołania, dopóki nie zakończy się powodzeniem Filter.ShouldTrace (). Oznacza to brak kosztownych wywołań ToString () dla wartości parametrów, dopóki system nie potwierdzi komunikatu.
  • Trace.CorrelationManager umożliwia korelowanie instrukcji dziennika dotyczących tej samej operacji logicznej (patrz poniżej).
  • VisualBasic.Logging.FileLogTraceListener jest dobry do pisania w plikach dziennika i obsługuje rotację plików. Chociaż w przestrzeni nazw VisualBasic, można go równie łatwo używać w projekcie C # (lub innym języku), po prostu dołączając bibliotekę DLL.
  • Gdy używasz EventLogTraceListener, jeśli wywołujesz TraceEvent z wieloma argumentami i ciągiem pustego lub pustego formatu, wówczas argumenty są przekazywane bezpośrednio do EventLog.WriteEntry (), jeśli używasz zlokalizowanych zasobów wiadomości.
  • Narzędzie Service Trace Viewer (z WCF) jest przydatne do przeglądania wykresów plików dziennika skorelowanych z aktywnością (nawet jeśli nie używasz WCF). Może to naprawdę pomóc w debugowaniu złożonych problemów, w których bierze udział wiele wątków / działań.
  • Unikaj narzutu, usuwając wszystkie detektory (lub usuwając domyślny); w przeciwnym razie Default przekaże wszystko do systemu śledzenia (i poniesie wszystkie te koszty ogólne ToString ()).

Obszary, które warto rozważyć rozszerzenia (w razie potrzeby):

  • Detektor śledzenia bazy danych
  • Kolorowy odbiornik śledzenia konsoli
  • Detektory śledzenia MSMQ / e-mail / WMI (w razie potrzeby)
  • Zaimplementuj FileSystemWatcher, aby wywoływać Trace.Refresh w celu dynamicznych zmian konfiguracji

Inne zalecenia:

Użyj identyfikatorów zdarzeń strukturalnych i przechowuj listę referencji (np. Udokumentuj je w wyliczeniu).

Posiadanie unikalnych identyfikatorów zdarzeń dla każdego (znaczącego) zdarzenia w systemie jest bardzo przydatne do korelowania i znajdowania określonych problemów. Łatwo jest wyśledzić konkretny kod, który rejestruje / używa identyfikatorów zdarzeń, i może ułatwić podanie typowych błędów, np. Błąd 5178 oznacza, że ​​łańcuch połączenia z bazą danych jest nieprawidłowy itp.

Identyfikatory zdarzeń powinny mieć jakąś strukturę (podobną do teorii kodów odpowiedzi używanych w wiadomościach e-mail i HTTP), która pozwala traktować je według kategorii bez znajomości określonych kodów.

np. pierwsza cyfra może określać klasę ogólną: 1xxx można użyć do operacji „Start”, 2xxx do normalnego zachowania, 3xxx do śledzenia aktywności, 4xxx do ostrzeżeń, 5xxx do błędów, 8xxx do operacji „Stop”, 9xxx do błędów krytycznych, itp.

Druga cyfra może szczegółowo określać obszar, np. 21xx dla informacji o bazie danych (41xx dla ostrzeżeń bazy danych, 51xx dla błędów bazy danych), 22xx dla trybu obliczeń (42xx dla ostrzeżeń obliczeniowych itp.), 23xx dla innego modułu itp.

Przypisane, ustrukturyzowane identyfikatory zdarzeń pozwalają również używać ich w filtrach.

P: Jeśli korzystasz ze śledzenia, czy korzystasz z Trace.Correlation.StartLogicalOperation?

Odp .: Trace.CorrelationManager jest bardzo przydatny do korelowania instrukcji dziennika w dowolnym środowisku wielowątkowym (co w dzisiejszych czasach jest prawie wszystkim).

Musisz przynajmniej ustawić ActivityId jeden raz dla każdej operacji logicznej, aby dokonać korelacji.

Start / Stop i LogicalOperationStack mogą być następnie użyte w prostym kontekście stosu. W przypadku bardziej złożonych kontekstów (np. Operacji asynchronicznych) użycie TraceTransfer do nowego ActivityId (przed zmianą) pozwala na korelację.

Narzędzie Service Trace Viewer może być przydatne do przeglądania wykresów aktywności (nawet jeśli nie używasz WCF).

P: Czy piszesz ten kod ręcznie, czy używasz do tego jakiejś formy programowania aspektowego? Chcesz udostępnić fragment kodu?

Odp .: Możesz chcieć utworzyć klasę zasięgu, np. LogicalOperationScope, która (a) ustanawia kontekst po utworzeniu i (b) resetuje kontekst po usunięciu.

Umożliwia to pisanie kodu, takiego jak poniżej, w celu automatycznego zawijania operacji:

  using( LogicalOperationScope operation = new LogicalOperationScope("Operation") )
  {
    // .. do work here
  }

Podczas tworzenia zakres może najpierw ustawić ActivityId, jeśli to konieczne, wywołać StartLogicalOperation, a następnie zarejestrować komunikat TraceEventType.Start. Przy Dispose może zarejestrować komunikat Stop, a następnie wywołać StopLogicalOperation.

P: Czy zapewniasz jakąkolwiek formę szczegółowości w stosunku do źródeł śledzenia? Np. TraceSources WPF pozwalają skonfigurować je na różnych poziomach.

Odp .: Tak, wiele źródeł śledzenia jest użytecznych / ważnych w miarę powiększania się systemów.

Chociaż prawdopodobnie chcesz konsekwentnie rejestrować wszystkie ostrzeżenia i powyżej lub wszystkie informacje i powyższe komunikaty, dla dowolnego systemu o rozsądnych rozmiarach objętość śledzenia aktywności (Start, Stop itp.) I rejestrowanie pełne stają się po prostu zbyt duże.

Zamiast tylko jednego przełącznika, który włącza lub wyłącza wszystko, warto włączyć te informacje dla jednej sekcji systemu na raz.

W ten sposób możesz zlokalizować znaczące problemy na podstawie zwykłego logowania (wszystkie ostrzeżenia, błędy itp.), A następnie „powiększyć” wybrane sekcje i ustawić je na śledzenie aktywności lub nawet poziomy debugowania.

Liczba potrzebnych źródeł śledzenia zależy od aplikacji, np. Możesz potrzebować jednego źródła śledzenia na zespół lub główną sekcję aplikacji.

Jeśli potrzebujesz jeszcze bardziej precyzyjnej kontroli, dodaj indywidualne przełączniki logiczne, aby włączyć / wyłączyć określone śledzenie dużych głośności, np. Zrzuty nieprzetworzonych wiadomości. (Lub można zastosować osobne źródło śledzenia, podobne do WCF / WPF).

Możesz także rozważyć oddzielne źródła śledzenia dla śledzenia aktywności w porównaniu do rejestrowania ogólnego (inne), ponieważ może to nieco ułatwić skonfigurowanie filtrów dokładnie tak, jak chcesz.

Pamiętaj, że wiadomości mogą być nadal skorelowane przez ActivityId, nawet jeśli używane są różne źródła, więc używaj ich tyle, ile potrzebujesz.


Słuchacze

P: Jakich wyników dziennika używasz?

Może to zależeć od rodzaju aplikacji, którą piszesz i od tego, co jest rejestrowane. Zwykle różne rzeczy idą w różnych miejscach (tj. Wiele wyników).

Generalnie dzielę wyniki na trzy grupy:

(1) Zdarzenia - Dziennik zdarzeń Windows (i pliki śledzenia)

np. jeśli piszesz serwer / usługę, najlepszą praktyką w systemie Windows jest korzystanie z dziennika zdarzeń Windows (nie masz interfejsu użytkownika do zgłoszenia).

W takim przypadku wszystkie zdarzenia krytyczne, błędy, ostrzeżenia i informacje (na poziomie usługi) powinny przejść do dziennika zdarzeń systemu Windows. Poziom informacji powinien być zarezerwowany dla tego rodzaju zdarzeń wysokiego poziomu, które chcesz przejść do dziennika zdarzeń, np. „Uruchomiono usługę”, „Zatrzymano usługę”, „Połączono z Xyz”, a może nawet „Zapoczątkowano harmonogram” , „Zalogowany użytkownik” itp.

W niektórych przypadkach możesz chcieć, aby zapisywanie w dzienniku zdarzeń było wbudowaną częścią aplikacji, a nie przez system śledzenia (tj. Zapisywanie wpisów w dzienniku zdarzeń bezpośrednio). Oznacza to, że nie można go przypadkowo wyłączyć. (Pamiętaj, że nadal chcesz odnotować to samo zdarzenie w systemie śledzenia, abyś mógł skorelować).

W przeciwieństwie do tego aplikacja GUI systemu Windows generalnie zgłasza je użytkownikowi (chociaż mogą one także logować się do dziennika zdarzeń systemu Windows).

Zdarzenia mogą mieć również powiązane liczniki wydajności (np. Liczbę błędów / s), i może być ważne koordynowanie dowolnego bezpośredniego zapisu do dziennika zdarzeń, liczników wydajności, zapisu do systemu śledzenia i raportowania do użytkownika, aby wystąpiły o o tym samym czasie.

tzn. jeśli użytkownik zobaczy komunikat o błędzie w określonym czasie, powinieneś być w stanie znaleźć ten sam komunikat o błędzie w Dzienniku zdarzeń systemu Windows, a następnie to samo zdarzenie z tym samym znacznikiem czasu w dzienniku śledzenia (wraz z innymi szczegółami śledzenia).

(2) Działania - pliki dziennika aplikacji lub tabela bazy danych (i pliki śledzenia)

Jest to regularna czynność wykonywana przez system, np. Obsługiwana strona internetowa, złożony handel giełdowy, przyjęte zamówienie, wykonane obliczenia itp.

Przydatne jest tutaj śledzenie aktywności (start, stop itp.) (Przy właściwej granulacji).

Ponadto bardzo często stosuje się konkretny dziennik aplikacji (czasami nazywany dziennikiem kontroli). Zwykle jest to tabela bazy danych lub plik dziennika aplikacji i zawiera ustrukturyzowane dane (tj. Zestaw pól).

Sprawy mogą się tu nieco rozmazać w zależności od aplikacji. Dobrym przykładem może być serwer WWW, który zapisuje każde żądanie w dzienniku internetowym; podobnymi przykładami może być system przesyłania komunikatów lub system obliczeń, w którym każda operacja jest rejestrowana wraz ze szczegółowymi danymi aplikacji.

Nie tak dobrym przykładem są transakcje giełdowe lub system zamówień sprzedaży. W tych systemach prawdopodobnie rejestrujesz już aktywność, ponieważ mają one ważną wartość biznesową, jednak zasada korelowania ich z innymi działaniami jest nadal ważna.

Oprócz niestandardowych dzienników aplikacji działania często mają również powiązane liczniki wydajności, np. Liczbę transakcji na sekundę.

Zasadniczo należy koordynować rejestrowanie działań w różnych systemach, tj. Zapisywać do dziennika aplikacji w tym samym czasie, gdy zwiększa się licznik wydajności i logować się do systemu śledzenia. Jeśli robisz to wszystko jednocześnie (lub bezpośrednio po sobie w kodzie), wówczas problemy z debugowaniem są łatwiejsze (niż jeśli wszystkie występują w różnych momentach / miejscach w kodzie).

(3) Śledzenie debugowania - plik tekstowy, a może XML lub baza danych.

Są to informacje na poziomie Verbose i niższym (np. Niestandardowe przełączniki boolean do włączania / wyłączania zrzutów surowych danych). Zapewnia to odwagę lub szczegóły tego, co robi system na poziomie poddziałania.

Jest to poziom, który chcesz włączyć / wyłączyć dla poszczególnych sekcji aplikacji (stąd wiele źródeł). Nie chcesz, aby te rzeczy zaśmiecały dziennik zdarzeń systemu Windows. Czasami używana jest baza danych, ale bardziej prawdopodobne są toczące się pliki dziennika, które są czyszczone po pewnym czasie.

Duża różnica między tymi informacjami a plikiem dziennika aplikacji polega na tym, że nie ma on struktury. Podczas gdy dziennik aplikacji może zawierać pola Do, Od, Kwota itp., Pełne ślady debugowania mogą być czymkolwiek, co programista wprowadza, np. „Sprawdzanie wartości X = {wartość}, Y = fałsz” lub losowe komentarze / znaczniki, takie jak „ Zrobiłem to, próbując ponownie ".

Jedną ważną praktyką jest upewnienie się, że rzeczy, które umieszczasz w plikach dziennika aplikacji lub Dzienniku zdarzeń systemu Windows, również są logowane do systemu śledzenia z tymi samymi szczegółami (np. Znacznik czasu). Pozwala to następnie skorelować różne dzienniki podczas badania.

Jeśli planujesz użyć konkretnej przeglądarki dziennika, ponieważ masz złożoną korelację, np. Service Trace Viewer, musisz użyć odpowiedniego formatu, np. XML. W przeciwnym razie zwykły plik tekstowy jest zwykle wystarczający - na niższych poziomach informacje są w dużej mierze nieustrukturyzowane, więc możesz znaleźć zrzuty tablic, zrzuty stosów itp. Pod warunkiem, że możesz skorelować się z bardziej uporządkowanymi dziennikami na wyższych poziomach, rzeczy powinny być w porządku.

P: Jeśli używasz plików, czy używasz dzienników kroczących, czy tylko jednego pliku? W jaki sposób udostępniasz dzienniki użytkownikom?

Odp .: W przypadku plików, na ogół chcesz przewijać pliki dziennika z punktu widzenia zarządzania (w System.Diagnostics wystarczy użyć VisualBasic.Logging.FileLogTraceListener).

Dostępność ponownie zależy od systemu. Jeśli mówisz tylko o plikach, to w przypadku serwera / usługi można uzyskać dostęp do plików w razie potrzeby. (Dziennik zdarzeń systemu Windows lub dzienniki aplikacji bazy danych miałyby własne mechanizmy dostępu).

Jeśli nie masz łatwego dostępu do systemu plików, śledzenie debugowania w bazie danych może być łatwiejsze. [tzn. zaimplementuj TraceListener bazy danych].

Jednym z ciekawych rozwiązań, jakie widziałem dla aplikacji GUI dla systemu Windows, było to, że rejestrował bardzo szczegółowe informacje o śledzeniu do „rejestratora lotu” podczas działania, a następnie, kiedy go wyłączałeś, jeśli nie miał problemów, po prostu usunął plik.

Jeśli jednak wystąpił błąd lub napotkał problem, plik nie został usunięty. Albo jeśli złapie błąd, albo przy następnym uruchomieniu zauważy plik, a następnie może podjąć działania, np. Skompresować go (np. 7zip) i wysłać pocztą e-mail lub w inny sposób udostępnić.

Wiele systemów obecnie obejmuje zautomatyzowane zgłaszanie awarii do centralnego serwera (po sprawdzeniu z użytkownikami, np. Ze względu na prywatność).


Przeglądanie

P: Jakich narzędzi używasz do przeglądania dzienników?

Odp .: Jeśli masz wiele dzienników z różnych powodów, będziesz używać wielu przeglądarek.

Notepad / vi / Notepad ++ lub jakikolwiek inny edytor tekstowy to podstawa dzienników zwykłego tekstu.

Jeśli masz skomplikowane operacje, np. Czynności związane z transferami, to oczywiście użyłbyś specjalistycznego narzędzia, takiego jak Service Trace Viewer. (Ale jeśli go nie potrzebujesz, edytor tekstu jest łatwiejszy).

Ponieważ generalnie loguję informacje wysokiego poziomu do Dziennika zdarzeń systemu Windows, zapewnia on szybki sposób uporządkowanego przeglądu (szukaj ładnych ikon błędów / ostrzeżeń). Musisz zacząć przeszukiwać pliki tekstowe tylko wtedy, gdy w dzienniku nie ma wystarczającej ilości, chociaż przynajmniej dziennik daje punkt wyjścia. (W tym momencie upewnianie się, że twoje logi są skoordynowane, staje się przydatne).

Ogólnie dziennik zdarzeń systemu Windows udostępnia te znaczące zdarzenia narzędziom monitorowania, takim jak MOM lub OpenView.

Inne -

Jeśli zalogujesz się do bazy danych, możesz łatwo filtrować i sortować informacje (np. Powiększyć konkretny identyfikator działania. (W plikach tekstowych możesz użyć Grep / PowerShell lub podobny do filtrowania na wybranym GUID)

MS Excel (lub inny program do obsługi arkuszy kalkulacyjnych). Może to być przydatne do analizowania informacji ustrukturyzowanych lub częściowo ustrukturyzowanych, jeśli można je zaimportować za pomocą odpowiednich separatorów, aby różne wartości trafiały do ​​różnych kolumn.

Podczas uruchamiania usługi w trybie debugowania / testowania zwykle hostuję ją w aplikacji konsolowej dla uproszczenia Uważam, że przydatny jest kolorowy rejestrator konsoli (np. Czerwony w przypadku błędów, żółty w przypadku ostrzeżeń itp.). Musisz zaimplementować niestandardowy detektor śledzenia.

Zauważ, że framework nie zawiera kolorowego rejestratora konsoli ani rejestratora bazy danych, więc w tej chwili musisz je napisać, jeśli ich potrzebujesz (nie jest to zbyt trudne).

Naprawdę denerwuje mnie to, że kilka frameworków (log4net, EntLib itp.) Zmarnowało czas na ponowne wynalezienie koła i ponowne wdrożenie podstawowego rejestrowania, filtrowania i logowania do plików tekstowych, dziennika zdarzeń systemu Windows i plików XML, każdy we własnym zakresie inny sposób (instrukcje dziennika są różne w każdym); każdy z nich zaimplementował następnie własną wersję, na przykład, rejestratora bazy danych, gdy większość z nich już istniała i wystarczyło jeszcze kilka detektorów śledzenia dla System.Diagnostics. Mów o dużym marnowaniu podwójnego wysiłku.

P: Jeśli budujesz rozwiązanie ASP.NET, czy używasz również monitorowania kondycji ASP.NET? Czy dołączasz dane wyjściowe śledzenia do zdarzeń monitorowania kondycji? Co z Trace.axd?

Te rzeczy można włączyć / wyłączyć w razie potrzeby. Uważam, że Trace.axd jest dość użyteczny do debugowania reakcji serwera na pewne rzeczy, ale ogólnie nie jest użyteczny w silnie używanym środowisku lub do długoterminowego śledzenia.

P: Co z niestandardowymi licznikami wydajności?

W przypadku profesjonalnej aplikacji, zwłaszcza serwera / usługi, spodziewam się, że będzie ona w pełni wyposażona w liczniki Monitora wydajności i logowanie do Dziennika zdarzeń systemu Windows. Są to standardowe narzędzia w systemie Windows i powinny być używane.

Musisz upewnić się, że dołączasz instalatory używanych liczników wydajności i dzienników zdarzeń; należy je utworzyć podczas instalacji (podczas instalacji jako administrator). Gdy aplikacja działa normalnie, nie powinna mieć uprawnień administratora (a więc nie będzie w stanie tworzyć brakujących dzienników).

Jest to dobry powód, aby ćwiczyć programowanie jako użytkownik niebędący administratorem (należy mieć osobne konto administratora, gdy trzeba zainstalować usługi itp.). W przypadku zapisywania w dzienniku zdarzeń platforma .NET automatycznie utworzy brakujący dziennik przy pierwszym zapisywaniu; jeśli rozwijasz się jako nie-administrator, złapiesz to wcześnie i unikniesz nieprzyjemnej niespodzianki, gdy klient instaluje system, a następnie nie będzie mógł go użyć, ponieważ nie działa jako administrator.

Sly Gryphon
źródło
Do Twojej wiadomości: Wystąpił problem polegający na tym, że awaria śledzenia Microsoft do pliku. Jeśli masz wiele procesów (lub wątków) zapisujących do tego samego pliku i kolidują one, w pliku dziennika pojawia się błąd blokowania dostępu na wyłączność systemu plików.
Jay
1
Infrastruktura System.Diagnostics jest bezpieczna dla wątków; domyślnym zachowaniem jest blokowanie frameworka, jednak można zastąpić TraceListener.IsThreadSafe, jeśli zapewni się własne blokowanie. Zobacz msdn.microsoft.com/en-us/library/… . W przypadku wielu procesów zwykle piszesz w osobnych plikach, ale zwróć uwagę, że Service Trace Viewer może załadować wiele plików śledzenia (np. Z wielu komputerów) i skorelować je za pomocą ActivityId.
Sly Gryphon
1
Może możesz zasugerować, jak używać TraceEvent () do rejestrowania wyjątków?
Dmitriy Sosunov
1
Czy nie jest to jedna z głównych wad tego System.Diagnostics.Trace, że jest ozdobiona, [Conditional("TRACE")]co sprawia, że ​​nie nadaje się do użytku w środowiskach produkcyjnych, w których rzadko koduje się z TRACEflagą?
Asbjørn Ulsberg
2
@asbjornu Domyślna konfiguracja kompilacji wersji w Visual Studio ma zdefiniowane TRACE (DEBUGA jest wyłączona dla kompilacji wersji); jeśli budujesz z linii poleceń, musisz to jednak włączyć.
Sly Gryphon
40

Muszę dołączyć do refrenu polecającego log4net, w moim przypadku pochodzącego z elastyczności platformy (desktop .Net / Compact Framework, 32/64-bit).

Jednak zawinięcie go w API własnej marki jest głównym anty-wzorcem . log4net.ILoggerjest już .Net odpowiednikiem otoki interfejsu API Commons Logging , więc sprzężenie jest już dla Ciebie zminimalizowane, a ponieważ jest to również biblioteka Apache, zwykle nie stanowi to problemu, ponieważ nie rezygnujesz z żadnej kontroli: rozwiąż ją, jeśli musieć.

Większość bibliotek opakowań domowych, które widziałem, popełnia także jedną lub więcej litanii błędów:

  1. Korzystanie z globalnego rejestratora singleton (lub równoważnie statycznego punktu wejścia), który traci dokładną rozdzielczość zalecanego wzorca rejestratora dla klasy bez żadnego innego wzmocnienia selektywności.
  2. Nie ujawnienie opcjonalnego Exceptionargumentu , co prowadzi do wielu problemów:
    • Sprawia to, że zasady rejestrowania wyjątków są jeszcze trudniejsze w utrzymaniu, więc nic nie dzieje się zgodnie z wyjątkami.
    • Nawet przy spójnej polityce sformatowanie wyjątku w ciąg znaków przedwcześnie powoduje utratę danych. Napisałem niestandardowego ILayoutdekoratora, który szczegółowo analizuje wyjątek w celu ustalenia łańcucha zdarzeń.
  3. Brak ujawnienia właściwościIsLevelEnabled , co odrzuca możliwość pominięcia kodu formatowania, gdy obszary lub poziomy rejestrowania są wyłączone.
Jeffrey Hantin
źródło
1
Zadanie polegało na przefakturowaniu (okropnego) wewnętrznego opakowania wokół log4j na coś nieco mniej okropnego (to nadal dość złe, ale jest to wynikiem dostosowania wymagań, które otrzymałem od log4j). Próbowałem wyeliminować globalny statyczny punkt wejścia, ale został zestrzelony. Naprawdę nie rozumiem o co chodzi. W naszym ustawieniu log4j jest tak mocno rozszerzony i przekręcony, że tak naprawdę jest po prostu używany jako dyspozytor zdarzeń; używamy go tylko dlatego, że ktoś zapytał „jak możemy do tego użyć log4j?” Albo użyj log4whittle, albo po prostu napisz swój własny framework. Środkowa droga jest bolesna.
Adam Jaskiewicz
25
Nie zgadzam się z twoją rekomendacją, aby nie owijać log4net. Owijanie go za pomocą cienkiego interfejsu API modelu dostawcy pozwala użytkownikom bibliotek klas na podłączenie ich ulubionej struktury rejestrowania. YMMV oczywiście, ale opisywanie go jako „głównego anty-wzoru” jest nieco dogmatyczne. Również fakt, że istnieją biblioteki opakowań z „litanią błędów”, nie jest dobrym argumentem przeciwko dobrze napisanemu opakowaniu.
Joe
1
Nazwanie czegoś anty-wzorem nie oznacza, że ​​zawsze jest to w 100% zły pomysł - tylko to, że powoduje tendencję do malowania się w kącie, jeśli nie jesteś ostrożny. Ponadto ILog / LogManager sam w sobie jest dobrze napisaną minibiblioteczką opakowania na obrazie rejestrowania wspólnego, który jest zawarty w zestawie log4net, ale nie ma powodu, dla którego nie można go wyodrębnić i przekształcić we właściwe rejestrowanie wspólne dla CLR.
Jeffrey Hantin
18

Często nie rozwijam się w asp.net, jednak jeśli chodzi o rejestratory, myślę, że wiele najlepszych praktyk jest uniwersalnych. Oto kilka moich przypadkowych przemyśleń na temat logowania, których nauczyłem się przez lata:

Ramy

  • Użyj środowiska abstrakcji programu rejestrującego - takiego jak slf4j (lub uruchom własne), aby oddzielić implementację programu rejestrującego od interfejsu API. Widziałem wiele frameworków rejestrujących, które przychodzą i odchodzą, i lepiej, abyś mógł bez problemu wprowadzić nową.
  • Spróbuj znaleźć platformę obsługującą różne formaty wyjściowe.
  • Spróbuj znaleźć platformę obsługującą wtyczki / niestandardowe filtry.
  • Użyj frameworka, który można skonfigurować za pomocą plików zewnętrznych, aby Twoi klienci / konsumenci mogli łatwo modyfikować dane wyjściowe dziennika, aby można je było łatwo odczytać w komercyjnych aplikacjach do zarządzania dziennikami.
  • Pamiętaj, aby nie przesadzać z niestandardowymi poziomami rejestrowania, w przeciwnym razie możesz nie być w stanie przejść do różnych ram rejestrowania.

Wyjście rejestratora

  • Staraj się unikać dzienników w stylu XML / RSS do rejestrowania, które może napotkać katastrofalne awarie. Jest to ważne, ponieważ jeśli wyłącznik zasilania zostanie wyłączony bez rejestratora zapisującego </xxx>znacznik zamykający , dziennik zostanie uszkodzony.
  • Zaloguj wątki. W przeciwnym razie śledzenie przebiegu programu może być bardzo trudne.
  • Jeśli musisz internacjonalizować swoje dzienniki, możesz chcieć, aby programista logował się tylko w języku angielskim (lub w wybranym przez Ciebie języku).
  • Czasami możliwość wstawienia instrukcji rejestrowania do zapytań SQL może uratować życie w sytuacjach debugowania. Jak na przykład:
    - Wywoływanie klasy: com.foocorp.foopackage.FooClass: 9021
    WYBIERZ * Z foo;
  • Chcesz rejestrowania na poziomie klasy. Zwykle nie chcesz również statycznych wystąpień rejestratorów - nie warto mikrooptymalizować.
  • Oznaczanie i kategoryzowanie zarejestrowanych wyjątków jest czasem przydatne, ponieważ nie wszystkie wyjątki są sobie równe. Znając podzbiór ważnych wyjątków, czas jest pomocny, jeśli masz monitor dziennika, który musi wysyłać powiadomienia o stanach krytycznych.
  • Filtry duplikacji oszczędzą Twój wzrok i dysk twardy. Czy naprawdę chcesz, aby ta sama instrukcja rejestrowania była powtarzana 10 ^ 10000000 razy? Czy nie byłoby lepiej po prostu otrzymać wiadomość: This is my logging statement - Repeated 100 times

Zobacz także moje pytanie .

Eliasz
źródło
5
filtry do duplikacji to świetny pomysł
Paul Stovell
Kiedyś zgadzałem się na problem z uszkodzonym tagiem, ale większość dobrych pisarzy XML i tak nie używa pełnego XML (tzn. nie ma elementu głównego), aby mogli się logować bez ładowania DOM DOM. w rzadkim przypadku, gdy pojawia się problem z częściowo napisanym wpisem, można go naprawić ręcznie
Paul Stovell,
Od lat zajmuję się logowaniem XML. Teraz wydaje mi się to przesadne. Jeśli potrzebowałem kanału RSS o statusie aplikacji, myślę, że lepiej ją zaimplementować za pomocą narzędzia do monitorowania dziennika.
Elijah
Zgadzam się na RSS. Myślę więcej o narzędziach do wizualizacji, które pozwalają lepiej zrozumieć wpis. z plikami tekstowymi zazwyczaj chcesz zachować wpis w jednym wierszu; ale czasami chcesz dołączyć ślady stosu lub obiekty zserializowane. tutaj przydaje się dziennik XML (używany przez WCF)
Paul Stovell
+1 za wzmiankę o instrumentacji zapytań SQL. Jest to rzeczywiście bardzo przydatne do korelacji śladów bazy danych i śladów aplikacji. Robię to ręcznie w moim DAL, ale zastanawiam się, jakie wsparcie dla narzędzi jest dostępne dla tej techniki?
Constantin
17

Nie mam uprawnień do komentowania logowania do .Net, ponieważ moim chlebem i masłem jest Java, ale przez ostatnie 8 lat mieliśmy migrację podczas logowania, możesz znaleźć przydatną analogię do swojego pytania.

Zaczęliśmy od rejestratora Singleton, który był używany przez każdy wątek w JVM, i ustawiliśmy poziom rejestrowania dla całego procesu. Spowodowało to powstanie ogromnych dzienników, gdybyśmy musieli debugować nawet bardzo określoną część systemu, więc lekcja numer jeden polega na segmentowaniu rejestrowania.

Nasze obecne wcielenie rejestratora pozwala na wiele instancji z jedną zdefiniowaną jako domyślną. Możemy utworzyć dowolną liczbę podrzędnych programów rejestrujących, które mają różne poziomy rejestrowania, ale najbardziej użytecznym aspektem tej architektury jest możliwość tworzenia programów rejestrujących dla poszczególnych pakietów i klas po prostu poprzez zmianę właściwości rejestrowania. Lekcja druga polega na stworzeniu elastycznego systemu, który pozwala przesłonić jego zachowanie bez zmiany kodu.

Korzystamy z biblioteki dzienników wspólnych Apache owiniętej wokół Log4J.

Mam nadzieję że to pomoże!

* Edytować *

Po przeczytaniu poniższego wpisu Jeffreya Hantina zdałem sobie sprawę, że powinienem był zauważyć, czym tak naprawdę stało się nasze wewnętrzne opakowanie rejestrujące. Obecnie jest to w zasadzie fabryka i jest ściśle używany do uzyskania działającego programu rejestrującego przy użyciu poprawnego pliku właściwości (który z wcześniejszych powodów nie został przeniesiony do domyślnej pozycji). Ponieważ możesz teraz określić plik konfiguracyjny rejestrowania w wierszu poleceń, podejrzewam, że stanie się on jeszcze bardziej uproszczony, a jeśli zaczynasz nową aplikację, zdecydowanie zgodzę się z jego stwierdzeniem, że nie powinieneś nawet zawracać sobie głowy pakowaniem programu rejestrującego.

Steve Moyer
źródło
Dziękuję za odpowiedź. czy tworzysz podrzędne programy rejestrujące ręcznie w kodzie (tj. czy są one zakodowane na stałe) czy za pomocą jakiejś automatycznej / niejawnej rzeczy?
Paul Stovell,
Nie ... jeśli dodamy konfigurację rejestrowania do plików dziennika.properties dla pakietu lub klasy, zostaną one zarejestrowane zgodnie z tą konfiguracją, ale każdy pakiet lub klasa, która nie została specjalnie skonfigurowana, zostanie zarejestrowana na domyślnych poziomach.
Steve Moyer
9

Używamy Log4Net w pracy jako dostawcy rejestrowania, z opakowaniem singletonu dla instancji dziennika (chociaż singleton jest sprawdzany, pytając, czy jest to dobry pomysł, czy nie).

Wybraliśmy go z następujących powodów:

  • Prosta konfiguracja / rekonfiguracja w różnych środowiskach
  • Dobra liczba gotowych programów dołączających
  • Jeden z używanych przez nas CMS już go ma
  • Niezła liczba poziomów logów i konfiguracji wokół nich

Powinienem wspomnieć, że mówi to z punktu widzenia programowania ASP.NET

Widzę pewne zalety korzystania ze śledzenia, które jest w środowisku .NET, ale nie jestem w pełni sprzedawany, głównie dlatego, że komponenty, z którymi pracuję, nie wykonują żadnych wywołań śledzenia. Jedyne, czego często używam, to to, System.Net.Mailco mogę powiedzieć.

Mamy więc bibliotekę, która otacza log4net, aw naszym kodzie potrzebujemy tylko takich rzeczy:

Logger.Instance.Warn("Something to warn about");
Logger.Instance.Fatal("Something went bad!", new Exception());

try {
  var i = int.Parse("Hello World");
} catch(FormatException, ex) {
  Logger.Instance.Error(ex);
}

W ramach metod sprawdzamy, czy poziom rejestrowania jest włączony, więc nie masz zbędnych wywołań do interfejsu API log4net (więc jeśli debugowanie nie jest włączone, instrukcje debugowania są ignorowane), ale kiedy mam trochę czasu Będę go aktualizować, aby je ujawnić, abyś mógł sam sprawdzić. Zapobiegnie to przeprowadzaniu ocen, gdy nie powinny, np .:

Logger.Instance.Debug(string.Format("Something to debug at {0}", DateTime.Now);

Stanie się to:

if(Logger.DebugEnabled) Logger.Instance.Debug(string.Format("Something to debug at {0}", DateTime.Now);

(Zaoszczędź trochę czasu wykonania)

Domyślnie logujemy się w dwóch lokalizacjach:

  1. System plików witryny (w nieobsługiwanym rozszerzeniu)
  2. Wysyłanie wiadomości e-mail z powodu błędu i błędu krytycznego

Pliki są wykonywane jako zwijanie każdego dnia lub 10 MB (IIRC). Nie korzystamy z EventLog, ponieważ może wymagać większego bezpieczeństwa niż często chcemy dać stronie.

Uważam, że Notatnik działa dobrze do odczytu dzienników.

Aaron Powell
źródło
Struktury rejestrowania są jednym z niewielu przypadków, w których singleton nie jest niewłaściwie wykorzystywany.
mmcdole
Może być tak, jeśli chcesz zapewnić kontekst wokół swojego programu rejestrującego. Ale pomaga radzić sobie ze współbieżnością
Aaron Powell
7
Zdecydowanie wyrwałbym singletona. Z pewnością możesz mieć jedną instancję, która jest przekazywana (najlepiej w kontenerze IOC / DI). Spróbowałbym również przenieść logowanie do przechwytywacza ....
yfeldblum
2
Nie jest też fanem pojedynczej instancji. Wolę nadać każdej klasie rejestrator o unikalnej nazwie, więc zwiększanie lub zmniejszanie rejestrowania dla poszczególnych modułów jest łatwe.
Jeffrey Hantin
8

Z jakich ram korzystasz?

Używamy mieszanki bloku aplikacji rejestrującej i niestandardowego pomocnika rejestrującego, który działa wokół bitów frameworku .Net. LAB jest skonfigurowany do generowania dość obszernych plików dziennika, w tym oddzielnych ogólnych plików śledzenia dla wejścia / wyjścia metody serwisowej i określonych plików błędów w przypadku nieoczekiwanych problemów. Konfiguracja obejmuje datę / godzinę, wątek, identyfikator itp. Do pomocy w debugowaniu, a także pełne szczegóły wyjątku i stos (w przypadku nieoczekiwanego wyjątku).

Niestandardowy pomocnik rejestrowania korzysta z Trace.Correlation i jest szczególnie przydatny w kontekście logowania w WF. Na przykład mamy maszynę stanu, która wywołuje szereg sekwencyjnych przepływów pracy. Przy każdej z tych czynności invoke rejestrujemy początek (przy użyciu StartLogicalOperation), a następnie na końcu zatrzymujemy operację logiczną za pomocą procedury obsługi zdarzenia powrotu gereric.

Przydało się to kilka razy podczas próby debugowania błędów w złożonych sekwencjach biznesowych, ponieważ pozwala nam szybciej określać takie decyzje, jak oddziały If / Else itp. Na podstawie sekwencji wykonywania działań.

Jakich wyników dziennika używasz?

Używamy plików tekstowych i plików XML. Pliki tekstowe są konfigurowane przez blok aplikacji, ale mamy również dane wyjściowe XML z naszej usługi WF. Umożliwia nam to przechwytywanie zdarzeń środowiska wykonawczego (trwałość itp.), A także ogólnych wyjątków typu biznesowego. Pliki tekstowe są dziennikami kroczącymi, które są walcowane według dnia i rozmiaru (uważam, że całkowity rozmiar 1 MB jest punktem przejścia).

Jakich narzędzi używasz do przeglądania dzienników?

Używamy Notatnika i Przeglądarki Śledzenia Usług WCF w zależności od grupy wyników, na którą patrzymy. Przeglądarka śledzenia usługi WCF jest naprawdę bardzo przydatna, jeśli poprawnie skonfigurowałeś wyjście i może znacznie ułatwić odczyt. To powiedziawszy, jeśli i tak z grubsza wiem, gdzie jest błąd - dobrze jest też dobrze odczytać plik z adnotacjami.

Dzienniki są wysyłane do pojedynczego katalogu, który jest następnie dzielony na podkatalogi na podstawie usługi źródłowej. Katalog główny jest ujawniany za pośrednictwem strony internetowej, której dostęp jest kontrolowany przez grupę użytkowników wsparcia. Pozwala nam to spojrzeć na dzienniki produkcji bez konieczności zgłaszania żądań i przechodzenia przez długie procedury biurokratyczne dla danych produkcyjnych.

Steve Godbold
źródło
6

Jako autorzy narzędzia używamy oczywiście SmartInspect do rejestrowania i śledzenia aplikacji .NET. Zwykle używamy nazwanego protokołu potoku do rejestrowania na żywo i (zaszyfrowanych) plików dziennika binarnego dla dzienników użytkowników końcowych. Używamy konsoli SmartInspect jako narzędzia do przeglądania i monitorowania.

Istnieje naprawdę sporo struktur rejestrowania i narzędzi dla platformy .NET. DotNetLogging.com oferuje przegląd i porównanie różnych narzędzi .

Dennis G.
źródło
5

W odpowiedziach jest wiele świetnych rekomendacji.

Ogólna najlepsza praktyka polega na rozważeniu, kto będzie czytał dziennik. W moim przypadku będzie to administrator na stronie klienta. Więc loguję wiadomości, które dają im coś, na czym mogą działać. Na przykład „Nie można zainicjować aplikacji. Jest to zwykle spowodowane przez ......”

Matthew Sposato
źródło
1

Używamy log4net w naszych aplikacjach internetowych.

Możliwość dostosowania rejestrowania w czasie wykonywania przez zmianę pliku konfiguracyjnego XML jest bardzo przydatna, gdy aplikacja działa nieprawidłowo w czasie wykonywania i trzeba zobaczyć więcej informacji.

Pozwala także kierować określone klasy lub atrybuty do logowania. Jest to bardzo przydatne, gdy masz pomysł, gdzie występuje błąd. Klasycznym przykładem jest NHibernate, w którym chcesz zobaczyć tylko SQL przechodzący do bazy danych.

Edytować:

Wszystkie zdarzenia zapisujemy w bazie danych i systemie śledzenia. Dziennik zdarzeń, którego używamy w przypadku błędów lub wyjątków. Rejestrujemy większość zdarzeń w bazie danych, abyśmy mogli tworzyć niestandardowe raporty i pozwolić użytkownikom przeglądać dziennik, jeśli chcą bezpośrednio z aplikacji.

Jeffrey Cameron
źródło
Czy możesz podać więcej szczegółów na temat korzystania z niego? Czy logujesz się do pliku lub dziennika zdarzeń? Czy jest to ciągły plik dziennika? Co robisz, aby go zabezpieczyć lub wykonać kopię zapasową? Interesuje mnie rzeczywiste użytkowanie.
Paul Stovell,