I'm using spdlog in various C++ libraries for which Python bindings are created with pybind11.
Now I'm wondering if there is a nice way how I can configure these loggers (mostly the level and format) from the Python side.
Currently I am creating a separate logger for each class in the constructor (logger_
is a class member):
MyClass::MyClass()
{
logger_ = spdlog::get(LOGGER_NAME);
if (!logger_)
{
logger_ = spdlog::stderr_color_mt(LOGGER_NAME);
}
logger_->debug("Logger is set up");
}
Now I can just use MyClass and it will create and use a logger with default settings. If I want to change this, I can do so by creating a logger with the proper name before creating the class:
auto logger = spdlog::stdout_color_st(MyClass::LOGGER_NAME);
logger->set_level(spdlog::level::debug);
logger->set_pattern("[%l] %n: %v");
MyClass c;
However, I can't find a good way to do this when using the Python bindings of MyClass
. I saw that there is already a Python package binding spdlog, so I tried the following:
import spdlog
logger = spdlog.ConsoleLogger(MyClass.LOGGER_NAME)
logger.set_level(spdlog.LogLevel.DEBUG)
logger.set_pattern("[%l] %n: %v")
c = MyClass()
However, this does not affect the logger used inside MyClass
(I assume there is simply no connection between the spdlog instance from the Python package and the one in my C++ code).
So long story short: Is there a way how I can configure the logger used in the C++ code from the Python side? If there is a way without having to manually pass a logger to the constructor of each class, that would be great. But I'm not sure if this is possible?
jwm's answer pointed me to a working solution. The logger can be created on the Python side and be registered with the module containing the C++ class by also binding spdlog::register_logger()
in that module.
spdlog::register_logger()
in the module that binds MyClass
. So the code for binding looks like this:
PYBIND11_MODULE(mylib, m)
{
pybind11::class_<MyClass>(m, "MyClass")
/* ... */;
m.def("register_logger", &spdlog::register_logger);
}
import spdlog
import mylib
logger = spdlog.ConsoleLogger(mylib.MyClass.LOGGER_NAME)
logger.set_level(spdlog.LogLevel.DEBUG)
logger.set_pattern("[%l] %n: %v")
# register logger with the function from mylib, so it is accessible inside MyClass
mylib.register_logger(logger.get_underlying_logger())
c = mylib.MyClass()