Logger - wariacje na temat wyjść

Tekstem tym zaczynam krótką serię rozszerzającą temat loggerów. Temat ten rozwinięty został kiedyś w artykule o loggerach na Warsztacie i nie chcę powtarzać zamieszczonych tam informacji, dlatego zachęcam Cię, Czytelniku, byś się z nim zapoznał zanim zaczniesz czytać dalej. A w dzisiejszym odcinku porozmawiamy na temat różnych wyjść dla komunikatów loggera. Rodzaje wyjść Wymieńmy kilka rodzajów wyjść, które możemy chcieć uwzględnić pisząc swój system logowania:
  • Wyjście tekstowe - najważniejsze i najczęściej stosowane. Bezpośredni zapis komunikatów do pliku tekstowego, z ewentualnym niewielkim formatowaniem.
  • XHTML - zapis do pliku XHTML jest niewiele bardziej skomplikowany od wyjścia tekstowego - musi tylko ujmować komunikaty w odpowiednie tagi formatujące. Ta metoda pozwala nam na wizualne wyróżnianie komunikatów (np. zaznaczenie komunikatów o błędzie na czerwono). W połączeniu z arkuszami CSS log w tym formacie może się okazać bardzo przyjazny dla odczytującego, oraz nadawać się do natychmiastowego wrzucenia na stronę internetową.
  • XML - zapis w XML'u jest bardzo podobny do zapisu w XHTML, jednak pozwala programiście na wygodne zapisanie wszystkich informacji o komunikacie w postaci tagów XML. Tak stworzony plik może być zarówno odczytywany, jak i parsowany przez inne programy. Na GameDev.net można znaleźć wart przeczytania artykuł, który prezentuje możliwości zapisu w XML.
  • RTF - jest to ciekawy format zapisu, zaproponowany i omówiony w ciekawym artykule na GameDev.net. Oferuje on funkcjonalność podobną do plików XHTML.
  • OutputDebugString() - w systemie Windows mamy do dyspozycji funkcję OutputDebugString(), która wypisuje podany jej jako argument tekst do okna debuggera (jeśli ten jest włączony). Posiadanie takiego wyjścia warto rozważyć, jeśli korzystamy z debuggera w czasie tworzenia naszej aplikacji. Jako ciekawostkę polecam artykuł z CodeProject.com, w którym autor prezentuje klasę strumienia podobną do std::ostream korzystającą z OutputDebugString()
  • Konsola Windows - wspomniana już w artykule, do którego przeczytania zachęcałem na początku. To szczególne wyjście pozwala nam śledzić komunikaty o błędach w czasie rzeczywistym. System Windows pozwala też na łatwą zmianę kolorów wypisywanego tekstu, co dobrze współpracuje z komunikatami loggera o różnych priorytetach. Konsola Windows, gdy jest wyświetlana, ma jednak zabójczy wpływ na framerate (jeśli będzie zainteresowanie, to rozszerzę ten temat). Temat używania konsoli jest szerszy i osobiście zachęcam zapoznanie się z artykułem Regedita pod tytułem "Asynchroniczna konsola Windows".
  • Dziennik zdarzeń Windows - ten rodzaj wyjścia może być mało przydatny w grach, ale warto wspomnieć o jego istnieniu. Systemy Windows z rodziny NT prowadzą tak zwany dziennik zdarzeń, w którym logują ważne zdarzenia w systemie. Odczytać ten dziennik można przez narzędzie MMC. Temat sposobów zapisu do tego dziennika pozostawię Czytelnikowi do zbadania samodzielnie; podpowiem jedynie funkcję ReportEvent() (choć jeśli będzie zainteresowanie, to i o tym mogę tu napisać szerzej).
  • Wyjście w sieć - jeśli "po drugiej stronie" mamy uruchomiony odpowiedni program, to możemy stworzyć połączenie komunikaty loggera wysyłać przez sieć - czy to w obrębie lokalnej maszyny, czy to przez Internet. Zdalne debugowanie aplikacji to kolejny szeroki temat do omówienia; sygnalizuję teraz jedynie jego istnienie.
Ikonki? Na ciekawy pomysł wpadł Steel_Eagle, który w swojej wypowiedzi na forum Warsztatu wspomniał o używaniu kolorowych ikonek do oznaczania ważności komunikatów loggera. Ta koncepcja jest godna uwagi przy wyjściach do formatów XHTML i XML, gdyż może znacząco zwiększyć czytelność i uprzyjemnić korzystanie z loga. Formatowanie komunikatów Zastanawiasz się być może teraz, czy wszystkie te rodzaje wyjść trzeba zapisać w programie? Czy jest sens, żeby program wypluwał z siebie tyle różnych logów o tej samej treści? Powiem szczerze, że... nie. Nie byłoby to nawet rozsądne. Osobiście proponuję przemyśleć sposób, w jaki formatujemy komunikaty wyjściowe dla pliku tekstowego. Odwołując się do wielowyjściowego loggera omówionego w artykule polecanym na początku tego wpisu, polecam taki rodzaj formatu:
[TYP KOMUNIKATU] [CZAS] Klasa::Funkcja() - komunikat
Na przykład:
[S] [10:15:51] CTexture::Load() - loaded texture textures/font.tga - width: 512, height: 512, bpp: 32.
Typem komunikatu może być jedna literka, np. E - błąd, F - błąd fatalny, I - informacja, S - sukces, itd. Poza wartością estetyczną, taki zapis daje nam jedną bardzo dużą korzyść - plik tekstowy loga ma ustalony format. Pozwala nam to napisać prosty programik albo skrypt (na przykład w Perlu), który przeczyta nasz tekstowy log (zawierający przecież wszystkie informacje o komunikatach) i wygeneruje z niego logi w XHTML, XML, RTF i w czym tam jeszcze nie będziemy chcieli. W ten sposób zachowamy wygodę w czytaniu loga, a jednocześnie uprościmy program oraz życie osób, które logi będą nam wysyłać - wystarczy, że prześlą nam plik tekstowy. Zaproszenie do dyskusji Tyle na dzisiaj; w następnym odcinku wejdziemy głębiej w temat zapisywania komunikatów w loggerze wewnątrz programu. Na pewno masz, Czytelniku, jakieś przemyślenia dotyczące przedstawionej tu treści. Zachęcam do podzielenia się i podyskutowania na temat wyjść w loggerach.