c++loggingboostboost-logboost-logging

How to expose and register one boost log core to another


A dll and an executable both use boost::log. They end up using different singleton log cores. How can I expose the dll core to the executable and register the dll-core to the exe-core so that I can redirect both into one logfile.

I wrote a minimal example to illustrate where I stumble:

LogUser.hpp

#pragma once

#ifdef DYNLIB_EXPORTS
#define DYNLIB_API __declspec(dllexport)
#else
#define DYNLIB_API __declspec(dllimport)
#endif

class DYNLIB_API LogUser
{
public:
    LogUser();
    ~LogUser() {}
};

LogUser.cpp

#include "LogUser.hpp"
#include <boost\log\trivial.hpp>
LogUser::LogUser()
{
    BOOST_LOG_TRIVIAL(trace) << "LogUser constructed";
}

Main.cpp

#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>

#pragma comment (lib, "dynlib.lib")
#include <dynlib/LogUser.hpp>

void setupLogging();

int main()
{
    setupLogging();
    BOOST_LOG_TRIVIAL(trace) << "main enter";
    LogUser dynamicLogUser;
    BOOST_LOG_TRIVIAL(trace) << "main exit";
    return 0;
}

void setupLogging()
{
    using namespace boost::log;
    add_common_attributes();
    register_simple_formatter_factory< trivial::severity_level, char >("Severity");
    add_file_log
        (
        keywords::file_name = "file.log",
        keywords::format = "[%TimeStamp%] [%ThreadID%] [%Severity%]: %Message%"
        );
}

LogUser compiles into LogUser.dll. The constructor of LogUser creates a trace message that ends up on the console. Main redirects its output to a log file but does not redirect the dll output to the same logfile. I suppose the dll contains its own logcore and I would have to redirect its messages to the other core first. I googled the problem and I can not find a simple solution although it feels like this should be a one line call in main during setup. And a getter to the boost logcore singleton in the dll interface.

Is there a standard way that I am missing? How would I redirect that logging here?

Edit #1: - output on my system and fiction of what I want to happen. enter image description here

Edit #2: - I foubd a possible solution here. - If that tip solves the problem I will delete this question due to being a clone.

Edit #3: I implemented the suggested solution from EDIT #2. It works but isn't what I want.

Essentially you are supposed to #define BOOST_LOG_DYN_LINK . Unfortunately that does not work since log is using other libraries that recursively also have to be added. I ended up with #define BOOST_ALL_DYN_LINK . All of boost is now made dynamic and with V1.59 that may be 30 dlls. In my minimal example I had to supply the dlls for chrono, date_time, filesystem, log_setup, log, regex, system and thread (.count = 8).

So even though the result is exactly that I wanted the way to get to it is different, this distinguishes this question from the other question. The DLL approach ensures that there is only the one dll singleton of the core. I prefer having 2 cores over having to supply the dlls so chaining the two together is acceptable for me.

Is there a way to get the same result while still linking statically?


Solution

  • Boost.Log requires to be built as a shared library if you use it from multiple modules. The library design is relying on that requirement, and the logging core is not the only singleton in the library. Depending on the library features you use, you are more or less likely to run into hard to debug problems if you violate this precondition. It is also possible that the code that works with your currently used version of Boost.Log will break with a different version.