20 Stimmen

Asynchrone thread-sichere Protokollierung in C++

Ich bin auf der Suche nach einer Möglichkeit, asynchrone und Thread-sichere Protokollierung in meinem C++-Projekt zu tun, wenn möglich in eine Datei. Ich verwende derzeit cerr y clog für die Aufgabe, aber da sie synchron sind, wird die Ausführung jedes Mal kurz unterbrochen, wenn etwas protokolliert wird. Da es sich um eine relativ grafiklastige Anwendung handelt, ist diese Art von Dingen ziemlich ärgerlich.

Der neue Logger sollte asynchrone E/A verwenden, um diese Pausen zu beseitigen. Thread-Sicherheit wäre auch wünschenswert, da ich beabsichtige, einige grundlegende Multithreading bald hinzufügen.

Ich habe einen Ansatz mit einer Datei pro Thread in Erwägung gezogen, aber das schien mir die Verwaltung der Protokolle zu einem Albtraum zu machen. Irgendwelche Vorschläge?

20voto

Kjell Hedström Punkte 450

Ich habe diesen über 1 Jahr alten Thread entdeckt. Vielleicht könnte der asynchrone Logger, den ich geschrieben habe, von Interesse sein.

http://www.codeproject.com/KB/library/g2log.aspx

G2log verwendet eine geschützte Nachrichtenwarteschlange, um Protokolleinträge an einen Hintergrundworker weiterzuleiten, auf den die langsame Festplatte zugreift.

Ich habe es mit einer sperrfreien Warteschlange versucht, die die durchschnittliche Zeit für einen LOG-Aufruf erhöhte, aber die Zeit im schlimmsten Fall verringerte, aber ich verwende jetzt die geschützte Warteschlange, da sie plattformübergreifend ist. Es ist auf Windows/Visual Studio 2010 und Ubuntu 11.10/gcc4.6 getestet.

Es ist als Public Domain freigegeben, so dass Sie damit machen können, was Sie wollen, ohne Bedingungen zu stellen.

4voto

Amardeep AC9MF Punkte 17715

Das ist SEHR gut möglich und praktisch. Woher ich das weiß? Ich habe genau das bei meinem letzten Job geschrieben. Leider (für uns) besitzen sie jetzt den Code :-) Traurigerweise benutzen sie ihn nicht einmal.

Ich beabsichtige, in naher Zukunft eine Open-Source-Version zu schreiben. In der Zwischenzeit kann ich Ihnen einige Hinweise geben.

  1. E/A-Manipulatoren sind eigentlich nur Funktionsnamen. Sie können sie für Ihre eigene Protokollierungsklasse implementieren, damit Ihr Logger cout/cin-kompatibel ist.
  2. Ihre Manipulatorfunktionen können die Operationen mit Token versehen und in einer Warteschlange speichern.
  3. Ein Thread kann in dieser Warteschlange blockiert sein und darauf warten, dass Teile des Protokolls durchgeschleust werden. Er verarbeitet dann die String-Operationen und erzeugt das eigentliche Protokoll.

Dies ist an sich Thread-kompatibel, da Sie eine Warteschlange verwenden. Dennoch sollten Sie das Schreiben in die Warteschlange mit einem Mutex-ähnlichen Schutz versehen, damit eine gegebene Operation vom Typ log << "stuff" << "more stuff"; zeilenatomisch bleibt.

Viel Spaß!

1voto

Cubbi Punkte 44766

Ich denke, der richtige Ansatz ist nicht eine Datei pro Thread, sondern ein Thread pro Datei. Wenn auf eine Datei (oder eine Ressource im Allgemeinen) in Ihrem System immer nur von einem Thread zugegriffen wird, wird eine thread-sichere Programmierung sehr viel einfacher.

Warum also nicht Logger zu einem eigenen Thread machen (oder mehrere Threads, einen pro Datei, wenn Sie verschiedene Dinge in verschiedenen Dateien protokollieren), und in allen anderen Threads würde das Schreiben in das Protokoll die Nachricht in die Eingabewarteschlange des entsprechenden Logger-Threads stellen, der sie erhält, nachdem er mit dem Schreiben der vorherigen Nachricht fertig ist. Alles, was man braucht, ist ein Mutex, um die Warteschlange vor dem Hinzufügen eines Ereignisses zu schützen, während Logger ein Ereignis liest, und eine Condvar, auf die Logger warten kann, wenn seine Warteschlange leer ist.

1voto

Matthieu M. Punkte 266317

Haben Sie die Verwendung einer Protokollbibliothek in Betracht gezogen.

Ich habe festgestellt, dass es mehrere davon gibt Pantheios und es scheint wirklich unglaublich zu sein.

Es handelt sich eher um einen Front-End-Logger, bei dem Sie selbst bestimmen können, welches System verwendet wird. Er kann interagieren mit ACE o log4cxx und es scheint wirklich einfach zu benutzen und zu konfigurieren zu sein. Der Hauptvorteil ist, dass es typsichere Operatoren verwendet, was immer großartig ist.

Wenn Sie nur eine einfache Protokollierungsbibliothek benötigen:

  • ACE
  • log4c*
  • Boost.Log

Such dir was aus :)

Ich sollte anmerken, dass es möglich ist, sperrfreie Warteschlangen in C++ zu implementieren und dass sie sich hervorragend für die Protokollierung eignen.

0voto

Jezor Punkte 2838

Ich hatte das gleiche Problem, und ich glaube, ich habe die perfekte Lösung gefunden. Ich präsentiere Ihnen, eine Single-Header-Bibliothek namens loguru: https://github.com/emilk/loguru

Es ist einfach zu bedienen, portabel, konfigurierbar, makrobasiert und bietet standardmäßig keine #include alles (für die süße, süße Kompilationszeit).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X