Skip to content
/ microlog Public

A lightweight, universal logging library in C. Just two files. Compatible with C++, embedded projects, and most major compilers. Covered by unit tests.

License

Notifications You must be signed in to change notification settings

an-dr/microlog

Repository files navigation

microlog - Extensible and configurable logging library for embedded and desktop applications

License: MIT Latest Tests

main_pic

  • 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.

Table of Contents

Quick Start

1. Install

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_DIR variable with path to the package microlog_DIR=~/microlog-1.2.3-cmake
  • 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.wrap in your MyMesonProject/subprojects/ directory
  • Add to your dependencies as in Option 3

Option 5 - CPM:

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)

2. Use

#include "ulog.h" int main() { ulog_info("Hello, World"); return 0; }

Output:

INFO src/main.cpp:4: Hello, World 

3. Extend

Add missing functionalities via API or use predefined extensions. See Extensions documentation.

Advanced Usage

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.

Contributing

Contributions are welcome! Please read the CONTRIBUTING.md for details, I tried to keep it simple.

Comparison with log.c

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.

Core Differences

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.

Key Capabilities Unique to microlog

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 only

2. 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 ... 

Changelog

See CHANGELOG.md for details.

License

This library is free software; you can redistribute it and/or modify it under the terms of the MIT license. See LICENSE for details.

Credits

Based on https://github.com/rxi/log.c.git

About

A lightweight, universal logging library in C. Just two files. Compatible with C++, embedded projects, and most major compilers. Covered by unit tests.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors 6