Zalety rejestrowania strukturalnego w porównaniu do rejestrowania podstawowego


110

Tworzymy nową aplikację i chciałbym włączyć rejestrowanie strukturalne. Moja idealna konfiguracja byłaby podobna Serilogdo naszego kodu C # i Bunyannaszego JS. Te miały się zasilać, fluentda potem mogły przejść do dowolnej liczby rzeczy, początkowo myślałem elasticsearch + kibana. Mamy już bazę danych MySQL, więc w najbliższym czasie bardziej interesuje mnie konfiguracja Serilog + Bunyan i deweloperów, aby z niej korzystać i możemy logować się do MySQL, podczas gdy poświęcamy nieco więcej czasu na płynną i resztę.

Jednak jeden z naszych bardziej doświadczonych programistów wolałby po prostu zrobić coś takiego: log.debug("Disk quota {0} exceeded by user {1}", quota, user);używając, log4neta następnie po prostu uruchomić instrukcje select przeciwko MySQL, takie jak:SELECT text FROM logs WHERE text LIKE "Disk quota";

Biorąc to pod uwagę, które podejście jest lepsze i / lub jakie rzeczy należy wziąć pod uwagę przy wyborze rodzaju systemu rejestrowania?


Zgadzam się z wprowadzonymi zmianami. Nie tyle próbuję komuś coś udowodnić, co staram się zrozumieć korzyści i różnice w logowaniu strukturalnym i podstawowym. Moim zdaniem struktura zorganizowana daje nam znacznie większą elastyczność, szczególnie w źródłach dzienników i w jaki sposób jesteśmy w stanie wyświetlić ich dane. W tym momencie nie jestem w stanie wyjaśnić, dlaczego podstawowe logowanie i wyszukiwanie w MySQL jest lepsze / gorsze niż logowanie strukturalne.
DTI-Matt

2
@ Strukturalne rejestrowanie serilogu DTI-Matt jest zwykłym logowaniem, tylko formatuje obiekty, które na nim drukujesz - coś, co możesz zrobić sam, bardzo łatwo pokonując ToString. Ważniejszym aspektem jest konfiguracja i zarządzanie plikami dziennika, a nie jeden sposób formatowania ciągu na inny, innym jest wydajność. Jeśli deweloper chce użyć log4net (co jest dobrym logowaniem do biblioteki lib), to wybór serilog (który wygląda fajnie) jest jednym z tych „rozwiązań w poszukiwaniu problemu”.
gbjbaanb

@ DTI-Matt Patrząc na serilog, wygląda bardzo podobnie do log4net. log4net obsługuje tworzenie logów strukturalnych podczas konfiguracji. Nie trzeba przeszukiwać komunikatów w dzienniku, ponieważ można skonfigurować i zapisać dodatkowe informacje w tabeli. Skonfiguruj także log4net dla Fluentd tipstuff.org/2014/05/…
RubberChickenLeader

Uważaj, są głupcy, którzy nie rozumieją idei pytań koncepcyjnych. pytanie o kierunek aplikacji bazodanowych w celu uzyskania informacji na temat ich możliwości ETL v. kod spowoduje poważne negatywne opinie. Zakładam, że twoje pytanie też będzie na bloku do krojenia.
user3916597,

2
@gbjbaanb Serilog działa tak samo jak log4net podczas renderowania zdarzeń jako tekst, ale jeśli używasz formatu strukturalnego do przechowywania dzienników, będzie on wiązał nazwane właściwości z argumentami, które są przekazywane (tj. w celu obsługi wyszukiwania / filtrowania bez wyrażeń regularnych itp. ) HTH!
Nicholas Blumhardt,

Odpowiedzi:


140

Istnieją dwa podstawowe postępy w podejściu strukturalnym , których nie można emulować za pomocą dzienników tekstowych bez (czasem ekstremalnych) dodatkowego wysiłku.

Rodzaje zdarzeń

Kiedy piszesz dwa zdarzenia z log4net, takie jak:

log.Debug("Disk quota {0} exceeded by user {1}", 100, "DTI-Matt");
log.Debug("Disk quota {0} exceeded by user {1}", 150, "nblumhardt");

Spowoduje to wytworzenie podobnego tekstu:

Disk quota 100 exceeded by user DTI-Matt
Disk quota 150 exceeded by user nblumhardt

Ale jeśli chodzi o przetwarzanie maszynowe, to tylko dwa wiersze innego tekstu.

Możesz znaleźć wszystkie zdarzenia „Przekroczone miejsce na dysku”, ale uproszczony przypadek wyszukiwania zdarzeń like 'Disk quota%'spadnie, gdy tylko pojawi się inne zdarzenie wyglądające jak:

Disk quota 100 set for user DTI-Matt

Rejestrowanie tekstu odrzuca informacje, które początkowo posiadamy na temat źródła zdarzenia, i należy to zrekonstruować, czytając logi zwykle za pomocą coraz bardziej rozbudowanych wyrażeń dopasowania.

Natomiast podczas pisania następujących dwóch zdarzeń Serilog :

log.Debug("Disk quota {Quota} exceeded by user {Username}", 100, "DTI-Matt");
log.Debug("Disk quota {Quota} exceeded by user {Username}", 150, "nblumhardt");

Wywołują one tekst wyjściowy podobny do wersji log4net, ale za kulisami "Disk quota {Quota} exceeded by user {Username}" szablon wiadomości jest przenoszony przez oba zdarzenia.

Z odpowiednim ujściem możesz później pisać zapytania where MessageTemplate = 'Disk quota {Quota} exceeded by user {Username}'i uzyskiwać dokładnie zdarzenia, w których limit miejsca został przekroczony.

Nie zawsze wygodne jest przechowywanie całego szablonu wiadomości przy każdym zdarzeniu dziennika, więc niektóre zatapiają szablon wiadomości w EventTypewartości liczbowej (np. 0x1234abcd), Lub możesz dodać wzbogacenie do potoku rejestrowania, aby zrobić to sam .

Jest bardziej subtelny niż kolejna różnica poniżej, ale jest niezwykle potężny w przypadku dużych objętości kłód.

Dane strukturalne

Ponownie, biorąc pod uwagę dwa zdarzenia dotyczące wykorzystania miejsca na dysku, może być dość łatwe przy użyciu dzienników tekstowych, aby zapytać o konkretnego użytkownika like 'Disk quota' and like 'DTI-Matt'.

Jednak diagnostyka produkcji nie zawsze jest tak prosta. Wyobraź sobie, że konieczne jest znalezienie zdarzeń, w których przekroczony limit miejsca był mniejszy niż 125 MB?

Z Serilog jest to możliwe w większości zlewów przy użyciu wariantu:

Quota < 125

Konstruowanie tego rodzaju zapytań z wyrażenia regularnego jest możliwe, ale szybko się męczy i zwykle jest miarą ostateczności.

Teraz dodaj do tego typ zdarzenia:

Quota < 125 and EventType = 0x1234abcd

Zaczynasz widzieć, jak te możliwości łączą się w prosty sposób, dzięki czemu debugowanie produkcyjne za pomocą dzienników wydaje się być działaniem programistycznym najwyższej klasy.

Kolejną zaletą, być może nie tak łatwą do uniknięcia z góry, ale po usunięciu debugowania produkcyjnego z krainy hakowania wyrażeń regularnych, programiści zaczynają bardziej doceniać dzienniki i bardziej uważnie pisząc je. Lepsze logi -> aplikacje lepszej jakości -> więcej szczęścia dookoła.


4
uwielbiam tę odpowiedź. bardzo dobrze napisany iz jakiegoś powodu nie potrafię wyjaśnić, utrzymuje mnie na krawędzi siedzenia.
Jokab

16

Podczas zbierania dzienników do przetworzenia, czy to parsowania do jakiejś bazy danych i / lub późniejszego przeszukiwania przetworzonych dzienników, korzystanie z rejestrowania strukturalnego sprawia, że ​​niektóre przetwarzanie jest łatwiejsze / bardziej wydajne. Analizator składni może wykorzystać znaną strukturę ( np. JSON, XML, ASN.1, cokolwiek) i używać maszyn stanu do parsowania, w przeciwieństwie do wyrażeń regularnych (których kompilacja i wykonanie może być drogie obliczeniowo (względnie). Analiza tekstu w dowolnej formie, takiego jak sugerowany przez współpracownika, zwykle polega na wyrażeniach regularnych i na niezmiennym tekście . Może to sprawić, że parsowanie tekstu swobodnego będzie raczej kruche ( tzn. Parsowanie jest ściśle powiązane z dokładnym tekstem w kodzie).

Rozważ również przypadek wyszukiwania / wyszukiwania, np . :

SELECT text FROM logs WHERE text LIKE "Disk quota";

LIKEwarunki wymagają porównań z każdą textwartością wiersza; znowu jest to względnie drogie obliczeniowo, szczególnie gdy używa się symboli wieloznacznych:

SELECT text FROM logs WHERE text LIKE "Disk %";

W przypadku rejestrowania strukturalnego komunikat dziennika związany z błędem dysku może wyglądać tak w JSON:

{ "level": "DEBUG", "user": "username", "error_type": "disk", "text": "Disk quota ... exceeded by user ..." }

Pola tego rodzaju struktury można dość łatwo odwzorować np. Na nazwy kolumn tabeli SQL, co oznacza, że ​​wyszukiwanie może być bardziej szczegółowe / szczegółowe:

SELECT user, text FROM logs WHERE error_type = "disk";

Możesz umieszczać indeksy w kolumnach, których wartości będą często wyszukiwać / wyszukiwać, o ile nie użyjesz LIKEklauzul dla tych wartości kolumn . Im bardziej możesz podzielić swój dziennik na określone kategorie, tym bardziej ukierunkowane możesz dokonać wyszukiwania. Na przykład, oprócz error_typepola / kolumny w powyższym przykładzie, możesz zrobić parzyste "error_category": "disk", "error_type": "quota"lub takie.

Im bardziej struktura masz w wiadomościach dziennika, systemy bardziej swój parsowanie / wyszukiwanie (takie jak fluentd, elasticsearch, kibana) mogą skorzystać z tej struktury i wykonywać swoje zadania z większą prędkością i mniejszą CPU / pamięci.

Mam nadzieję że to pomoże!


1
+1 Chcę dodać, że nie chodzi tylko o szybkość i wydajność. Trafność wyników wyszukiwania będzie o wiele wyższa, gdy użyje się rejestrowania strukturalnego, a tym samym „zapytań strukturalnych”. Bez tego poszukiwanie słów, które występują w różnych kontekstach, da ci mnóstwo nieistotnych trafień.
Marjan Venema,

1
+1 ode mnie też, myślę, że to gwoździ. Dodano nieco inną formułę poniżej, aby rozszerzyć również o typy zdarzeń.
Nicholas Blumhardt,

8

Rejestrowanie strukturalne nie przyniesie większych korzyści, gdy aplikacja tworzy kilkaset dzienników wiadomości. Z pewnością to zrobisz, gdy będziesz mieć kilkaset komunikatów dziennika na sekundę pochodzących z wielu różnych wdrożonych aplikacji.

Powiązane, konfiguracja, w której komunikaty dziennika kończą się na stosie ELK, jest również odpowiednia dla skali, w której logowanie do SQL staje się wąskim gardłem.

Widziałem konfigurację „podstawowego rejestrowania i wyszukiwania” z SQL select .. likei regexps przesunięte do granic możliwości tam, gdzie się rozpada - są fałszywe pozytywy, pominięcia, okropny kod filtru z błędami knwon, które są trudne do utrzymania i nikt nie chce ich dotykać, nowe komunikaty w dzienniku, które nie są zgodne z założeniami filtru, niechęć do dotykania instrukcji rejestrowania w kodzie, aby nie złamać raportów itp.

Pojawia się kilka pakietów oprogramowania, które lepiej radzą sobie z tym problemem. Jest Serilog, słyszę, że zespół NLog na to patrzy , i napisaliśmy StructuredLogging.Jsondo Nlog , widzę również, że nowe abstrakcje rejestrowania rdzenia ASP.Net „umożliwiają dostawcom rejestrowania wdrożenie… rejestrowania strukturalnego”.

Przykład z StructuredLogging. Logujesz się do rejestratora NLog, takiego jak to:

logger.ExtendedError("Order send failed", new { OrderId = 1234, RestaurantId = 4567 } );

Te uporządkowane dane trafiają do kibana. Wartość 1234jest przechowywana w OrderIdpolu wpisu dziennika. Następnie możesz wyszukiwać za pomocą składni zapytania kibana np. Wszystkie wpisy w dzienniku gdzie @LogType:nlog AND Level:Error AND OrderId:1234.

Messagei OrderIdsą teraz tylko polami, które można wyszukiwać w celu dopasowania dokładnego lub niedokładnego według potrzeb, lub agregować w celu obliczenia. Jest to potężne i elastyczne.

Z najlepszych praktyk StructuredLogging :

Zarejestrowana wiadomość powinna być za każdym razem taka sama. Powinien być ciągiem ciągłym, a nie ciągiem sformatowanym tak, aby zawierał wartości danych, takie jak identyfikatory lub ilości. Następnie łatwo jest wyszukać.

Zarejestrowany komunikat powinien być wyraźny, tzn. Nie taki sam jak komunikat wygenerowany przez niepowiązaną instrukcję dziennika. Zatem wyszukiwanie go również nie pasuje do niepowiązanych rzeczy.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.