Skip to content
Eduard Mishkurov edited this page Apr 22, 2026 · 4 revisions

FAQ

Why are my log messages duplicated?

The most common reason is channel linking combined with backends on more than one level of the route.

If a channel links to another channel, the message is first propagated to the linked channel and then delivered to the current channel’s own backends. If both channels print to the console or file, you will see duplication.

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");

How to fix it:

  • attach the backend only once in the route, or
  • keep both backends but use different purposes / formats deliberately, or
  • suppress link propagation for one record with Override::Add.DisableLink

Why is there no output?

Several common reasons:

1. Logging is compiled out

If _LOGME_ACTIVE is false for the build, the macros expand to an inert branch. For release logging, make sure your build enables the corresponding release option/macros documented by the project.

2. The channel is not routed anywhere

Logging to a channel ID is valid even if the channel does not exist yet:

Logme::ID ch{"some_name"};
LogmeI(ch, "hello");

But a record only becomes visible when the target channel exists and is routed to at least one backend directly or through a link.

3. The channel filter level rejects the record

LEVEL_INFO is the default channel level, so debug records are dropped unless you lower the filter.

4. The channel is disabled

A disabled channel drops records during Channel::Display().

5. A precheck skips argument evaluation for an inactive explicit channel

This is usually a feature, not a bug. If you pass an inactive ChannelPtr, logme may skip evaluating later arguments entirely.


Why does formatting not work?

The usual cause is mixing the two formatting macro families.

LogmeI, LogmeE, ... — printf-style formatting

These macros use classic % formatting:

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

Using {} placeholders here leaves them uninterpreted.

fLogmeI, fLogmeE, ... — std::format formatting

When std::format support is enabled, the fLogme... family uses {} placeholders:

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

Using %i with fLogme... is the wrong family.

Stream form

If you call a macro without a format string, it returns a stream object:

LogmeI() << "value=" << 1;

Is logging from signal handlers supported?

No. The implementation uses mutexes, condition variables, allocation, standard formatting facilities, and file I/O. Treat logme as a normal multi-threaded logger, not as an async-signal-safe emergency logger.


Typical configuration mistakes

Adding backends to multiple linked channels

This often creates duplicate output.

Creating channels but never routing them

Valid, but invisible.

Relying on implicit defaults

Defaults are convenient for startup, but production setups should usually set channel levels, flags, links, and backend settings explicitly.

Mixing formatting families

  • Logme... -> %
  • fLogme... -> {}

Assuming runtime control can recreate full JSON config

The control server is excellent for live tweaks, but backend --add ... only creates default backend instances. Full backend parameters still belong in code or JSON configuration.


Q: Can I use LogmeX macros directly in if/else without braces?

if (something)
  LogmeI(message1);
else
  LogmeI(message2);

A: No. This pattern is not safe.

LogmeX macros expand into an if-like construct, which causes the else to bind to the wrong if after macro expansion (dangling-else problem).

Minimum safe pattern (brace the branch with the macro):

if (something)
{
  LogmeI(message1);
}
else
  LogmeI(message2);

fLogmeX macros do not suffer from this issue in the same way.

Getting Started

Practical Runbooks

Architecture

Output & Formatting

Backends

Runtime Control

Tools

Reference

Examples

Clone this wiki locally