Comment vider manuellement un journal de boost?

Je joue avec Boost.Log dans boost 1.54.0 pour voir si c’est une option viable pour mon application. En général, la mise en mémoire tampon ne me pose pas de problème. Je ne cherche donc pas à activer auto_flush ni quoi que ce soit … mais j’ai remarqué que les messages enregistrés avant d’appeler fork() sont dupliqués. se demandant si c’est parce qu’ils sont mis en mémoire tampon, le tampon est dupliqué lorsque l’image de processus est copiée, puis les deux processus écrivent finalement leurs copies de tampon dans le fichier journal …

Donc, fondamentalement, je voudrais juste faire un vidage manuel du journal, une fois seulement, immédiatement avant d’appeler fork() afin d’être sûr qu’aucun message ne rest en mémoire. En d’autres termes, je recherche quelque chose qui ressemble à fflush() , .flush() , << flush , etc., que je peux utiliser dans un journal de boost.

J’ai essayé d’utiliser << flush avec le journal, mais je reçois toujours les messages dupliqués. Je ne suis donc pas sûr à 100% s’il s’agit de purger et si les doublons sont causés par un autre problème, ou s’ils ignorent silencieusement le << flush

Modifier:

Je cherchais autour de moi et je me suis rendu compte que le journal boost n’était pas sûr pour la fourche. J’ajoute donc que je n’essaie pas d’utiliser le même journal dans les processus parent et enfant. J’ai deux scénarios de forking – dans l’un, le parent se termine immédiatement et l’enfant continu (donc cela devrait être sûr), et dans l’autre, l’enfant devrait ouvrir son propre fichier journal séparé, donc ça devrait être sûr aussi … mais je ‘aurais besoin de comprendre comment fermer un collecteur de fichier journal, puis en ouvrir un nouveau (sur un fichier différent). Je suppose que fermer l’évier peut aussi être un moyen de forcer une chasse d’eau …?

Ok … j’ai du creuser un peu le code boost (mais pas trop), et j’ai trouvé ceci, qui semble fonctionner:

Lorsque vous appelez add_file_log(strLogFilename) il renvoie un shared_ptrsink est votre type de récepteur (par exemple, shared_ptr< synchronous_sink< text_file_backend > > ). Si vous créez plutôt votre récepteur “manuellement”, vous avez bien sûr également un pointeur sur celui-ci … Il semble que les puits et le .flush() aient une méthode .flush() . Je ne suis pas sûr de savoir comment vous obtenez directement une copie du backend pour l’appeler, mais le flush de l’évier semble simplement appeler le flush de son (s) back-end (s), donc ça marche. Voici un exemple de code de ce que j’ai trouvé fonctionner pour moi:

 shared_ptr< synchronous_sink< text_file_backend > > pLogSink = add_file_log(strLogFilaname); BOOST_LOG_TRIVIAL(debug) << "Boost log!"; // other work goes here BOOST_LOG_TRIVIAL(debug) << "About to fork..."; if (pLogSink) pLogSink->flush(); pid_t pid = fork(); if (pid < 0) // handle error else if (pid > 0) exit(EXIT_SUCCESS); // parent terminates assert(0 == pid); // child continues BOOST_LOG_TRIVIAL(debug) << "Fork succeeded!"; 

En utilisant cette méthode, je vois maintenant chaque message du journal une seule fois. Bien entendu, gardez à l'esprit cet avertissement concernant le mélange de Boost.Log avec fork () ... http://boost-log.sourceforge.net/libs/log/doc/html/log/rationale/fork_support.html

Dans mon exemple, c'est sans danger uniquement parce que le processus parent se ferme immédiatement après le bifurcage sans toucher le journal (après le fork). Ainsi, il n'y a pas de conflit pour le journal.

Malgré les limitations, je peux utiliser cette méthode dans quelques cas: 1) démonisation d’un processus (ce que j’essaie de faire ici, en fait), 2) motif fork-exec (qui fonctionne bien avec Boost.Log, selon l'URL ci-dessus) ou 3) le processus enfant ferme immédiatement le collecteur de fichiers et ouvre un nouveau collecteur pour le journal qui pointe vers un fichier différent (celui utilisé par le processus parent) - je pense que ce troisième cas devrait être sûr .

Un code encore plus simple (avec une journalisation sortingviale):

 #include  #include  #include  #include  #include  namespace logging = boost::log; void InitLogging() { boost::filesystem::path full_path(boost::filesystem::current_path()); auto sink = logging::add_file_log("sample.log"); BOOST_LOG_TRIVIAL(info) << "Log initialized."; BOOST_LOG_TRIVIAL(info) << "Working dir: " << full_path; sink->flush(); } int main() { InitLogging(); return 0; } 

Selon mes tests, flush est une méthode de blocage. Je ne l’utilise que pendant l’initialisation, donc si quelque chose ne va pas, je sais où se trouvait l’exécution.