Skip to content
Eduard Mishkurov edited this page Jan 21, 2026 · 3 revisions

FAQ

Why are my log messages duplicated?

First, make sure that your code is not explicitly logging the same message multiple times.
If this is not the case, the most common reason is channel linking combined with shared backends.

If a channel is linked to another channel, and both channels have the same backend (for example ConsoleBackend), the message will be routed through both paths and printed multiple times.

Example:

Logme::ID chId{"test"};
auto ch = Logme::Instance->CreateChannel(chId);

ch->AddBackend(std::make_shared<Logme::ConsoleBackend>(ch));
ch->AddLink(::CH); // the default channel usually already has ConsoleBackend

LogmeI(ch, "duplicated message");

In this example:

  • ch has its own ConsoleBackend
  • ch is linked to the default channel CH
  • CH also has a ConsoleBackend

As a result, the message is printed twice.

How to fix

  • Avoid attaching the same backend to both a channel and its linked parent
  • Or rely on routing via links without duplicating backends

Why is there no output?

There are several common reasons why log messages may not appear.


1. Logging is compiled out in Release builds

By default, logging may be disabled in Release builds to eliminate runtime overhead.

If logging is required in Release builds, the application must be built with the LOGME_INRELEASE macro enabled.


2. The channel is not routed anywhere (not created / no backends / no links)

In Logme it is valid to log to a channel by ID without creating it first.
This is intentional: subsystems may log to their own named channels, and those channels can be created and configured later, when there is interest in their output.

Logme::ID ch{"some_name"};
LogmeI(ch, "hello"); // valid, but produces no output if the channel is not routed

However, a channel that is not routed to any backend (directly or via links) will not produce any output, so messages will be dropped.

To make messages visible, create and configure the channel:

auto ch = Logme::Instance->CreateChannel(ch);
ch->AddBackend(std::make_shared<Logme::ConsoleBackend>(ch));
LogmeI(ch, "hello2"); // now visible

Alternatively, link the channel to another channel that already has backends:

auto ch = Logme::Instance->CreateChannel("some_name");
ch->AddLink(::CH);

3. Message level is filtered out

Each channel has a log level filter.
By default, CreateChannel() sets the level to LEVEL_INFO.

LogmeD(ch, "hello3"); // dropped because LEVEL_DEBUG < LEVEL_INFO

Lower the channel log level if needed:

ch->SetLevel(Logme::Level::LEVEL_DEBUG);

4. The channel is disabled

A disabled channel drops all messages unconditionally:

ch->SetEnabled(false);
LogmeI(ch, "hello4"); // dropped

Why does formatting not work?

Formatting issues are usually caused by mixing incompatible formatting styles.

Logme provides two distinct macro families, each using its own formatting mechanism.


LogmeI, LogmeE, ... — {}-style formatting

These macros use C++20-style formatting (std::format-like syntax):

LogmeI("value={}", 1); // correct

Using C-style format specifiers will not work:

LogmeI("value=%i", 1); // prints: value=%i

fLogmeI, fLogmeE, ... — C-style % formatting

These macros expect classic C-style formatting:

fLogmeI("value=%i", 1); // correct

Using {} placeholders here will not work:

fLogmeI("value={}", 1); // prints: value={}

Formatting summary

Macro family Formatting style
LogmeI, LogmeE, ... {} (C++20 / std::format style)
fLogmeI, fLogmeE, ... % (C-style formatting)

Typical Configuration Mistakes

Adding backends to multiple linked channels

Attaching the same type of backend (for example ConsoleBackend) to both a channel and its linked parent channel often results in duplicated output.

Recommendation
Attach backends at a single routing level and use channel links only for propagation.


Creating channels but never routing them

Logging to a channel ID without routing it anywhere is valid, but often misunderstood. Messages will remain invisible until the channel is routed to a backend.

LogmeI("net", "connection opened"); // valid, but invisible without routing

Recommendation

  • Route channels explicitly when their output is needed
  • Use dynamic channel creation to enable logging on demand

Relying on default log levels unintentionally

The default channel level is LEVEL_INFO.
Debug messages will not be visible unless the level is lowered explicitly.

Recommendation

  • Set channel levels explicitly in configuration code or JSON
  • Avoid relying on implicit defaults

Mixing formatting macro families

Using {} placeholders with fLogme* macros or % specifiers with Logme* macros will always result in unformatted output.

Recommendation

  • Use Logme* macros for modern C++20-style formatting
  • Use fLogme* macros only when C-style formatting is required

Assuming logging is enabled in Release builds

Release builds may completely remove logging code.

Recommendation

  • Enable LOGME_INRELEASE if logging is required
  • Document this requirement clearly in build instructions

Clone this wiki locally