C++ – How to add logging to a library so it can integrate easily with the logging system of the program using the library

clogging

I'm writing a library that has a lot of information that may be of use in a log in the program which uses it, but I don't know the best way to expose it in such a way that the program using my library can integrate my library's logs with its own logs seemlessly (if desired).

Picking a specific logging library for my library adds to the list of dependencies for using my library as well as ties the main program to that library — and if multiple libraries used by the main program did this, there could each have selected a different library.

I've though about having the program register a C++ stream object with the library for it to use. That seems like it would be relatively general purpose, but I also thought about just having the main program register a callback function which would be called for with the contents and metadata when data is logged. Another option would just be to store the log data in the library in some sort of list for the main program to grab whenever it wants to deal with that data, letting the main program decide when it has time to deal with the data.

I'm looking for suggestions and pros/cons of different approaches so I can decide what is best in my situation.

Best Answer

You can expose multiple methods to receive the logging from your library, and wrap all but one in adaptors to the "real" one used in the library.

E.g. you decide to internally have a std::function<void(std::string)> collection that is each logger callback. You provide:

void registerLogCallback(std::function<void(std::string)> callback); 
// Main logging implemention

and also

registerLogStream(std::ostream stream) { 
    registerLogCallback([stream](std::string message){ stream << message; }); 
}

and also

template<typename OutputIterator>
registerLogOutputIterator(OutputIterator iter) { 
    registerLogCallback([iter](std::string message){ *iter++ = message; }); 
}

and any more variations of "recieve strings from somewhere" types you care to implement adaptors for.

Related Topic