Skip to content

efmsoft/logme

Repository files navigation

logme


CI Release Platform C++ Docs

vcpkg Conan Center

Colored console output example

logme is a cross-platform C/C++ logging framework that allows applications to dynamically control what is logged and where, without restarting or recompiling.

It is designed for both high-load servers and simple applications, providing selective, on-demand logging with minimal overhead and full runtime control.


Why logme is more than a logger

logme is designed as a logging infrastructure layer, not just a set of formatting macros. Its core model is built around runtime control: channels, subsystems, links, backends, output flags, and configuration can be changed while the application is running. This makes it useful for production systems where detailed diagnostics must be enabled only when needed and only for the affected component.

The project also includes companion tools and operational features: logmectl for runtime control, logmefmt for converting readable logme output to JSON/XML, logmeobf for log obfuscation, file rotation and retention, structured output, function tracing/profiling macros, and early/boot logging support.

For the design background, see the logging articles at tips.efmsoft.com.


Performance highlights

Performance is one of logme's main design goals, especially when logging is disabled, filtered out, or routed to asynchronous output. The separate logbench repository contains a reproducible benchmark suite and an article with charts and methodology.

Recent throughput results, measured as completed cycles during the same benchmark interval:

Library null file console file+console
logme (c) 1,121,998,419 153,752,170 325,518 359,772
logme (cpp-stream) 1,053,074,266 24,290,646 335,276 364,349
logme (std::format) 1,082,512,863 90,255,191 362,369 365,770
spdlog 244,991,156 118,546,708 368,944 355,449
quill 1,568,610 1,357,532 191,531 200,378
easylogging++ 25,597,177 1,656,726 356,948 277,846

The result is not based on a single trick. logme combines early filtering, call-site context caching, low-cost disabled paths, multiple formatting APIs, asynchronous file output, and runtime routing designed to avoid doing unnecessary work in hot paths.

See the wiki pages Performance and Why logme is fast for details.

Key features

  • Runtime control via a built-in control server: enable, disable, and reconfigure logging dynamically without restarting or recompiling the application.
  • Channels and subsystems: logically separate log output by component, module, or functional area.
  • Hierarchical channels: build structured logging trees and control groups of components together.
  • Flexible verbosity control: fine-grained filtering using log levels (Debug / Info / Warn / Error), subsystems, and channel hierarchy.
  • Multiple backends per channel: console, debugger, files, and other output destinations.
  • Channel links: redirect or fan-out log messages between channels without duplicating backend configuration.
  • Retention rules: limit the size of individual log files and the total disk usage across all logs.
  • Log file obfuscation: optional obfuscation of log data written to files.
  • Multiple APIs: C-style macros, C++ stream-style logging, and optional format-based formatting.
  • Cross-platform: Windows, Linux and macOS support.

Quick start

Minimal usage (out of the box)

The simplest possible usage. This works out of the box and requires no configuration.

#include <Logme/Logme.h>

int main()
{
  LogmeI("Hello from logme (%s style)", "C");
  LogmeW() << "Hello from logme (C++ stream style)";
  fLogmeE("Hello from logme ({} style)", "format");

  return 0;
}

This produces colored console output similar to the following:

Output result


Configuration files (recommended)

For most applications, logme is configured via a JSON configuration file, which can describe the following elements:

  • channels
  • backends
  • links
  • levels
  • flags
  • subsystems

This lets you adjust logging behavior at runtime or between runs without recompiling.

For details and examples, see the project Wiki.


Programmatic configuration (advanced)

All aspects of logme behavior can be configured directly from C++ application code. This approach is useful for small tools, embedded scenarios, or when configuration files are not desired.

#include <memory>

#include <Logme/Logme.h>
#include <Logme/Backend/ConsoleBackend.h>

int main()
{
  auto ch = Logme::Instance->CreateChannel("http");
  ch->AddBackend(std::make_shared<Logme::ConsoleBackend>(ch));

  fLogmeI(ch, "GET {} -> {}", "/index.html", 200); // -> GET /index.html -> 200
  return 0;
}

Runtime control (built-in control server)

Applications using logme can optionally enable a built-in control server that allows logging behavior to be fully managed at runtime.

The control server exposes a management interface for:

  • creating and removing channels,
  • attaching or detaching backends,
  • enabling, disabling, or blocking channels,
  • controlling subsystems, levels, and routing.

A command-line utility is provided with the library to send control commands to a running process, but the specific tool is not important — the key point is that logging can be reconfigured dynamically while the application is running.

Why this matters

A common use case is a modular application where each component writes to its own channel.

At startup:

  • channels may not exist at all,
  • messages sent to non-existent or inactive channels are silently dropped,
  • no log files are created,
  • no console output is produced.

When diagnostics are required:

  • a channel can be created remotely,
  • backends can be attached (file, console, debugger),
  • messages from the selected component immediately start appearing.

Later:

  • the channel can be removed,
  • blocked,
  • or detached from all backends,
  • instantly stopping further output.

Result

This model allows selective, on-demand logging:

  • only for specific components,
  • only when needed,
  • only to selected destinations.

It keeps production systems quiet by default while still allowing deep, targeted diagnostics without restarting the application or recompiling it.


Concepts

Channel

A channel is where you write messages. A channel can have:

  • one or more backends (output destinations),
  • optional links to other channels (redirect / fan-out).

Backend

A backend defines where messages go (console, debugger, file, etc.). Multiple backends can be attached to the same channel.

Subsystem

A subsystem is an optional identifier that provides an additional level of classification inside a channel. Subsystems allow grouping and filtering messages within the same channel, making it possible to enable or disable logging for specific functional parts of a component without affecting the entire channel.

Link (redirect)

A link forwards messages from one channel to another after local backends are processed. This is useful for building routing trees (e.g., httproot).


Installation

Option A: CMake FetchContent

include(FetchContent)

FetchContent_Declare(
  logme
  GIT_REPOSITORY https://github.com/efmsoft/logme.git
  GIT_TAG        main  # Prefer a release tag when available
)

FetchContent_MakeAvailable(logme)

target_link_libraries(your_target PRIVATE logme)

Option B: Add as a subdirectory

add_subdirectory(external/logme)

target_link_libraries(your_target PRIVATE logme)

An example of integrating logme as a git submodule can be found here: https://github.com/efmsoft/logme_cmake_submodule_example


Option C: vcpkg

vcpkg install logme
find_package(logme CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE logme::logme)

Option D: Conan

conan install --requires=logme/<version>
find_package(logme REQUIRED)
target_link_libraries(your_target PRIVATE logme::logme)

Build

Configure and build

cmake -S . -B build
cmake --build build

Tests

cmake -S . -B build -DLOGME_BUILD_TESTS=ON
cmake --build build
ctest --test-dir build

CMake options

  • LOGME_BUILD_EXAMPLES (ON/OFF)
  • LOGME_BUILD_TESTS (ON/OFF)
  • LOGME_BUILD_STATIC (ON/OFF)
  • LOGME_BUILD_DYNAMIC (ON/OFF)
  • LOGME_FMT_FORMAT (AUTO, ON, OFF)
  • LOGME_STD_FORMAT (AUTO, ON, OFF)

Requirements and compatibility

Language standard

  • C++20 is used.

format support

format is optional. If your standard library does not provide <format>, disable it via:

  • -DLOGME_FMT_FORMAT=OFF -DLOGME_STD_FORMAT=OFF (or define LOGME_DISABLE_STD_FORMAT)

Roadmap

  • More backends and routing presets
  • Improved documentation and more integration examples

Contributing

Contributions are welcome via issues and pull requests.

Please include:

  • OS and compiler version,
  • CMake options used,
  • minimal reproduction steps if applicable.

License

See the LICENSE file.