Właściwości:
Log to obiekt klasy dziedziczącej z interfejsu common::ILog. Reprezentuje miejsce, do którego mogą trafiać logowane komunikaty i odpowiada za ich zapisywanie do tego miejsca. Może to być na przykład plik tekstowy w jakimś formacie, realizowana z użyciem jakiegoś API konsola albo cokolwiek.
Prawidłowa sekwencja wywołań wygląda jak w przykładzie:
// 1. Utworzenie loggera // Utworzenie logów common::CreateLogger(false); common::Logger & Logger = common::GetLogger(); common::TextFileLog *Log = new common::TextFileLog("Log.txt", common::FILE_MODE_NORMAL, common::EOL_CRLF); // 2. Konfiguracja logów // Konfiguracja loggera // Zarejestrowanie logów Logger.AddLogMapping(0xFFFFFFFF, Log); // 3. Używanie w czasie pracy programu Logger.Log(1, "Komunikat 1"); Logger.Log(1, "Komunikat 2"); Logger.Log(1, "Komunikat 3"); // 4. Usunięcie loggera common::DestroyLogger(); // 5. Usunięcie logów delete Log;
Bardzo ważne jest, aby logi usuwać dopiero po usunięciu loggera. Ważne też, by po rozpoczęciu używania loggera nie dokonywać już żadnej konfiguracji loggera ani logów, nie tworzyć nowych logów itd.
Typ komunikatu to maska bitowa. Można jej nadać dowolne znaczenie, np.:
Komunikaty logujemy za pomocą metody common::Logger::Log podając kolejno typ i treść. Logger wysyła go do zera, jednego lub wielu logów zależnie od mapowania. Podczas rejestrowania logów w loggerze podajemy maskę bitową, która będzie łączona operatorem & z typem komunikatu i jeśli wynik będzie niezerowy, komunikat trafi do danego loga. W ten sposób można mapować tylko wybrane typy komunikatów na wybrane logi. Log zarejestrowany z maską 0xFFFFFFFF otrzyma wszystkie komunikaty o niezerowym typie.
Przykład mapowania typów komunikatów na logi:
Logger.AddLogMapping(0xFFFFFFFF, Log1); Logger.AddLogMapping(1, Log2); Logger.Log(1, "Komunikat 1"); Logger.Log(2, "Komunikat 2"); Logger.Log(3, "Komunikat 3");
W tym przykładzie do Log1 trafią wszystkie komunikaty, a do Log2 tylko te, których typ ma ustawiony najmłodszy bit, czyli komunikaty 1 i 3.
Nie należy rejestrować logów w loggerze więcej niż raz.
%D - data%T - czas%1 ... %3 - własne informacje prefiksu%% - znak "\%"Format prefiksu można ustawić dla loga metodą common::ILog::SetPrefixFormat(). Można też ustawić na raz format prefiksu dla wszystkich logów zarejestrowanych w loggerze metodą common::Logger::SetPrefixFormat(). Ustawianie formatu prefiksu jest częścią procesu konfiguracji.
Własne informacje prefiksu to trzy łańcuchy, które można zmieniać w czasie działania programu (ich zmiana jest częścią procesu używania loggera) i które mogą być dołączane do prefiksu. Są wspólne dla całego loggera. Do ich zmiany służy metoda common::Logger::SetCustomPrefixInfo(). Można je wykorzystywać np. do wskazania numeru bieżącej klatki gry czy innych tym podobnych rzeczy.
Prefiks typu to dodatkowy prefiks dołączany za prefiksem głównym do treści logowanego komunikatu. Jest ustalonym na stałe łańcuchem. Każdy log ma własne mapowanie masek typów na prefiksy typu. Można to mapowanie wykonać metodą common::ILog::AddTypePrefixMapping(). Metoda common::Logger::AddTypePrefixMapping() loggera dokonuje go jednocześnie dla wszystkich zarejestrowanych w nim logów. Jest to część procesu konfiguracji.
Przykład:
Log1->SetPrefixFormat("[%D %T %1] "); Log1->AddTypePrefixMapping(1, "(!) "); Logger.SetCustomPrefixInfo(0, "Frame:123"); Logger.Log(1, "Komunikat 1"); Logger.Log(2, "Komunikat 2"); Logger.Log(3, "Komunikat 3");
Da w efekcie mniej więcej takie wyjście:
[2006-08-18 21:52:28 Frame:123] (!) Komunikat 1 [2006-08-18 21:52:28 Frame:123] Komunikat 2 [2006-08-18 21:52:28 Frame:123] (!) Komunikat 3
W przypadku kiedy typ danego komunikatu pasuje do wielu mapowań na prefiks, wykorzystane zostanie pierwsze z nich. Dlatego mapowania należy dodawać w kolejności od najbardziej szczegółowych do najbardziej ogólnych. Na przykład jeśli chcemy dodać mapowanie które dotyczy "wszystkich pozostałych" komunikatów, dodajemy je z maską 0xFFFFFFFF na samym końcu.
Tryb z kolejką jest szybszy, ale tryb bez kolejki jest bardziej niezawodny w wypadku awarii programu. W trybie z kolejką finalizacja loggera może potrwać dłuższą chwilę, jeśli wymaga poczekania na zalogowanie zalegających w kolejce komunikatów.
Kolejność wywołań logowania komunikatów i zmiany własnych informacji prefiksu jest respektowana także w trybie z kolejką.
Loggery plikowe można otwierać w trzech trybach:
Tryb z kolejką w połączeniu z common::FILE_MODE_NORMAL jest najszybszy.
Tryb bez kolejki w połączeniu z common::FILE_MODE_REOPEN jest najpewniejszy - daje gwarancję, że nawet w przypadku nagłego wysypania się programu wszystko, co było wcześniej logowane trafiło do logów.
Logowanie i zmiana własnych informacji prefiksu są bezpieczne wątkowo. Można ich dokonywać z wielu wątków na raz.
Klasa ta nie musi być bezpieczna wątkowo - o bezpieczeństwo wątkowe dba sam logger. Metody tej klasy mogą być wywoływane z różnych wątków, ale nigdy nie będą wywoływane równocześnie.
1.5.5