A simple, header-only logging utility for C++ with:
- ANSI-colored log levels (
DEBUG
,INFO
,WARN
,ERROR
) - Optional thread safety with
std::mutex
- Compile-time log filtering (based on
LOG_LEVEL_THRESHOLD
) - Simple to integrate (drop in or via CMake)
- log_once_* macros for one-time log messages
- GNU-style variadic macros with fallback for standard C++
- Zero runtime cost for disabled log levels
one_header_logger/
├── logger.hpp # The only header you need
├── CMakeLists.txt # Minimal CMake interface library
└── test/
├── CMakeLists.txt # Optional setup for test and as example
└── main.cpp # Example usage
Level | Value | Description | Color |
---|---|---|---|
DEBUG | 0 |
Developer details | Blue |
INFO | 1 |
General info | Green |
WARN | 2 |
Warnings | Yellow |
ERROR | 3 |
Errors only | Red |
Caution
Minimum Required Version
cmake_minimum_required(VERSION 3.14)
Add to Your Project
Clone or add as a submodule
git submodule add https://github.com/yourname/one_header_logger.git
Then, in your CMakeLists.txt:
To use the logger in your project, add the library using add_subdirectory
and configure it with optional compile-time definitions:
add_subdirectory(one_header_logger)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE one_header_logger)
target_compile_definitions(my_app PRIVATE
LOG_LEVEL_THRESHOLD=LOG_LEVEL_INFO # Filter out lower-priority logs at compile time
ENABLE_LOG_MUTEX # Make logging thread-safe using std::mutex
)
Explanation of Options
-
LOG_LEVEL_THRESHOLD: Filters out all logs below the specified level. This is a compile-time optimization — excluded log calls are completely stripped from the binary using preprocessor conditions.
-
Optional: If not defined, it defaults to
LOG_LEVEL_DEBUG
(i.e. all logs are enabled). -
Usage Tip: You can leave it undefined during development for full verbosity, and define it as
LOG_LEVEL_WARN
orLOG_LEVEL_ERROR
for production builds.
-
-
ENABLE_LOG_MUTEX: Enables internal use of a global
std::mutex
to prevent interleaved log output in multi-threaded applications.-
Optional: If not defined, logging is not synchronized, which is fine for single-threaded or performance-critical cases where you control log order.
-
Use this if: Your application logs from multiple threads and you want cleaner terminal output.
-
Option | Default | Effect |
---|---|---|
LOG_LEVEL_THRESHOLD |
LOG_LEVEL_DEBUG |
All logs are compiled in (no filtering) |
ENABLE_LOG_MUTEX |
not enabled | No locking; output may interleave in multi-threaded code |
Macro Value | Logs Included |
---|---|
LOG_LEVEL_DEBUG (0) |
DEBUG , INFO , WARN , ERROR |
LOG_LEVEL_INFO (1) |
INFO , WARN , ERROR |
LOG_LEVEL_WARN (2) |
WARN , ERROR |
LOG_LEVEL_ERROR (3) |
ERROR only |
Suppress lower-priority logs by defining LOG_LEVEL_THRESHOLD
before including logger.hpp
.
Example (in code):
#define LOG_LEVEL_THRESHOLD <LEVEL>
#include "logger.hpp"
```cpp
#define LOG_LEVEL_THRESHOLD LOG_LEVEL_DEBUG
#define LOG_LEVEL_THRESHOLD LOG_LEVEL_INFO
#define LOG_LEVEL_THRESHOLD LOG_LEVEL_WARN
#define LOG_LEVEL_THRESHOLD LOG_LEVEL_ERROR
Or via compiler flags:
-DLOG_LEVEL_THRESHOLD=LOG_LEVEL_DEBUG
-DLOG_LEVEL_THRESHOLD=LOG_LEVEL_INFO
-DLOG_LEVEL_THRESHOLD=LOG_LEVEL_WARN
-DLOG_LEVEL_THRESHOLD=LOG_LEVEL_ERROR
Or in CMake:
add_compile_definitions(LOG_LEVEL_DEBUG)
add_compile_definitions(LOG_LEVEL_INFO)
add_compile_definitions(LOG_LEVEL_WARN)
add_compile_definitions(LOG_LEVEL_ERROR)
Example (in code):
#define ENABLE_LOG_MUTEX
#include "logger.hpp"
Or via compiler flags:
-DENABLE_LOG_MUTEX
Or in CMake:
add_compile_definitions(ENABLE_LOG_MUTEX)
#include "logger.hpp"
int main() {
log_debug("Debug message: x = %d\n", 42);
log_info("App started at %s\n", "10:00AM");
log_warn("Low memory warning\n");
log_error("File not found: %s\n", "config.json");
}
output will be
Use log_once_*
macros to emit a log message only once per call site, even inside loops. This is useful to avoid flooding the logs with repeated warnings or debug messages.
log_once_debug(...)
log_once_info(...)
log_once_warn(...)
log_once_error(...)
for (int i = 0; i < 5; ++i)
{
log_info("log_info: %i\n", i);
log_once_info("log_once_info\n");
log_once_debug("log_once_debug\n");
log_once_warn("log_once_warn\n");
log_once_error("log_once_error\n");
}
output will be
Each message prints only once, even though the loop runs multiple times.