- Easy to use - simple API, works out of the box
- Advanced filtering and log levels per topic or output
- Thread-safety via external locking injection
- Customization - only data you need
- Extensible - add your own features via public API, set of predefined extensions
- Support for embedded systems static allocation, small size
- Easy to install two files for copy-paste and support for many build systems
- For everyone - C and C++ support, works with any compiler, any platform, commercial or open-source use
In the default configuration it looks like this:
![]() |
|---|
| Picture 1 - default configuration: no time, long default levels, source location, no topics, no colors |
...but in can be very minimalistic :
![]() |
|---|
| Picture 2 - short levels, no colors, no time, no source location |
... or feature-rich:
![]() |
|---|
| Picture 3 - time, custom prefix for MsgID, custom syslog levels, topics, source location, colors |
The project is based on the following core principles:
- Universal for embedded and desktop applications
- No feature - no code for compilation
- Shallow learning curve, works out of box
- No dependencies
- Two files for core functionality.
- Extensions as recipes for your own features.
Option 1 - Sources:
- Download a Source Package from Releases
- Add sources to your system manually
Option 2 - CMake Package (recommended CMake > 3.15.0):
- Download a CMake Package from Releases
- Specify the install location:
- Specify package storage
cmake -B./build -DCMAKE_PREFIX_PATH="~/MyCmakePackages"or - Set
microlog_DIRvariable with path to the packagemicrolog_DIR=~/microlog-1.2.3-cmake
- Specify package storage
- Use in your project:
find_package(microlog 1.2.3 REQUIRED) add_executable(example_package example.cpp) target_link_libraries(example_package PRIVATE microlog::microlog) target_compile_definitions(microlog PRIVATE ULOG_BUILD_COLOR=1) # configuration # Or use a user-defined configuration header `ulog_config.h`: # target_compile_definitions(microlog PRIVATE ULOG_BUILD_CONFIG_HEADER_ENABLED=1) # target_include_directories(microlog PRIVATE path/to/directory/containing/ulog_config.h)Option 3 - Meson Package:
- Download a Meson Package from Releases
- Copy the content to
MyMesonProject/subprojects - Add to your dependencies:
add_global_arguments('-DULOG_BUILD_COLOR=1', language: ['cpp', 'c']) # configuration # Or use a user-defined configuration header `ulog_config.h`: # add_global_arguments('-DULOG_BUILD_CONFIG_HEADER_ENABLED=1', language: ['cpp', 'c']) # And add include directory where ulog_config.h is located: # add_global_arguments('-Ipath/to/directory/containing/ulog_config.h', language: ['cpp', 'c']) exe = executable( meson.project_name(), src, include_directories: include, dependencies: dependency('microlog'), )Option 4 - Meson Wrap File:
- Download the wrap file from Releases
- Place
microlog.wrapin yourMyMesonProject/subprojects/directory - Add to your dependencies as in Option 3
Option 5 - CPM:
- Download CPM (https://github.com/cpm-cmake/CPM.cmake)
- Add microlog to your projects CMAKE file:
include(cpm/CPM.cmake) CPMAddPackage("gh:an-dr/microlog@6.4.5") target_link_libraries(${PROJECT_NAME} PUBLIC microlog::microlog) target_compile_definitions( microlog PRIVATE ULOG_BUILD_COLOR=1) # configuration # Or use a user-defined configuration header `ulog_config.h`: # target_compile_definitions(microlog PRIVATE ULOG_BUILD_CONFIG_HEADER_ENABLED=1) # target_include_directories(microlog PRIVATE path/to/directory/containing/ulog_config.h)#include "ulog.h" int main() { ulog_info("Hello, World"); return 0; }Output:
INFO src/main.cpp:4: Hello, World Add missing functionalities via API or use predefined extensions. See Extensions documentation.
User Manual in doc/features.md - detailed information about the available features.
Extensions - Optional add-ons that use only the public API to enhance functionality.
See the example for more features in action: example/main.cpp.
Contributions are welcome! Please read the CONTRIBUTING.md for details, I tried to keep it simple.
microlog started as a fork of rxi/log.c (~150 lines, 3.3k stars) but evolved into a fundamentally different architecture (~2,500 lines) optimized for embedded systems and advanced filtering. Thanks to compile-time feature stripping, unused features are excluded from the build—so a minimal microlog configuration can match log.c’s footprint in both size and performance.
rxi/log.c: Minimalist and ready to use. Fixed footprint, 6 levels, simple callbacks. microlog: Compile-time feature selection. Configurable footprint, 8 renameable levels, multi-dimensional filtering.
| Feature | log.c | microlog |
|---|---|---|
| Philosophy | Simple-to-use, Minimalist for average use | Simple-to-use, extensible and configurable for diverse needs |
| Configuration | Color, verbosity | ✅ Compile-time feature selection + optional runtime |
| Runtime Configuration | Only verbosity | ✅ Verbosity, color, time, prefix, source location, topics (Disablable feature) |
| Zero-Overhead Disable | Arguments still evaluated | ✅ True no-op with ULOG_BUILD_DISABLED |
| Log Levels | 6 fixed | 8, runtime renameable (e.g., syslog) |
| Filtering | Global + per-callback | Per-output + per-topic + global |
| Topics/Subsystems | Manual prefixes | ✅ Full support with filtering per topic and routing |
| Output Routing | All outputs get all logs | ✅ Route topics to specific or all outputs |
| Memory | Static | ✅ Static or dynamic (user choice) |
| Build Systems | Manual integration | ✅ CMake, Meson, CPM packages |
| Platform Helpers | DIY | ✅ FreeRTOS, Zephyr, ThreadX, pthread, Win32 |
TL;DR:
- When to choose log.c:
- Small projects needing basic logging with minimal setup.
- When to choose microlog:
- Same scenarios, as default setup is just as simple.
- Plus: embedded systems, multi-subsystem applications, or projects requiring fine-grained control and advanced filtering.
1. Multi-Dimensional Filtering - Per-output AND per-topic levels:
ulog_topic_add("Credentials", secure_file_only, ULOG_LEVEL_TRACE); ulog_topic_add("Network", ULOG_OUTPUT_ALL, ULOG_LEVEL_DEBUG); ulog_output_level_set(ULOG_OUTPUT_STDOUT, ULOG_LEVEL_ERROR); // Console: errors only2. True Zero-Overhead Disable - Arguments not evaluated:
ulog_info("Result: %d", expensive()); // With ULOG_BUILD_DISABLED=1 → ((void)0)3. Custom Log Levels - Redefine all 8 at runtime:
ulog_level_descriptor syslog = {ULOG_LEVEL_7, {"DEBUG", "INFO", "NOTICE", "WARN", "ERR", "CRIT", "ALERT", "EMERG"}}; ulog_level_set_new_levels(&syslog);4. Fine-Grained Code Control - 12+ build flags to strip features:
-DULOG_BUILD_SOURCE_LOCATION=0 // Remove file:line -DULOG_BUILD_TIME=0 // Remove timestamps -DULOG_BUILD_COLOR=0 // Remove ANSI codes ... See CHANGELOG.md for details.
This library is free software; you can redistribute it and/or modify it under the terms of the MIT license. See LICENSE for details.
Based on https://github.com/rxi/log.c.git


