spdlog_setup
spdlog_setup copied to clipboard
spdlog setup initialization via file configuration for convenience.
spdlog_setup (spdlog setup)
Overview
Header-only spdlog file-based setup
library for convenience in initializing spdlog. Inspired by
spdlog-config for using
TOML configuration, a format that is
simple and easy-to-read.
Requirements
Requires at least CMake 3.3, g++-4.9 for Linux, or MSVC2015 with MSBuild
for Windows, providing sufficient C++11 features.
g++-4.8 will notably fail because of the missing std::regex implementation.
MSVC2013 will fail too as it does not accept noexcept, which is used in some
of the functions.
Tested against:
g++-4.9g++-5g++-6g++-7g++-8clang-3.6clang-3.7clang-3.8clang-3.9clang-4.0clang-5.0clang-6.0clang-7cl(v140 / MSVC2015)cl(v141 / MSVC2017)
Features
- Header-only (check
How to Installto extract out the header files). - Initialization of
spdlogsinks, patterns and loggers based onTOMLconfiguration file. - Tag replacement (e.g. "{tagname}-log.txt") within the
TOMLconfiguration file. - Throw exception describing the error during the parsing of the config file.
Changelog
See CHANGELOG.md for more details.
Repository Checkout
Since this repository has other git-based dependencies as git submodules, use
the command:
git clone --recursive https://github.com/guangie88/spdlog_setup.git in order
to clone all the submodule dependencies.
If the repository has already been cloned without the submodules, then instead
run: git submodule update --init --recursive in order to clone all the
submodule dependencies.
Dependencies
This repository uses the following external dependencies directly:
In addition, the following dependencies are inlined as part of the include:
How to Build
This guide prefers a CMake out-of-source build style. For build with unit
tests, add -DSPDLOG_SETUP_INCLUDE_UNIT_TESTS=ON during the CMake
configuration.
How to Install
If a recent enough spdlog is already available, and unit tests are not to be
run, it is possible to just copy the spdlog_setup directory within include
into another solution for header-only include, as long as spdlog can be found
in that solution.
If spdlog is not available, the installation step of CMake can copy out the
entire list of header files required for spdlog_setup into the installation
directory, including spdlog. To change the installation directory, add
-DCMAKE_INSTALL_PREFIX=<path-to-install> during the CMake configuration.
Linux (GCC)
In the root directory after git cloning:
Debug without Installation
mkdir build-debugcd build-debugcmake .. -DCMAKE_BUILD_TYPE=Debug -DSPDLOG_SETUP_INCLUDE_UNIT_TESTS=ONcmake --build .
Now the unit test executable should be compiled and residing in
build-debug/spdlog_setup_unit_test.
Release with Installation
mkdir build-releasecd build-releasecmake .. -DCMAKE_BUILD_TYPE=Release -DSPDLOG_SETUP_INCLUDE_UNIT_TESTS=ON -DCMAKE_INSTALL_PREFIX=installcmake --build . --target install
Now the unit test executable should be compiled and residing in
build-release/spdlog_setup_unit_test.
The header files should be installed in build-release/install/include.
Windows (MSVC2015 as Example)
Ensure that Microsoft Build Tools 2015
and Visual C++ Build Tools 2015
(or Visual Studio 2015) have been installed.
In the root directory after git cloning:
mkdir buildcd buildcmake .. -G "Visual Studio 14 Win64" -DSPDLOG_SETUP_INCLUDE_UNIT_TESTS=ON -DCMAKE_INSTALL_PREFIX=install- (Debug)
cmake --build . --config Debug - (Release with installation)
cmake --build . --config Release --target install
Now the unit test executable should be compiled and residing in
- (Debug)
build/Debug/spdlog_setup_unit_test.exeor - (Release)
build/Release/spdlog_setup_unit_test.exe.
The header files should be installed in build/install/include.
Supported Sinks
stdout_sink_ststdout_sink_mtstderr_sink_ststderr_sink_mtcolor_stdout_sink_stcolor_stdout_sink_mtcolor_stderr_sink_stcolor_stderr_sink_mtbasic_file_sink_stbasic_file_sink_mtrotating_file_sink_strotating_file_sink_mtdaily_file_sink_stdaily_file_sink_mtnull_sink_stnull_sink_mtsyslog_sink(only for Linux,SPDLOG_ENABLE_SYSLOGpreprocessor definition must be defined before anyspdlog/spdlog_setupheader is included)
Currently ostream_sink and dist_sink do not fit into the use case and are
not supported.
For more information about how the above sinks work in spdlog, please refer to
the original spdlog sinks wiki page at:
https://github.com/gabime/spdlog/wiki/4.-Sinks.
TOML Configuration Example
Static File Configuration
# level is optional for both sinks and loggers
# level for error logging is 'err', not 'error'
# _st => single threaded, _mt => multi threaded
# syslog_sink is automatically thread-safe by default, no need for _mt suffix
# max_size supports suffix
# - T (terabyte)
# - G (gigabyte)
# - M (megabyte)
# - K (kilobyte)
# - or simply no suffix (byte)
# check out https: // github.com/gabime/spdlog/wiki/3.-Custom-formatting
global_pattern = "[%Y-%m-%dT%T%z] [%L] <%n>: %v"
[[sink]]
name = "console_st"
type = "stdout_sink_st"
[[sink]]
name = "console_mt"
type = "stdout_sink_mt"
[[sink]]
name = "color_console_st"
type = "color_stdout_sink_st"
[[sink]]
name = "color_console_mt"
type = "color_stdout_sink_mt"
[[sink]]
name = "file_out"
type = "basic_file_sink_st"
filename = "log/spdlog_setup.log"
# truncate field is optional
# truncate = false (default)
level = "info"
# optional flag to indicate the set - up to create the log dir first
create_parent_dir = true
[[sink]]
name = "file_err"
type = "basic_file_sink_mt"
filename = "log/spdlog_setup_err.log"
truncate = true
level = "err"
# to show that create_parent_dir is indeed optional(defaults to false)
[[sink]]
name = "rotate_out"
type = "rotating_file_sink_st"
base_filename = "log/rotate_spdlog_setup.log"
max_size = "1M"
max_files = 10
level = "info"
[[sink]]
name = "rotate_err"
type = "rotating_file_sink_mt"
base_filename = "log/rotate_spdlog_setup_err.log"
max_size = "1M"
max_files = 10
level = "err"
[[sink]]
name = "daily_out"
type = "daily_file_sink_st"
base_filename = "log/daily_spdlog_setup.log"
rotation_hour = 17
rotation_minute = 30
level = "info"
[[sink]]
name = "daily_err"
type = "daily_file_sink_mt"
base_filename = "log/daily_spdlog_setup_err.log"
rotation_hour = 17
rotation_minute = 30
level = "err"
[[sink]]
name = "null_sink_st"
type = "null_sink_st"
[[sink]]
name = "null_sink_mt"
type = "null_sink_mt"
# only works for Linux
[[sink]]
name = "syslog_st"
type = "syslog_sink_st"
# generally no need to fill up the optional fields below
# ident = "" (default)
# syslog_option = 0 (default)
# syslog_facility = LOG_USER (default macro value)
# only works for Linux
[[sink]]
name = "syslog_mt"
type = "syslog_sink_mt"
# generally no need to fill up the optional fields below
# ident = "" (default)
# syslog_option = 0 (default)
# syslog_facility = LOG_USER (default macro value)
# only works for Windows
[[sink]]
name = "msvc_st"
type = "msvc_sink_st"
# only works for Windows
[[sink]]
name = "msvc_mt"
type = "msvc_sink_mt"
[[pattern]]
name = "succient"
value = "%c-%L: %v"
[[logger]]
name = "root"
sinks = [
"console_st", "console_mt",
"color_console_st", "color_console_mt",
"daily_out", "daily_err",
"file_out", "file_err",
"rotate_out", "rotate_err",
"null_sink_st", "null_sink_mt",
"syslog_st", "syslog_mt"]
level = "trace"
[[logger]]
name = "windows_only"
sinks = ["msvc_st", "msvc_mt"]
[[logger]]
name = "console"
sinks = ["console_st", "console_mt"]
pattern = "succient"
# Async
[global_thread_pool]
queue_size = 8192
num_threads = 1
[[thread_pool]]
name = "tp"
queue_size = 4096
num_threads = 2
[[logger]]
type = "async"
name = "global_async"
sinks = ["console_mt"]
pattern = "succient"
[[logger]]
type = "async"
name = "local_async"
sinks = ["console_mt"]
pattern = "succient"
thread_pool = "tp"
overflow_policy = "overrun_oldest" # block (default) | overrun_oldest
Tagged-Base Pre-TOML File Configuration
# level is optional for both sinks and loggers
# level for error logging is 'err', not 'error'
# max_size supports suffix
# - T (terabyte)
# - G (gigabyte)
# - M (megabyte)
# - K (kilobyte)
# - or simply no suffix (byte)
[[sink]]
name = "console"
type = "stdout_sink_mt"
[[sink]]
name = "rotate_out"
type = "rotating_file_sink_mt"
base_filename = "log/{index}-info/simple-{path}.log"
max_size = "1M"
max_files = 10
level = "info"
# optional flag to indicate the set - up to create the log dir first
create_parent_dir = true
[[sink]]
name = "simple_err"
type = "basic_file_sink_mt"
filename = "log/{index}-err/simple-{path}.log"
truncate = false
level = "err"
# optional flag to indicate the set - up to create the log dir first
create_parent_dir = true
[[logger]]
name = "root"
sinks = ["console", "rotate_out", "simple_err"]
level = "trace"
Use Examples
Static Configuration File
#include "spdlog_setup/conf.h"
#include <iostream>
#include <string>
int main() {
try {
// spdlog_setup::setup_error thrown if file not found
spdlog_setup::from_file("log_conf.toml");
// assumes that root logger has been initialized
auto logger = spdlog::get("root");
logger->trace("trace message");
logger->debug("debug message");
logger->info("info message");
logger->warn("warn message");
logger->error("error message");
logger->critical("critical message");
// ...
} catch (const spdlog_setup::setup_error &) {
// ...
} catch (const std::exception &) {
// ...
}
}
Tagged Based Configuration File
#include "spdlog_setup/conf.h"
#include <string>
int main(const int argc, const char * argv[]) {
// assumes both index and path are given by command line arguments
try {
// gets index integer, e.g. 123
const auto index = std::stoi(argv[1]);
// gets path string, e.g. a/b/c
const auto path = std::string(argv[2]);
// performs parsing with dynamic tag value replacements
// tags are anything content that contains {xxx}, where xxx is the name
// of the tag to be replaced
spdlog_setup::from_file_with_tag_replacement(
"log_conf.pre.toml",
// replaces {index} with actual value in current variable index via
// fmt mechanism
fmt::arg("index", index),
// replaces {path} with actual value in current variable path
fmt::arg("path", path));
auto logger = spdlog::get("root");
// ...
} catch (const spdlog_setup::setup_error &) {
// ...
} catch (const std::exception &) {
// ...
}
}
Notes
- Make sure that the directory for the log files to reside in exists before
using
spdlog, unless thecreate_parent_dirflag is set to true for the sink. - For the current set of unit tests, the working directory must be at the git
root directory or in
builddirectory so that the TOML configuration files inconfigdirectory can be found.
Contributions
Pull requests are welcome!
To make the code formatting more objective, clang-format is used to format
all the source code files.
Please try to run
./run-clang-format.sh
which will pull the appropriate Docker image to run the formatting command over the entire repository directory.
If your docker command requires sudo, then you will need to run it as
sudo sh ./run-clang-format.sh
Alternatively, you could also try to set up your own clang-format (currently
this repository uses version 7), and run
clang-format -i path_to_h_cpp_file
over the changed files.