Ich schreibe eine Bibliothek mit vielen Informationen, die in einem Protokoll des Programms, das sie verwendet, von Nutzen sein können, aber ich weiß nicht, wie ich sie am besten so verfügbar machen kann, dass das Programm, das meine Bibliothek verwendet, dies kann Integrieren Sie die Protokolle meiner Bibliothek nahtlos in die eigenen Protokolle (falls gewünscht).
Wenn Sie eine bestimmte Protokollierungsbibliothek für meine Bibliothek auswählen, wird die Liste der Abhängigkeiten für die Verwendung meiner Bibliothek erweitert und das Hauptprogramm an diese Bibliothek gebunden. Wenn dies vom Hauptprogramm mehrere Bibliotheken verwendet haben, könnte jede eine andere Bibliothek ausgewählt haben .
Ich habe darüber nachgedacht, dass das Programm ein C ++ - Stream-Objekt bei der Bibliothek registriert, damit es verwendet werden kann. Das scheint ein relativ allgemeiner Zweck zu sein, aber ich habe auch darüber nachgedacht, dass das Hauptprogramm nur eine Rückruffunktion registriert, die bei der Protokollierung der Daten mit den Inhalten und Metadaten aufgerufen wird. Eine andere Möglichkeit wäre, die Protokolldaten in der Bibliothek in einer Art Liste zu speichern, damit das Hauptprogramm sie abrufen kann, wann immer es mit diesen Daten umgehen möchte, damit das Hauptprogramm entscheiden kann, wann es Zeit hat, mit den Daten umzugehen.
Ich suche nach Vor- und Nachteilen verschiedener Ansätze, damit ich entscheiden kann, was in meiner Situation am besten ist.
Antworten:
Sie können mehrere Methoden verfügbar machen, um die Protokollierung von Ihrer Bibliothek zu erhalten, und alle bis auf eine in Adapter für die in der Bibliothek verwendete "echte" umschließen.
Sie entscheiden sich beispielsweise für eine interne
std::function<void(std::string)>
Sammlung, die jeder Logger-Rückruf darstellt. Sie bieten:und auch
und auch
und weitere Variationen der Typen "Strings von irgendwoher empfangen", für die Sie Adapter implementieren möchten.
quelle
Der einfachste Weg, einer Anwendung zu ermöglichen, auf die Protokollierungsfunktion zuzugreifen, besteht darin, eine Klasse / Funktion zu registrieren, um die Protokollnachricht zu empfangen. Was sie mit dieser Nachricht machen, hängt ganz von der Anwendung ab.
Mit C / C ++ können Sie Folgendes in Ihrer Bibliothek verwenden:
Eine Anwendung kann eine Funktion durch Aufrufen registrieren
registerLogMessageReceiver
. mit dem entsprechendenuser_data
. Im Protokollierungsbereich Ihrer Codebasis müssen Sie sicherstellen, dass Sie diese Funktion mit der entsprechenden Nachricht und der registrierten aufrufenuser_data
.Wenn Sie sich nicht um C kümmern müssen, können Sie eine Klasse als Empfänger von Nachrichten verwenden.
und fügen Sie eine Funktion in der Bibliothek hinzu, damit eine Anwendung einen Protokollnachrichtenempfänger registrieren kann.
Eine Anwendung kann a registrieren,
LogMessageReceiver
indem sie die obige Funktion aufruft. Sie müssen einige politische Entscheidungen bezüglich des Eigentums der registrierten Personen treffenLogMessageReceiver
. Wenn die Bibliothek den Empfänger übernimmt, muss siedelete
den Zeiger haben. Wenn die Bibliothek den Empfänger nicht übernimmt, muss sich die Anwendung umdelete
den Empfänger kümmern .Durch die Verwendung einer Klasse als Protokollnachrichtenempfänger kann das
user_data
Bit weggelassen werden,registerLogMessageReceiver
da der Untertyp vonLogMessageReceiver
frei ist, Daten zu speichern, die für seine Funktion nützlich sind. Es müssen keine zusätzlichen Benutzerdaten in derreceive
Funktion übergeben werden.Von dort aus kann es komplexer werden, je nachdem, wie ausgefeilt Ihr Protokollierungsmechanismus ist.
Beispielsweise können Sie verschiedene Protokollierungsstufen haben: Concise, Normal, Verbose oder LoggingLevel1, LoggingLevel2, ..., LoggingLevelN.
In diesem Fall müssen Sie der Anwendung erlauben, die Protokollierungsstufe zu steuern, die sie verwenden möchten.
Sobald Sie sich entscheiden, über den simplen Protokollierungsmechanismus hinauszugehen, stehen Ihnen unendlich viele Möglichkeiten zur Verfügung. Es macht keinen Sinn, sich hier mit ihnen zu befassen.
quelle
Ich würde behaupten, dass Sie die Notwendigkeit einer Protokollierung in Verbindung mit Ihrer Bibliothek überdenken sollten . Besonders für C ++, wo es keine Standard-Logger-Schnittstelle gibt.
Unterschiedliche Anwendungen haben unterschiedliche Richtlinien für die Protokollierung. Eine Bibliothek sollte politikunabhängig sein.
Der Zweck einer Bibliothek besteht darin, einen Dienst bereitzustellen und vorzugsweise anzugeben, ob eine Anforderung für diesen Dienst erfolgreich war oder fehlgeschlagen ist. Idealerweise mit einem Hinweis darauf, warum [es fehlgeschlagen ist] über errno, Rückkehrcode, Ausnahme ... Wenn Sie eine Protokollierung wünschen, weil eine bereitgestellte Funktion an mehreren Stellen fehlschlagen kann , versuchen Sie möglicherweise , zu viel in einer Funktion zu tun. Vielleicht nicht , aber erwägen Sie die Möglichkeit.
quelle
[...] answer can be “don’t do that" [...]
.Das Schreiben einer Bibliothek, die problemlos mit dem Protokollsystem der Hostanwendung verbunden werden kann, ist einfach, sofern Sie wissen, um welches System es sich handelt. Wenn es dafür mehrere Möglichkeiten gibt, ist es schwieriger und Sie werden durch die Tyrannei des kleinsten gemeinsamen Nenners eingeschränkt. Sie könnten eine Kompatibilitätsebene haben, die Ihre Bibliothek an die verschiedenen Protokollsysteme anpasst, aber jetzt können Sie sich nicht mehr auf eine nützliche, einzigartige Funktion verlassen, die nur ein System bietet. Wenn der Endbenutzer das andere System hat, ist diese nützliche einzigartige Funktion nicht vorhanden.
In der .Net-Welt gibt es (mindestens) zwei häufig verwendete Protokollsysteme, log4net und NLog. Beide sind ähnlich, aber nicht identisch. Ich habe bereits log4net verwendet und dann angefangen, NHibernate (eine ORM-Bibliothek) zu verwenden. Glücklicherweise wird log4net intern verwendet, sodass es einfach war, es einem Projekt hinzuzufügen. (Und hier bin ich mit der Antwort von @ Daniel nicht einverstanden: Manchmal ist es für NHibernate äußerst nützlich, seine Aktivitäten in demselben System, das ich an anderer Stelle verwende, ohne zusätzliche Arbeit detailliert zu protokollieren.) Wenn ich bereits in NLog investiert war, bedeutet dies auch Ich wechsle oder habe ein Projekt, das beides verwendet.
Zumindest bei der Protokollierung besteht normalerweise die Möglichkeit, einen benutzerdefinierten Nachrichten-Appender zu erstellen, den Sie so konfigurieren können, dass eine in einem System angemeldete Nachricht an das andere Protokollierungssystem weitergeleitet wird. Wenn ich also bereits NLog verwenden würde und wirklich damit weitermachen wollte, aber auch NHibernate verwenden möchte, könnte ich meine Zähne zusammenbeißen und einen log4net-Appender schreiben, der jede Nachricht an NLog weiterleitet. Es wäre unkompliziert, wenn die APIs ähnlich wären.
Die Alternativen bestehen darin, das beste System für Ihre verfügbaren Anforderungen auszuwählen und vorbehaltlos zu verwenden oder eine Art Adapterschicht zu verwenden, die dem Problem des kleinsten gemeinsamen Nenners unterliegt. Welches ist keine sehr befriedigende Antwort.
quelle