simple_logger, a simple, multifunctional and header-only log library for C++17.
- ✅ Simple: Header-only, easy and convenient to use​
- âś… Multiple styles to use: C++
iostreamstyle, function style and ​format style - ✅ High performance: Templatized, no runtime polymorphism
- âś… Customizable thread-safety: Provide both thread-safe and thread-unsafe mode. No extra performance overhead in thread-unsafe mode.
- Unix-like Operating Systems (Linux, MacOS, FreeBSD, ...)
- Windows x86/x64 (MSVC, MinGW, MinGW-w64, Cygwin, ...)
- ...
MSVC, GCC and Clang, etc. supporting C++17 standard or above.
Run:
$ git clone https://github.com/Timothy-Liuxf/simple_logger.git --recursiveor
$ git clone https://github.com/Timothy-Liuxf/simple_logger.git
$ cd simple_logger
$ git submodule update --init --recursivesimple_logger is a header-only library and needn't to be built. Just add the include and third_party/fmt/include directories into the include directories of your C++ project and include simple_logger/simple_logger.hpp to get started.
There are six log levels in simple_logger: Trace, Debug, Info, Warn, Error and Fatal. The first two levels will print log messages into stdout, while the other two will print into stderr. By default, log messages in Debug level and Trace level are NOT printed.
There are three styles to log messages.
You can log messages in C++ iostream style:
#include <simple_logger/simple_logger.hpp>
using namespace simple_logger;
int main() {
logger.Trace() << "This message shouldn't be printed by default!";
logger.Debug() << "This message shouldn't be printed by default!";
logger.Info() << "Info message: <" << 8888 << '>';
logger.Warn() << "Warn message: <" << 8888 << '>';
logger.Error() << "Error message: <" << 8888 << '>';
logger.Fatal() << "Fatal message: <" << 8888 << '>';
return 0;
}You can also log messages just as a variadic function:
#include <simple_logger/simple_logger.hpp>
using namespace simple_logger;
int main() {
logger.Trace("This message shouldn't be printed by default!");
logger.Debug("This message shouldn't be printed by default!");
logger.Info("Info message: <", 8888, '>');
logger.Warn("Warn message: <", 8888, '>');
logger.Error("Error message: <", 8888, '>');
logger.Fatal("Fatal message: <", 8888, '>');
return 0;
}You can also log messages in C++20 format library style:
#include <simple_logger/simple_logger.hpp>
using namespace simple_logger;
int main() {
logger.Tracef("This message shouldn't be printed by default!");
logger.Debugf("This message shouldn't be printed by default!");
logger.Infof("Info message: <{}>", 8888);
logger.Warnf("Warn message: <{}>", 8888);
logger.Errorf("Error message: <{}>", 8888);
logger.Fatalf("Fatal message: <{}>", 8888);
return 0;
}With fmtlib, simple_logger can support almost all formatting methods in fmtlib. Such as:
-
Format ranges:
#include <simple_logger/simple_logger.hpp> #include <fmt/ranges.h> #include <array> using namespace simple_logger; int main() { std::array arr {0, 1, 2, 3}; logger.Infof("Info message: {}", arr); return 0; }
-
Format time:
#include <simple_logger/simple_logger.hpp> #include <fmt/chrono.h> #include <chrono> using namespace simple_logger; int main() { auto current_time = fmt::localtime( std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())); logger.Infof("Info message: current_time: {:%Y-%m-%d %H:%M:%S}", current_time); return 0; }
-
Literal-based format
#include <simple_logger/simple_logger.hpp> #include <fmt/format.h> using namespace simple_logger; int main() { using fmt::literals::operator""_a; logger.Infof("Info message: {num}", "num"_a = 5); return 0; }
-
For more usage, please see fmtlib API documentation.
To specify log levels, you should define the following macros before including simple_logger/simple_logger.hpp:
SIMPLE_LOGGER_DISABLE_LOG: No logs will be printedSIMPLE_LOGGER_ENABLE_LOG_TRACE: Log messages onTrace,Debug,Info,Warning,ErrorandFatallevels will be printedSIMPLE_LOGGER_ENABLE_LOG_DEBUG: Log messages onDebug,Info,Warning,ErrorandFatallevels will be printedSIMPLE_LOGGER_ENABLE_LOG_INFO: Log messages onInfo,Warning,ErrorandFatallevels will be printedSIMPLE_LOGGER_ENABLE_LOG_WARN: Log messages onWarning,ErrorandFatallevels will be printedSIMPLE_LOGGER_ENABLE_LOG_ERROR: Log messages onErrorandFatallevels will be printedSIMPLE_LOGGER_ENABLE_LOG_FATAL: Only log messages onFatallevel will be printed- If no macro is defined, it behaves just as
SIMPLE_LOGGER_ENABLE_LOG_INFOis defined
The log object logger is thread-safe. To use thread-unsafe log to avoid improve performance, you can use uslogger. For an example, the following code will cause chaos (changing uslogger to logger would fix it):
#include <simple_logger/simple_logger.hpp>
#include <memory>
#include <thread>
#include <utility>
#include <vector>
constexpr std::size_t nthreads = 128;
using namespace simple_logger;
int main(int argc, char*[]) {
std::vector<std::unique_ptr<std::thread>> threads(nthreads);
for (std::size_t i = 0; i < nthreads; ++i) {
threads[i] = std::make_unique<std::thread>([i, argc] {
std::this_thread::yield();
uslogger.Info() << "Thread-unsafe "
<< "log. "
<< "[argc: " << argc << "] "
<< "At "
<< "Index: " << i << ".";
});
}
for (std::size_t i = 0; i < nthreads; ++i) {
threads[i]->join();
threads[i].reset();
}
return 0;
}Source code of the examples are in the examples directory.
To build the examples:
For all platforms with CMake, run:
$ mkdir build
$ cd build
$ cmake ..
$ make -j$(nproc)For Unix-like platforms with GNU Autotools, run:
$ autoreconf -i
$ BUILD_TEST_EXAMPLES=1 ./configure
$ make -j$(nproc)To run the examples, then run:
$ ./examples/<example_name>The <example_name> is the same as the name of the corresponding source file after removing the extension name .cc.
Copyright (C) 2023, Timothy Liu
All rights reserved
