Logging channels in C++: spdlog vs logme
Support for channels in logging libraries is an important topic for C++ projects where it is necessary to separate, filter, and route messages from different subsystems. Support for channels in logging libraries directly affects how easy it is to analyze logs and how flexible the system is.
Why support for channels in logging libraries matters
Support for channels in logging libraries allows you to logically separate messages coming from different parts of the system.
In sufficiently complex projects, there are always multiple subsystems whose logs should be handled independently. For example, in a web server it is common to:
- write initialization and shutdown messages to a root log,
- create a separate log for each request.
Only with this approach do logs remain structured and easy to analyze.
Support for channels in logging libraries: approaches
Different libraries implement support for channels in logging libraries in different ways. Let’s look at two popular approaches using spdlog and logme.
More about spdlog: https://github.com/gabime/spdlog
Logme repository: https://github.com/efmsoft/logme
spdlog
In spdlog, a channel effectively corresponds to a separate logger.
In other words, support for channels in logging libraries is implemented via multiple loggers with different sinks.
auto sink1 = std::make_shared<spdlog::sinks::basic_file_sink_mt>("log1.txt", true);auto logger1 = std::make_shared<spdlog::logger>("log1", sink1);auto sink2 = std::make_shared<spdlog::sinks::basic_file_sink_mt>("log2.txt", true);auto logger2 = std::make_shared<spdlog::logger>("log2", sink2);logger1->info("Message for log1");logger2->info("Message for log2");This approach:
- is simple and intuitive,
- works well for statically configured systems,
- but does not provide built-in routing between channels.
logme
In logme, support for channels in logging libraries is implemented as a first-class concept.
A channel is created explicitly, and backends are attached to it:
auto log1 = Logme::Instance->CreateChannel();auto file1 = std::make_shared<Logme::FileBackend>(log1);file1->CreateLog("log1.log");log1->AddBackend(file1);auto log2 = Logme::Instance->CreateChannel();auto file2 = std::make_shared<Logme::FileBackend>(log2);file2->CreateLog("log2.log");log2->AddBackend(file2);LogmeI(log1, "Message for log1");LogmeI(log2, "Message for log2");Support for channels in logging libraries in this model becomes more flexible:
- a channel is an independent object,
- dynamic configuration is possible,
- centralized control is available.
Additional channel features in logme
Support for channels in logging libraries in logme includes several advanced capabilities that go beyond the basic spdlog model.
Compile-time disabling of logging
Logging is done via macros (LogmeI, LogmeD), which allows you to:
- completely remove logging from release builds,
- avoid formatting overhead,
- eliminate temporary objects.
This is a key difference compared to method calls (logger->info(...)), which remain in the binary even when disabled.
Channel linking (routing)
Channels can be linked:
log1->AddLink(log2);After that:
- all messages from
log1are automatically duplicated intolog2.
Support for channels in logging libraries in this form allows you to:
- build aggregated logs,
- separate detailed and high-level logs,
- implement flexible routing.
Per-message routing control
You can override routing for specific messages:
Logme::Override ovr;ovr.Add.DisableLink = true;LogmeI(log1, ovr, "message only for log1");In this case:
- the message goes only to
log1, - it is not duplicated to linked channels.
Key differences
If we summarize support for channels in logging libraries:
spdlog
- channel = logger,
- simple model,
- no built-in routing.
logme
- channel is a first-class entity,
- supports linking,
- flexible routing,
- compile-time logging elimination.
Conclusion
Support for channels in logging libraries is implemented differently and directly affects system capabilities.
spdlogis simple and efficient for most use cases.logmeprovides a more flexible architecture for complex scenarios and runtime control.
If your project requires:
- separation of logs by subsystem,
- minimal overhead,
- flexible routing of messages,
then support for channels in logging libraries becomes a key factor in choosing a logging solution.