Ich versuche, einen benutzerdefinierten Formatierer mit Boost.Log zu verwenden. Die Art, wie ich weiß, wie dies zu tun ist, um die set_formatter
Methode einer Senke nennen ihm die Adresse einer lokalen Funktion geben, wo die Signatur der lokalen Funktion sein muss:Wie Boost.Log Formatierungsausdrücke in benutzerdefinierten Formatierungsfunktion verwenden
void my_formatter(boost::log::record_view const& rec, boost::log::formatting_ostream& strm)
In my_formatter
ich die Boost-verwenden kann .Log Extraktion API, um die Attributwerte, die ich brauche. Sobald ich die Werte bekomme, kann ich sie an die strm
ausgeben. Ich möchte dies tun, damit ich einige benutzerdefinierte Attribute, die im Datensatz gespeichert sind, leicht formatieren kann. Aber für andere, konventionellere Boost.Log-Attribute möchte ich weiterhin die einfachen Formatierungsausdrücke verwenden, die als Schlüsselwortargumente für die set_formatter
-Methode dokumentiert sind. Gibt es eine Möglichkeit, die Schlüsselwortausdrücke auch in der benutzerdefinierten Funktion my_formatter
zu verwenden?
Zum Beispiel:
void my_formatter(boost::log::record_view const& rec, boost::log::formatting_ostream& strm)
{
// here I can get the timestamp attribute and format its ticks value to the stream
boost::log::value_ref<boost::posix_time::ptime> tstamp_ref =
boost::log::extract<boost::posix_time::ptime>("TimeStamp", rec);
const boost::posix_time::ptime& timestamp = tstamp_ref.get();
strm << timestamp.time_of_day().ticks();
}
Dann ein Waschbecken gegeben, kann ich anrufen
sink->set_formatter(&my_formatter)
Aber Boost.Log gibt mir einen eleganten (fast magischen) Ausdruck, die ich verwenden kann die Formatierer einzustellen :
boost::log::formatter formatter =
expr::stream
<< expr::format_date_time<boost::posix_time::ptime>(
"TimeStamp", "%Y/%m/%d, %H:%M:%S.%f, ");
sink->set_formatter(formatter)
Meine Frage ist: gibt es eine Möglichkeit, den Formatierer Ausdruck in meiner Gewohnheit zu verwenden my_formatter
Funktion?
Danke!
Danke! Das ist eine lange Antwort, also muss ich es ein wenig studieren, aber das scheint auch ein guter Ansatz zu sein. Können Sie die Leistungseinbußen bei der Verwendung der Formatierungsausdrücke etwas genauer erläutern? Sie erwähnen in den Dokumenten, dass die Formatierungsausdrücke im Code schneller ausgeführt werden als solche, die aus einer Konfigurationsdatei erstellt wurden. Meine Beobachtung ist, dass mein Nicht-Ausdruck-Formatierer schneller ist als der Ausdruck-basierte. (Zugegeben, in meinem Ad-hoc-Benchmark ist die einzige Arbeit, die getan wird, Logging, also bin ich hyperkritisch in Bezug auf die Verlangsamung, aber manchmal ist Leistung wirklich wichtig.) – Phil
Man müsste den Code und die generierte Assembly untersuchen der Grund der Leistungsregression. Die Formatierungsausdrücke (die sowieso 'expr :: stream 'enthalten) sind effizienter als die analysierten Formatierer, da der Compiler mehr Möglichkeiten zur Optimierung hat. Insbesondere kann es inline aggressiver arbeiten. Ein von Hand geschriebener Formatierer kann den Formatierungsausdruck möglicherweise übertreffen, da er spezieller sein kann. Es ist normalerweise eine flache Funktion, so dass es nicht darauf ankommt, so viel zu inlinern, während der Compiler die Template-Ausdrücke aus irgendeinem Grund nicht optimieren kann. –
Wenn Ihr Formatierer Datum/Uhrzeit einbezieht, sollten Sie sicherstellen, dass Sie 'expr :: format_date_time' und nicht den' Operator << 'von Boost.DateTime verwenden, da letzteres bekanntermaßen langsamer ist. –