2011-02-17 21 views
22

Poszukuję małego, lekkiego systemu logowania w języku C++. Znalazłem kilka istniejących frameworków, ale w tej chwili nie potrzebuję wszystkich ich funkcji. Głównie szukam małego systemu, który może na przykład skonfigurować plik wyjściowy poziomu dziennika. Szukam istniejącego rozwiązania, ponieważ nie chcę wymyślać koła.Mała klasa rejestratora

+5

Jeśli nie chcesz odkrywać koła na nowo, dlaczego nie używasz istniejącego rozwiązania do rejestrowania? [log4cpp] (http://log4cpp.sourceforge.net/) wygląda dobrze – Nekresh

+0

Witam Herzl, jakie jest twoje środowisko? Visual C++ i żaden zarządzany kod w ogóle? w .NET istnieje koncepcja detektorów śledzenia/debugowania, które mogą być konfigurowane za pomocą poziomu logu i różnych detektorów, takich jak plik, konsola, okno wyjściowe itd. Nie jestem pewien, co jest wbudowane w surowe C++ prawdopodobnie nic .. –

+0

Zakładam, że już to widziałeś, prawda? http://www.codeproject.com/KB/cpp/CPP_logging.aspx –

Odpowiedz

36

Gorąco polecam ten prosty system rejestrowania: http://www.drdobbs.com/cpp/201804215. Składa się z pojedynczego pliku nagłówkowego. I z powodzeniem stosować go na Linux, Windows i Mac OS X.

napisać w dzienniku tak:

FILE_LOG(logWARNING) << "Ops, variable x should be " << expectedX << "; is " << realX; 

Naprawdę lubię składni strumienia. Jest dyskretny, bezpieczny dla słów i ekspresyjny. Struktura rejestrowania automatycznie dodaje wartość \n na końcu wiersza, a także datę, godzinę i wcięcie.

Konfigurowanie dzienników jest całkiem proste:

FILELog::ReportingLevel() = logDEBUG3; 
FILE* log_fd = fopen("mylogfile.txt", "w"); 
Output2FILE::Stream() = log_fd; 

Ramy jest również łatwo rozszerzyć. W pracy wprowadziliśmy ostatnio pewne modyfikacje, aby teraz używać std::ofstream zamiast FILE*. W rezultacie możemy teraz dodawać ładne funkcje, takie jak szyfrowanie dzienników, przez łańcuchy strumieni.

+0

Gdzie mogę go pobrać? –

+6

ftp://ftp.drdobbs.com/sourcecode/ddj/2007/0710.zip. "log.h" jest najlepszym plikiem; druga to mniej elastyczna wersja bez szablonów. Przesłałem go tutaj, na wypadek, gdyby dr Dobbs ponownie przetasował go: http://pastie.org/1574516. –

+1

Nie sądzisz, że chciałbyś podzielić się swoimi zmianami w odniesieniu do strumienia? –

1

This question ma swoją próbę z pewną fancyzmacją. Jest to całkowicie standardowe C++ i nie tworzy żadnych założeń platformy. To w zasadzie składa się z tymczasowego obiektu używane tak:

Debug(5) << "This is level 5 debug info.\n"; 

Jestem pewien, że można dowiedzieć się, jak określić różne pliki i inne rzeczy, gdy masz podstawowy układ. Starałem się, aby klasa była zorganizowana w taki sposób, aby w wersji Release wszystkie wersje Debugowania były usuwane tak dobrze, jak to tylko możliwe.

Pamiętaj: jeśli podasz nazwę pliku za każdym razem, gdy go skonstruujesz, i otworzysz plik i zamkniesz go ponownie, wydajność ucierpi. W przypadku wielu plików wyjściowych z pewnością najlepiej byłoby mieć kilka statycznych elementów danych, które otwierają różne pliki podczas uruchamiania programu lub gdy są otwierane po raz pierwszy.

2

Jeśli nie masz ograniczeń rozmiaru w projekcie i spodziewasz się, że będzie on trwał długo, proponuję przejrzeć Apache Log4cxx. To nie jest mała biblioteka, ale obsługuje prawie wszystko, czego kiedykolwiek pragnąłeś (w tym pewne rzeczy, o których nawet nie wiedziałeś, że chciałeś) w logowaniu i jest przenośny.

Prędzej czy później, w każdym większym projekcie, będziesz chciał, aby twoje rozwiązanie do rejestrowania danych było czymś więcej niż tylko "małą klasą rejestratora", a więc dlaczego warto odkrywać nowe koło.

4

Polecam wypróbować bibliotekę plog (jestem autorem). To około 1000 linii kodu, tylko nagłówek i łatwy w użyciu:

#include <plog/Log.h> 

int main() 
{ 
    plog::init(plog::debug, "Sample.log"); 

    LOGD << "Hello log!"; 
    LOGD_IF(true) << "conditional logging"; 
    return 0; 
} 
14

Dla każdego, kto chce proste rozwiązanie, polecam: easylogging++

pojedyncze nagłówek tylko biblioteka C++ zalogowaniu. Jest wyjątkowo lekki, solidny, szybki, bezpieczny w użyciu i zabezpieczony wątkiem i składa się z wielu wbudowanych funkcji: . Zapewnia możliwość zapisywania logów w swoim własnym niestandardowym formacie .Zapewnia również wsparcie dla rejestrowania twoich zajęć, bibliotek stron trzecich, kontenerów STL i innych firm itp.

Ta biblioteka ma wszystko wbudowane, aby uniemożliwić korzystanie z zewnętrznych bibliotek .

Prosty przykład: (bardziej zaawansowane przykłady dostępne na powyższym linku).

#include "easylogging++.h" 

INITIALIZE_EASYLOGGINGPP 

int main(int argv, char* argc[]) { 
    LOG(INFO) << "My first info log using default logger"; 
    return 0; 
} 

Przykâadowa wewnątrz klasy:

2015-08-28 10: 38: 45900 DEBUGOWANY [domyślnie] [użytkownik @ localhost] [konfiguracji :: konfiguracji (const łańcuch)] [ src/Config.cpp: 7] Odczyt pliku config: 'config.json'

próbowałem log4cpp i boost :: zalogować, ale nie są tak proste, jak ten.

dodatkową zawartość: Minimalna wersja - nagłówek LOG

stworzyłem mały kod na jeszcze prostszych aplikacji opartych na easylogging ale nie wymaga inicjalizacji (należy zwrócić uwagę, że prawdopodobnie nie jest bezpieczeństwo wątków). Oto kod:

/* 
* File: Log.h 
* Author: Alberto Lepe <[email protected]> 
* 
* Created on December 1, 2015, 6:00 PM 
*/ 

#ifndef LOG_H 
#define LOG_H 

#include <iostream> 

using namespace std; 

enum typelog { 
    DEBUG, 
    INFO, 
    WARN, 
    ERROR 
}; 

struct structlog { 
    bool headers = false; 
    typelog level = WARN; 
}; 

extern structlog LOGCFG; 

class LOG { 
public: 
    LOG() {} 
    LOG(typelog type) { 
     msglevel = type; 
     if(LOGCFG.headers) { 
      operator << ("["+getLabel(type)+"]"); 
     } 
    } 
    ~LOG() { 
     if(opened) { 
      cout << endl; 
     } 
     opened = false; 
    } 
    template<class T> 
    LOG &operator<<(const T &msg) { 
     if(msglevel >= LOGCFG.level) { 
      cout << msg; 
      opened = true; 
     } 
     return *this; 
    } 
private: 
    bool opened = false; 
    typelog msglevel = DEBUG; 
    inline string getLabel(typelog type) { 
     string label; 
     switch(type) { 
      case DEBUG: label = "DEBUG"; break; 
      case INFO: label = "INFO "; break; 
      case WARN: label = "WARN "; break; 
      case ERROR: label = "ERROR"; break; 
     } 
     return label; 
    } 
}; 

#endif /* LOG_H */ 

Zastosowanie:

#include "Log.h" 

int main(int argc, char** argv) { 
    //Config: -----(optional)---- 
    structlog LOGCFG = {}; 
    LOGCFG.headers = false; 
    LOGCFG.level = DEBUG; 
    //--------------------------- 
    LOG(INFO) << "Main executed with " << (argc - 1) << " arguments"; 
} 

Ten wysokiej jakości wydruk kodu wiadomość za pomocą „cout”, ale można go zmienić na użyciu „cerr” lub dołączyć plik, itd. Mam nadzieję, przydatne dla kogoś. (Uwaga: nie jestem ekspertem C++ w żaden sposób, więc ten kod może eksplodować w skrajnych przypadkach).

+1

+1 dla wersji minimalnej. Musiałem umieścić pierwszą linię konfiguracyjną 'structlog LOGCFG = {};' poza główną metodą w zasięgu globalnym, aby ją uruchomić. – CodeKid

4

wszystkie wspomniane rejestratory do tej pory wykorzystują makra do rejestrowania połączeń. Dla mnie to jest takie brzydkie, nie obchodzi mnie, jaki wzrost wydajności daje, nie zbliżę się do tego.

https://github.com/gabime/spdlog to co lubię. Czysta składnia, obsługuje wszystkie typowe zastosowania. Szybki i mały. na przykład dla rejestratora plików jest to:

auto my_logger = spd::basic_logger_mt("basic_logger", "logs/basic.txt"); 
my_logger->info("Some log message"); 
Powiązane problemy