mirror of
https://github.com/FairRootGroup/FairLogger.git
synced 2025-10-15 09:31:44 +00:00
Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9949e83a14 | ||
|
4b462d2aa2 | ||
|
28882b70ca | ||
|
1e427a2e55 | ||
|
128bcceade | ||
|
bee04a260c | ||
|
8e9d91c596 | ||
|
27dcf93d7f | ||
|
8976d98913 | ||
|
3a5afe2d6a | ||
|
aaacaf316e | ||
|
180acaae26 | ||
|
2d5dd004cb | ||
|
4c2c238030 | ||
|
3e1de0a17b | ||
|
7d0411b939 | ||
|
9a8acdf6eb | ||
|
0c2532e6b9 | ||
|
49a6e9389d | ||
|
0901655a65 | ||
|
1f600fa981 | ||
|
63820e5f2c | ||
|
de02bd068f | ||
|
24001470e5 | ||
|
5696fef902 | ||
|
80b5eb6fb1 | ||
|
c26d4ba013 | ||
|
661bd88d81 | ||
|
65068fd959 | ||
|
00e7468b25 | ||
|
af288551aa | ||
|
8f68cef9e3 | ||
|
6d71d22986 | ||
|
e72a0409a6 | ||
|
88c13b67cc |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
build/
|
||||
.vscode
|
||||
|
127
CMakeLists.txt
127
CMakeLists.txt
@@ -1,5 +1,5 @@
|
||||
################################################################################
|
||||
# Copyright (C) 2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2018-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
@@ -7,21 +7,35 @@
|
||||
################################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.9.4 FATAL_ERROR)
|
||||
|
||||
cmake_policy(VERSION 3.9...3.14)
|
||||
|
||||
# Project ######################################################################
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
include(FairLoggerLib)
|
||||
|
||||
set_fairlogger_cmake_policies()
|
||||
get_git_version(OUTVAR_PREFIX FairLogger)
|
||||
get_git_version()
|
||||
|
||||
project(FairLogger VERSION ${FairLogger_VERSION} LANGUAGES CXX)
|
||||
message("${BWhite}${PROJECT_NAME}${CR} ${FairLogger_GIT_VERSION} from ${FairLogger_DATE}")
|
||||
project(FairLogger VERSION ${PROJECT_VERSION} LANGUAGES C CXX)
|
||||
message(STATUS "${BWhite}${PROJECT_NAME}${CR} ${PROJECT_GIT_VERSION} from ${PROJECT_DATE}")
|
||||
|
||||
set_fairlogger_defaults()
|
||||
|
||||
include(CTest)
|
||||
|
||||
option(USE_BOOST_PRETTY_FUNCTION "Use Boost BOOST_PRETTY_FUNCTION macro" OFF)
|
||||
################################################################################
|
||||
|
||||
|
||||
# Dependency ###################################################################
|
||||
if(USE_BOOST_PRETTY_FUNCTION)
|
||||
if(NOT DEFINED Boost_NO_BOOST_CMAKE AND CMAKE_VERSION VERSION_LESS 3.15)
|
||||
# Since Boost 1.70 a CMake package is shipped by default. Unfortunately, it has a number
|
||||
# of problems that are only fixed in Boost 1.71 or CMake 3.15. By default we skip the
|
||||
# BoostConfig lookup. This can be overridden on the command line via -DBoost_NO_BOOST_CMAKE=OFF
|
||||
set(Boost_NO_BOOST_CMAKE ON)
|
||||
endif()
|
||||
find_package2(PUBLIC Boost REQUIRED)
|
||||
endif()
|
||||
################################################################################
|
||||
|
||||
|
||||
@@ -32,15 +46,24 @@ configure_file(logger/Version.h.in
|
||||
@ONLY
|
||||
)
|
||||
|
||||
add_library(FairLogger SHARED
|
||||
add_library(FairLogger
|
||||
logger/Logger.cxx
|
||||
logger/Logger.h
|
||||
)
|
||||
|
||||
if(USE_BOOST_PRETTY_FUNCTION)
|
||||
target_link_libraries(FairLogger PUBLIC Boost::boost)
|
||||
target_compile_definitions(FairLogger PUBLIC FAIRLOGGER_USE_BOOST_PRETTY_FUNCTION)
|
||||
endif()
|
||||
|
||||
target_include_directories(FairLogger
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/logger>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
set_target_properties(FairLogger PROPERTIES
|
||||
VERSION ${PROJECT_GIT_VERSION}
|
||||
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||
)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
@@ -58,19 +81,20 @@ install(TARGETS
|
||||
FairLogger
|
||||
${test_targets}
|
||||
|
||||
EXPORT ${FairLogger_EXPORT_SET}
|
||||
LIBRARY DESTINATION ${FairLogger_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${FairLogger_INSTALL_BINDIR}
|
||||
EXPORT ${PROJECT_EXPORT_SET}
|
||||
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${PROJECT_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
install(FILES
|
||||
logger/Logger.h
|
||||
${CMAKE_BINARY_DIR}/logger/Version.h
|
||||
|
||||
DESTINATION ${FairLogger_INSTALL_INCDIR}
|
||||
DESTINATION ${PROJECT_INSTALL_INCDIR}
|
||||
)
|
||||
|
||||
install_fairlogger_cmake_package()
|
||||
install_cmake_package()
|
||||
################################################################################
|
||||
|
||||
|
||||
@@ -84,14 +108,81 @@ endif()
|
||||
|
||||
|
||||
# Summary ######################################################################
|
||||
message(" ")
|
||||
message(" ${Cyan}COMPONENT BUILT? INFO${CR}")
|
||||
message(" ${BWhite}library${CR} ${BGreen}YES${CR} (default, always built)")
|
||||
message(STATUS " ")
|
||||
message(STATUS " ${Cyan}CXX STANDARD${CR} ${BGreen}C++${CMAKE_CXX_STANDARD}${CR} (>= C++${PROJECT_MIN_CXX_STANDARD}, change with ${BMagenta}-DCMAKE_CXX_STANDARD=17${CR})")
|
||||
if(CMAKE_CXX_FLAGS)
|
||||
message(STATUS " ")
|
||||
message(STATUS " ${Cyan}GLOBAL CXX FLAGS${CR} ${BGreen}${CMAKE_CXX_FLAGS}${CR}")
|
||||
endif()
|
||||
if(CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS " ")
|
||||
message(STATUS " ${Cyan}BUILD TYPE CXX FLAGS${CR}")
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" selected_type)
|
||||
foreach(type IN LISTS CMAKE_CONFIGURATION_TYPES)
|
||||
string(TOUPPER "${type}" type_upper)
|
||||
if(type_upper STREQUAL selected_type)
|
||||
pad("${type}" 18 " " type_padded)
|
||||
message(STATUS "${BGreen}* ${type_padded}${CMAKE_CXX_FLAGS_${type_upper}}${CR}")
|
||||
else()
|
||||
pad("${type}" 18 " " type_padded)
|
||||
message(STATUS " ${BWhite}${type_padded}${CR}${CMAKE_CXX_FLAGS_${type_upper}}")
|
||||
endif()
|
||||
unset(type_padded)
|
||||
unset(type_upper)
|
||||
endforeach()
|
||||
message(STATUS " ")
|
||||
message(STATUS " (Change the build type with ${BMagenta}-DCMAKE_BUILD_TYPE=...${CR})")
|
||||
endif()
|
||||
if(PROJECT_PACKAGE_DEPENDENCIES)
|
||||
message(STATUS " ")
|
||||
message(STATUS " ${Cyan}DEPENDENCY FOUND VERSION PREFIX${CR}")
|
||||
foreach(dep IN LISTS PROJECT_PACKAGE_DEPENDENCIES)
|
||||
if(${dep}_VERSION)
|
||||
if(${dep} STREQUAL Boost)
|
||||
if(Boost_VERSION_MAJOR)
|
||||
set(version_str "${BGreen}${${dep}_VERSION_MAJOR}.${${dep}_VERSION_MINOR}${CR}")
|
||||
else()
|
||||
set(version_str "${BGreen}${${dep}_MAJOR_VERSION}.${${dep}_MINOR_VERSION}${CR}")
|
||||
endif()
|
||||
else()
|
||||
set(version_str "${BGreen}${${dep}_VERSION}${CR}")
|
||||
endif()
|
||||
else()
|
||||
set(version_str "${BYellow}unknown${CR}")
|
||||
endif()
|
||||
if(PROJECT_${dep}_VERSION)
|
||||
set(version_req_str " (>= ${PROJECT_${dep}_VERSION})")
|
||||
endif()
|
||||
pad(${dep} 20 " " dep_padded)
|
||||
if(DISABLE_COLOR)
|
||||
pad("${version_str}${version_req_str}" 25 " " version_padded)
|
||||
else()
|
||||
pad("${version_str}${version_req_str}" 25 " " version_padded COLOR 1)
|
||||
endif()
|
||||
if(${dep} STREQUAL Boost)
|
||||
if(TARGET Boost::headers)
|
||||
get_target_property(boost_include Boost::headers INTERFACE_INCLUDE_DIRECTORIES)
|
||||
else()
|
||||
get_target_property(boost_include Boost::boost INTERFACE_INCLUDE_DIRECTORIES)
|
||||
endif()
|
||||
get_filename_component(prefix ${boost_include}/.. ABSOLUTE)
|
||||
else()
|
||||
get_filename_component(prefix ${${dep}_INCLUDE_DIR}/.. ABSOLUTE)
|
||||
endif()
|
||||
message(STATUS " ${BWhite}${dep_padded}${CR}${version_padded}${prefix}")
|
||||
unset(version_str)
|
||||
unset(version_padded)
|
||||
unset(version_req_str)
|
||||
endforeach()
|
||||
endif()
|
||||
message(STATUS " ")
|
||||
message(STATUS " ${Cyan}COMPONENT BUILT? INFO${CR}")
|
||||
message(STATUS " ${BWhite}library${CR} ${BGreen}YES${CR} (default, always built)")
|
||||
if(BUILD_TESTING)
|
||||
set(testing_summary "${BGreen}YES${CR} (default, disable with ${BMagenta}-DBUILD_TESTING=OFF${CR})")
|
||||
else()
|
||||
set(testing_summary "${BRed} NO${CR} (enable with ${BMagenta}-DBUILD_TESTING=ON${CR})")
|
||||
endif()
|
||||
message(" ${BWhite}tests${CR} ${testing_summary}")
|
||||
message(" ")
|
||||
message(STATUS " ${BWhite}tests${CR} ${testing_summary}")
|
||||
message(STATUS " ")
|
||||
################################################################################
|
||||
|
@@ -47,10 +47,6 @@ EndIf()
|
||||
|
||||
Ctest_Start($ENV{ctest_model})
|
||||
|
||||
If(NOT $ENV{ctest_model} MATCHES Experimental)
|
||||
Ctest_Update(SOURCE "${CTEST_SOURCE_DIRECTORY}")
|
||||
EndIf()
|
||||
|
||||
Ctest_Configure(BUILD "${CTEST_BINARY_DIRECTORY}"
|
||||
OPTIONS "${configure_options}"
|
||||
)
|
||||
|
55
Jenkinsfile
vendored
55
Jenkinsfile
vendored
@@ -4,24 +4,53 @@ def specToLabel(Map spec) {
|
||||
return "${spec.os}-${spec.arch}-${spec.compiler}-FairSoft_${spec.fairsoft}"
|
||||
}
|
||||
|
||||
def buildMatrix(List specs, Closure callback) {
|
||||
def jobMatrix(String prefix, List specs, Closure callback) {
|
||||
def nodes = [:]
|
||||
for (spec in specs) {
|
||||
def label = specToLabel(spec)
|
||||
nodes[label] = {
|
||||
def fairsoft = spec.fairsoft
|
||||
def os = spec.os
|
||||
def compiler = spec.compiler
|
||||
nodes["${prefix}/${label}"] = {
|
||||
node(label) {
|
||||
githubNotify(context: "alfa-ci/${label}", description: 'Building ...', status: 'PENDING')
|
||||
githubNotify(context: "${prefix}/${label}", description: 'Building ...', status: 'PENDING')
|
||||
try {
|
||||
deleteDir()
|
||||
checkout scm
|
||||
|
||||
sh """\
|
||||
echo "export SIMPATH=\${SIMPATH_PREFIX}${fairsoft}" >> Dart.cfg
|
||||
echo "export FAIRSOFT_VERSION=${fairsoft}" >> Dart.cfg
|
||||
"""
|
||||
if (os =~ /Debian/ && compiler =~ /gcc8/) {
|
||||
sh '''\
|
||||
echo "source /etc/profile.d/modules.sh" >> Dart.cfg
|
||||
echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg
|
||||
echo "module load compiler/gcc/8" >> Dart.cfg
|
||||
'''
|
||||
}
|
||||
if (os =~ /MacOS/) {
|
||||
sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=clang++'\" >> Dart.cfg"
|
||||
} else {
|
||||
sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=g++'\" >> Dart.cfg"
|
||||
}
|
||||
|
||||
sh '''\
|
||||
echo "export BUILDDIR=$PWD/build" >> Dart.cfg
|
||||
echo "export SOURCEDIR=$PWD" >> Dart.cfg
|
||||
echo "export PATH=\\\$SIMPATH/bin:\\\$PATH" >> Dart.cfg
|
||||
echo "export GIT_BRANCH=$JOB_BASE_NAME" >> Dart.cfg
|
||||
echo "echo \\\$PATH" >> Dart.cfg
|
||||
'''
|
||||
sh 'cat Dart.cfg'
|
||||
|
||||
callback.call(spec, label)
|
||||
|
||||
deleteDir()
|
||||
githubNotify(context: "alfa-ci/${label}", description: 'Success', status: 'SUCCESS')
|
||||
githubNotify(context: "${prefix}/${label}", description: 'Success', status: 'SUCCESS')
|
||||
} catch (e) {
|
||||
deleteDir()
|
||||
githubNotify(context: "alfa-ci/${label}", description: 'Error', status: 'ERROR')
|
||||
githubNotify(context: "${prefix}/${label}", description: 'Error', status: 'ERROR')
|
||||
throw e
|
||||
}
|
||||
}
|
||||
@@ -33,20 +62,14 @@ def buildMatrix(List specs, Closure callback) {
|
||||
pipeline{
|
||||
agent none
|
||||
stages {
|
||||
stage("Run Build/Test Matrix") {
|
||||
stage("Run CI Matrix") {
|
||||
steps{
|
||||
script {
|
||||
parallel(buildMatrix([
|
||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc4.9', fairsoft: 'oct17'],
|
||||
[os: 'MacOS10.11', arch: 'x86_64', compiler: 'AppleLLVM8.0.0', fairsoft: 'oct17'],
|
||||
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM9.0.0', fairsoft: 'oct17'],
|
||||
parallel(jobMatrix('alfa-ci/build', [
|
||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc8.1.0', fairsoft: 'fairmq_dev'],
|
||||
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'],
|
||||
[os: 'MacOS10.14', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'],
|
||||
]) { spec, label ->
|
||||
sh '''\
|
||||
echo "export BUILDDIR=$PWD/build" >> Dart.cfg
|
||||
echo "export SOURCEDIR=$PWD" >> Dart.cfg
|
||||
echo "export PATH=$SIMPATH/bin:$PATH" >> Dart.cfg
|
||||
echo "export GIT_BRANCH=$JOB_BASE_NAME" >> Dart.cfg
|
||||
'''
|
||||
sh './Dart.sh alfa_ci Dart.cfg'
|
||||
})
|
||||
}
|
||||
|
77
Jenkinsfile.nightly
Normal file
77
Jenkinsfile.nightly
Normal file
@@ -0,0 +1,77 @@
|
||||
#!groovy
|
||||
|
||||
def specToLabel(Map spec) {
|
||||
return "${spec.os}-${spec.arch}-${spec.compiler}-FairSoft_${spec.fairsoft}"
|
||||
}
|
||||
|
||||
def buildMatrix(List specs, Closure callback) {
|
||||
def nodes = [:]
|
||||
for (spec in specs) {
|
||||
def label = specToLabel(spec)
|
||||
def fairsoft = spec.fairsoft
|
||||
def os = spec.os
|
||||
def compiler = spec.compiler
|
||||
nodes[label] = {
|
||||
node(label) {
|
||||
try {
|
||||
deleteDir()
|
||||
checkout scm
|
||||
|
||||
sh """\
|
||||
echo "export SIMPATH=\${SIMPATH_PREFIX}${fairsoft}" >> Dart.cfg
|
||||
echo "export FAIRSOFT_VERSION=${fairsoft}" >> Dart.cfg
|
||||
"""
|
||||
if (os =~ /Debian/ && compiler =~ /gcc8/) {
|
||||
sh '''\
|
||||
echo "source /etc/profile.d/modules.sh" >> Dart.cfg
|
||||
echo "module use /cvmfs/it.gsi.de/modulefiles" >> Dart.cfg
|
||||
echo "module load compiler/gcc/8" >> Dart.cfg
|
||||
'''
|
||||
}
|
||||
if (os =~ /MacOS/) {
|
||||
sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=clang++'\" >> Dart.cfg"
|
||||
} else {
|
||||
sh "echo \"export EXTRA_FLAGS='-DCMAKE_CXX_COMPILER=g++'\" >> Dart.cfg"
|
||||
}
|
||||
sh '''\
|
||||
echo "export BUILDDIR=$PWD/build" >> Dart.cfg
|
||||
echo "export SOURCEDIR=$PWD" >> Dart.cfg
|
||||
echo "export PATH=\\\$SIMPATH/bin:\\\$PATH" >> Dart.cfg
|
||||
echo "export GIT_BRANCH=dev" >> Dart.cfg
|
||||
echo "echo \\\$PATH" >> Dart.cfg
|
||||
'''
|
||||
sh 'cat Dart.cfg'
|
||||
|
||||
callback.call(spec, label)
|
||||
|
||||
deleteDir()
|
||||
} catch (e) {
|
||||
deleteDir()
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
pipeline{
|
||||
agent none
|
||||
triggers { cron('H 2 * * *') }
|
||||
stages {
|
||||
stage("Run Nightly Build/Test Matrix") {
|
||||
steps{
|
||||
script {
|
||||
parallel(buildMatrix([
|
||||
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc8.1.0', fairsoft: 'fairmq_dev'],
|
||||
[os: 'MacOS10.13', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'],
|
||||
[os: 'MacOS10.14', arch: 'x86_64', compiler: 'AppleLLVM10.0.0', fairsoft: 'fairmq_dev'],
|
||||
]) { spec, label ->
|
||||
sh './Dart.sh Nightly Dart.cfg'
|
||||
sh './Dart.sh Profile Dart.cfg'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
141
README.md
141
README.md
@@ -2,6 +2,8 @@
|
||||
|
||||
Lightweight and fast C++ Logging Library
|
||||
|
||||

|
||||
|
||||
| Branch | Build Status |
|
||||
| :---: | :--- |
|
||||
| `master` |  |
|
||||
@@ -38,6 +40,145 @@ find_package(FairLogger)
|
||||
On command line:
|
||||
|
||||
* `-DDISABLE_COLOR=ON` disables coloured console output.
|
||||
* `-DBUILD_TESTING=OFF` disables building of unit tests.
|
||||
* `-DUSE_BOOST_PRETTY_FUNCTION=ON` enables usage of `BOOST_PRETTY_FUNCTION` macro.
|
||||
|
||||
## Documentation
|
||||
|
||||
## 1. General
|
||||
|
||||
All log calls go through the provided LOG(severity) macro. Output through this macro is thread-safe. Logging is done to cout, file output and/or custom sinks.
|
||||
|
||||
## 2. Severity
|
||||
|
||||
The log severity is controlled via:
|
||||
```C++
|
||||
fair::Logger::SetConsoleSeverity("<severity level>");
|
||||
// and/or
|
||||
fair::Logger::SetFileSeverity("<severity level>");
|
||||
// and/or
|
||||
fair::Logger::SetCustomSeverity("<customSinkName>", "<severity level>");
|
||||
```
|
||||
|
||||
where severity level is one of the following:
|
||||
|
||||
```C++
|
||||
"nolog",
|
||||
"fatal",
|
||||
"error",
|
||||
"warn",
|
||||
"state",
|
||||
"info",
|
||||
"debug",
|
||||
"debug1",
|
||||
"debug2",
|
||||
"debug3",
|
||||
"debug4",
|
||||
"trace",
|
||||
```
|
||||
|
||||
Logger will log the chosen severity and all above it (except "nolog", which deactivates logging for that sink completely). Fatal severity is always logged.
|
||||
|
||||
## 3. Verbosity
|
||||
|
||||
The log verbosity is controlled via:
|
||||
```C++
|
||||
fair::Logger::SetVerbosity("<verbosity level>");
|
||||
```
|
||||
|
||||
it is same for all sinks, and is one of the following values: `verylow`, `low`, `medium`, `high`, `veryhigh`, which translates to following output:
|
||||
|
||||
```
|
||||
verylow: message
|
||||
low: [severity] message
|
||||
medium: [HH:MM:SS][severity] message
|
||||
high: [process name][HH:MM:SS:µS][severity] message
|
||||
veryhigh: [process name][HH:MM:SS:µS][severity][file:line:function] message
|
||||
```
|
||||
|
||||
When running a FairMQ device, the log severity can be simply provided via `--verbosity <level>` cmd option.
|
||||
|
||||
The user may customize the existing verbosities or any of `user1`, `user2`, `user3`, `user4` verbosities via:
|
||||
```C++
|
||||
void fair::Logger::DefineVerbosity(fair::Verbosity, fair::VerbositySpec);
|
||||
void fair::Logger::DefineVerbosity("<verbosity level>", fair::VerbositySpec);
|
||||
```
|
||||
|
||||
The `fair::Logger::VerbositySpec` object can e.g. be created like this:
|
||||
```C++
|
||||
auto spec = fair::VerbositySpec::Make(VerbositySpec::Info::timestamp_s,
|
||||
VerbositySpec::Info::process_name);
|
||||
// results in [HH:MM:SS][process name] message
|
||||
```
|
||||
|
||||
| **Argument** | **Result** |
|
||||
| --- | --- |
|
||||
| `fair::VerbositySpec::Info::process_name` | `[process name]` |
|
||||
| `fair::VerbositySpec::Info::timestamp_s` | `[HH:MM:SS]` |
|
||||
| `fair::VerbositySpec::Info::timestamp_us` | `[HH:MM:SS:µS]` |
|
||||
| `fair::VerbositySpec::Info::severity` | `[severity]` |
|
||||
| `fair::VerbositySpec::Info::file` | `[file]` |
|
||||
| `fair::VerbositySpec::Info::file_line` | `[file:line]` |
|
||||
| `fair::VerbositySpec::Info::file_line_function` | `[file:line:function]` |
|
||||
|
||||
|
||||
### 3.1 `BOOST_PRETTY_FUNCTION` support
|
||||
|
||||
By default, the `veryhigh` verbosity prints the function name from which the `LOG` macro was invoked. If you desire a more verbose function signature including the full namespace, return value and function arguments, you can enable support for `BOOST_PRETTY_FUNCTION`
|
||||
|
||||
* **globally** by compiling FairLogger with the CMake option `-DUSE_BOOST_PRETTY_FUNCTION=ON`, or
|
||||
* **per translation unit** by defining `FAIRLOGGER_USE_BOOST_PRETTY_FUNCTION` before including the FairLogger header, e.g.
|
||||
|
||||
```C++
|
||||
#define FAIRLOGGER_USE_BOOST_PRETTY_FUNCTION
|
||||
#include <Logger.h>
|
||||
```
|
||||
|
||||
In the latter case, the user needs to take care of adding the boost include path to the compiler search path manually (e.g. `-I/path/to/boost/include`).
|
||||
|
||||
## 4. Color
|
||||
|
||||
Colored output on console can be activated with:
|
||||
```C++
|
||||
Logger::SetConsoleColor(true);
|
||||
```
|
||||
|
||||
When running a FairMQ device, the log color (console) can be simply provided via `--color <true/false>` cmd option (default is true).
|
||||
|
||||
## 5. File output
|
||||
|
||||
Output to file can be enabled via:
|
||||
```C++
|
||||
Logger::InitFileSink("<severity level>", "test_log", true);
|
||||
```
|
||||
which will add output to "test_log" filename (if third parameter is `true` it will add timestamp to the file name) with `<severity level>` severity.
|
||||
|
||||
When running a FairMQ device, the log file can be simply provided via `--log-to-file <filename_prefix>` cmd option (this will also turn off console output).
|
||||
|
||||
## 5.5 Custom sinks
|
||||
|
||||
Custom sinks can be added via `Logger::AddCustomSink("sink name", "<severity>", callback)` method.
|
||||
|
||||
Here is an example adding a custom sink for all severities ("trace" and above). It has access to the log content and meta data. Custom log calls are also thread-safe.
|
||||
|
||||
```C++
|
||||
Logger::AddCustomSink("MyCustomSink", "trace", [](const string& content, const LogMetaData& metadata)
|
||||
{
|
||||
cout << "content: " << content << endl;
|
||||
|
||||
cout << "available metadata: " << endl;
|
||||
cout << "std::time_t timestamp: " << metadata.timestamp << endl;
|
||||
cout << "std::chrono::microseconds us: " << metadata.us.count() << endl;
|
||||
cout << "std::string process_name: " << metadata.process_name << endl;
|
||||
cout << "std::string file: " << metadata.file << endl;
|
||||
cout << "std::string line: " << metadata.line << endl;
|
||||
cout << "std::string func: " << metadata.func << endl;
|
||||
cout << "std::string severity_name: " << metadata.severity_name << endl;
|
||||
cout << "fair::Severity severity: " << static_cast<int>(metadata.severity) << endl;
|
||||
});
|
||||
```
|
||||
|
||||
If only output from custom sinks is desirable, console/file sinks must be deactivated by setting their severity to `"nolog"`.
|
||||
|
||||
## License
|
||||
|
||||
|
@@ -1,26 +1,34 @@
|
||||
################################################################################
|
||||
# Copyright (C) 2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2018-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
# copied verbatim in the file "LICENSE" #
|
||||
################################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.9.4 FATAL_ERROR)
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
### General variables for project discovery/inspection
|
||||
set(FairLogger_VERSION @PROJECT_VERSION@)
|
||||
set(FairLogger_GIT_VERSION @FairLogger_GIT_VERSION@)
|
||||
set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@)
|
||||
set(@PROJECT_NAME@_GIT_VERSION @PROJECT_GIT_VERSION@)
|
||||
set(@PROJECT_NAME@_GIT_DATE @PROJECT_GIT_DATE@)
|
||||
|
||||
set_and_check(FairLogger_ROOT @PACKAGE_CMAKE_INSTALL_PREFIX@)
|
||||
set_and_check(FairLogger_BINDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@FairLogger_INSTALL_BINDIR@)
|
||||
set_and_check(FairLogger_INCDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@FairLogger_INSTALL_INCDIR@)
|
||||
set_and_check(FairLogger_LIBDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@FairLogger_INSTALL_LIBDIR@)
|
||||
set_and_check(FairLogger_DATADIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@FairLogger_INSTALL_DATADIR@)
|
||||
set_and_check(@PROJECT_NAME@_PREFIX @PACKAGE_CMAKE_INSTALL_PREFIX@)
|
||||
set(@PROJECT_NAME@_BINDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_BINDIR@)
|
||||
set_and_check(@PROJECT_NAME@_INCDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@)
|
||||
set_and_check(@PROJECT_NAME@_LIBDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_LIBDIR@)
|
||||
|
||||
set(@PROJECT_NAME@_CXX_STANDARD_REQUIRED @CMAKE_CXX_STANDARD_REQUIRED@)
|
||||
set(@PROJECT_NAME@_CXX_STANDARD @CMAKE_CXX_STANDARD@)
|
||||
set(@PROJECT_NAME@_CXX_EXTENSIONS @CMAKE_CXX_EXTENSIONS@)
|
||||
set(@PROJECT_NAME@_BUILD_TYPE @CMAKE_BUILD_TYPE@)
|
||||
set(@PROJECT_NAME@_BUILD_TYPE_UPPER @PROJECT_BUILD_TYPE_UPPER@)
|
||||
set(@PROJECT_NAME@_CXX_FLAGS @PROJECT_CXX_FLAGS@)
|
||||
|
||||
|
||||
@PACKAGE_DEPENDENCIES@
|
||||
|
||||
### Import targets
|
||||
include(@PACKAGE_CMAKE_INSTALL_PREFIX@/@PACKAGE_INSTALL_DESTINATION@/FairLoggerTargets.cmake)
|
||||
include(@PACKAGE_CMAKE_INSTALL_PREFIX@/@PACKAGE_INSTALL_DESTINATION@/@PROJECT_EXPORT_SET@.cmake)
|
||||
|
||||
check_required_components(FairLogger)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
################################################################################
|
||||
# Copyright (C) 2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# Copyright (C) 2018-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
|
||||
# #
|
||||
# This software is distributed under the terms of the #
|
||||
# GNU Lesser General Public Licence (LGPL) version 3, #
|
||||
@@ -29,23 +29,6 @@ if(NOT WIN32 AND NOT DISABLE_COLOR)
|
||||
set(BWhite "${Esc}[1;37m")
|
||||
endif()
|
||||
|
||||
# set_fairlogger_cmake_policies()
|
||||
#
|
||||
# Sets CMake policies.
|
||||
macro(set_fairlogger_cmake_policies)
|
||||
# Find more details to each policy with cmake --help-policy CMPXXXX
|
||||
foreach(policy
|
||||
CMP0028 # Double colon in target name means ALIAS or IMPORTED target.
|
||||
CMP0048 # The ``project()`` command manages VERSION variables.
|
||||
CMP0054 # Only interpret ``if()`` arguments as variables or keywords when unquoted.
|
||||
)
|
||||
if(POLICY ${policy})
|
||||
cmake_policy(SET ${policy} NEW)
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
|
||||
find_package(Git)
|
||||
# get_git_version([DEFAULT_VERSION version] [DEFAULT_DATE date] [OUTVAR_PREFIX prefix])
|
||||
#
|
||||
@@ -54,7 +37,7 @@ function(get_git_version)
|
||||
cmake_parse_arguments(ARGS "" "DEFAULT_VERSION;DEFAULT_DATE;OUTVAR_PREFIX" "" ${ARGN})
|
||||
|
||||
if(NOT ARGS_OUTVAR_PREFIX)
|
||||
set(ARGS_OUTVAR_PREFIX FairLogger)
|
||||
set(ARGS_OUTVAR_PREFIX PROJECT)
|
||||
endif()
|
||||
|
||||
if(GIT_FOUND AND EXISTS ${CMAKE_SOURCE_DIR}/.git)
|
||||
@@ -103,6 +86,7 @@ endfunction()
|
||||
# Set defaults
|
||||
macro(set_fairlogger_defaults)
|
||||
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
|
||||
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPER)
|
||||
|
||||
# Set a default build type
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
@@ -110,48 +94,142 @@ macro(set_fairlogger_defaults)
|
||||
endif()
|
||||
|
||||
# Handle C++ standard level
|
||||
set(PROJECT_MIN_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
elseif(${CMAKE_CXX_STANDARD} LESS 11)
|
||||
message(FATAL_ERROR "A minimum CMAKE_CXX_STANDARD of 11 is required.")
|
||||
endif()
|
||||
if(NOT CMAKE_CXX_EXTENSIONS)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD ${PROJECT_MIN_CXX_STANDARD})
|
||||
elseif(${CMAKE_CXX_STANDARD} LESS ${PROJECT_MIN_CXX_STANDARD})
|
||||
message(FATAL_ERROR "A minimum CMAKE_CXX_STANDARD of ${PROJECT_MIN_CXX_STANDARD} is required.")
|
||||
endif()
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
# Generate compile_commands.json file (https://clang.llvm.org/docs/JSONCompilationDatabase.html)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
set(BUILD_SHARED_LIBS ON CACHE BOOL "Whether to build shared libraries or static archives")
|
||||
endif()
|
||||
|
||||
# Set -fPIC as default for all library types
|
||||
if(NOT CMAKE_POSITION_INDEPENDENT_CODE)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
# Define CMAKE_INSTALL_*DIR family of variables
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Define install dirs
|
||||
set(FairLogger_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR})
|
||||
set(FairLogger_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME_LOWER})
|
||||
set(FairLogger_INSTALL_INCDIR ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME_LOWER})
|
||||
set(FairLogger_INSTALL_DATADIR ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME_LOWER})
|
||||
set(PROJECT_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR})
|
||||
set(PROJECT_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR})
|
||||
set(PROJECT_INSTALL_INCDIR ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME_LOWER})
|
||||
set(PROJECT_INSTALL_DATADIR ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME_LOWER})
|
||||
|
||||
# https://cmake.org/Wiki/CMake_RPATH_handling
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_LIBDIR}" isSystemDir)
|
||||
if("${isSystemDir}" STREQUAL "-1")
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-Wl,--enable-new-dtags")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} "-Wl,--enable-new-dtags")
|
||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/../${PROJECT_INSTALL_LIBDIR}")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set(CMAKE_INSTALL_RPATH "@loader_path/../${PROJECT_INSTALL_LIBDIR}")
|
||||
else()
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Define export set, only one for now
|
||||
set(FairLogger_EXPORT_SET ${PROJECT_NAME}Targets)
|
||||
set(PROJECT_EXPORT_SET ${PROJECT_NAME}Targets)
|
||||
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug" "Release" "RelWithDebInfo" "Nightly" "Profile" "Experimental" "AdressSan" "ThreadSan")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wshadow -Wall -Wextra")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -Wshadow -Wall -Wextra -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_NIGHTLY "-O2 -g -Wshadow -Wall -Wextra")
|
||||
set(CMAKE_CXX_FLAGS_PROFILE "-g3 -Wshadow -Wall -Wextra -fno-inline -ftest-coverage -fprofile-arcs")
|
||||
set(CMAKE_CXX_FLAGS_EXPERIMENTAL "-O2 -g -Wshadow -Wall -Wextra -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_ADRESSSAN "-O2 -g -Wshadow -Wall -Wextra -fsanitize=address -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS_THREADSAN "-O2 -g -Wshadow -Wall -Wextra -fsanitize=thread")
|
||||
|
||||
if(CMAKE_GENERATOR STREQUAL "Ninja" AND
|
||||
((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR
|
||||
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)))
|
||||
# Force colored warnings in Ninja's output, if the compiler has -fdiagnostics-color support.
|
||||
# Rationale in https://github.com/ninja-build/ninja/issues/814
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
function(pad str width char out)
|
||||
cmake_parse_arguments(ARGS "" "COLOR" "" ${ARGN})
|
||||
string(LENGTH ${str} length)
|
||||
if(ARGS_COLOR)
|
||||
math(EXPR padding "${width}-(${length}-10*${ARGS_COLOR})")
|
||||
else()
|
||||
math(EXPR padding "${width}-${length}")
|
||||
endif()
|
||||
if(padding GREATER 0)
|
||||
foreach(i RANGE ${padding})
|
||||
set(str "${str}${char}")
|
||||
endforeach()
|
||||
endif()
|
||||
set(${out} ${str} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(join VALUES GLUE OUTPUT)
|
||||
string(REGEX REPLACE "([^\\]|^);" "\\1${GLUE}" _TMP_STR "${VALUES}")
|
||||
string(REGEX REPLACE "[\\](.)" "\\1" _TMP_STR "${_TMP_STR}") #fixes escaping
|
||||
set(${OUTPUT} "${_TMP_STR}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(generate_package_dependencies)
|
||||
join("${PROJECT_INTERFACE_PACKAGE_DEPENDENCIES}" " " DEPS)
|
||||
set(PACKAGE_DEPENDENCIES "\
|
||||
####### Expanded from @PACKAGE_DEPENDENCIES@ by configure_package_config_file() #######
|
||||
|
||||
set(${PROJECT_NAME}_PACKAGE_DEPENDENCIES ${DEPS})
|
||||
|
||||
")
|
||||
foreach(dep IN LISTS PROJECT_INTERFACE_PACKAGE_DEPENDENCIES)
|
||||
join("${PROJECT_INTERFACE_${dep}_COMPONENTS}" " " COMPS)
|
||||
if(COMPS)
|
||||
string(CONCAT PACKAGE_DEPENDENCIES ${PACKAGE_DEPENDENCIES} "\
|
||||
set(${PROJECT_NAME}_${dep}_COMPONENTS ${COMPS})
|
||||
")
|
||||
endif()
|
||||
if(PROJECT_INTERFACE_${dep}_VERSION)
|
||||
string(CONCAT PACKAGE_DEPENDENCIES ${PACKAGE_DEPENDENCIES} "\
|
||||
set(${PROJECT_NAME}_${dep}_VERSION ${PROJECT_INTERFACE_${dep}_VERSION})
|
||||
")
|
||||
endif()
|
||||
endforeach()
|
||||
string(CONCAT PACKAGE_DEPENDENCIES ${PACKAGE_DEPENDENCIES} "\
|
||||
|
||||
#######################################################################################
|
||||
")
|
||||
set(PACKAGE_DEPENDENCIES ${PACKAGE_DEPENDENCIES} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Configure/Install CMake package
|
||||
macro(install_fairlogger_cmake_package)
|
||||
macro(install_cmake_package)
|
||||
include(CMakePackageConfigHelpers)
|
||||
set(PACKAGE_INSTALL_DESTINATION
|
||||
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}
|
||||
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_GIT_VERSION}
|
||||
)
|
||||
install(EXPORT ${FairLogger_EXPORT_SET}
|
||||
install(EXPORT ${PROJECT_EXPORT_SET}
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
DESTINATION ${PACKAGE_INSTALL_DESTINATION}
|
||||
EXPORT_LINK_INTERFACE_LIBRARIES
|
||||
)
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion
|
||||
)
|
||||
generate_package_dependencies() # fills ${PACKAGE_DEPENDENCIES}
|
||||
string(TOUPPER ${CMAKE_BUILD_TYPE} PROJECT_BUILD_TYPE_UPPER)
|
||||
set(PROJECT_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${PROJECT_BUILD_TYPE_UPPER}})
|
||||
configure_package_config_file(
|
||||
${CMAKE_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
|
||||
@@ -164,3 +242,98 @@ macro(install_fairlogger_cmake_package)
|
||||
DESTINATION ${PACKAGE_INSTALL_DESTINATION}
|
||||
)
|
||||
endmacro()
|
||||
|
||||
#
|
||||
# find_package2(PRIVATE|PUBLIC|INTERFACE <pkgname>
|
||||
# [VERSION <version>]
|
||||
# [COMPONENTS <list of components>]
|
||||
# [ADD_REQUIREMENTS_OF <list of dep_pgkname>]
|
||||
# [any other option the native find_package supports]...)
|
||||
#
|
||||
# Wrapper around CMake's native find_package command to add some features and bookkeeping.
|
||||
#
|
||||
# The qualifier (PRIVATE|PUBLIC|INTERFACE) to the package to populate
|
||||
# the variables PROJECT_[INTERFACE]_<pkgname>_([VERSION]|[COMPONENTS]|PACKAGE_DEPENDENCIES)
|
||||
# accordingly. This bookkeeping information is used to print our dependency found summary
|
||||
# table and to generate a part of our CMake package.
|
||||
#
|
||||
# When a dependending package is listed with ADD_REQUIREMENTS_OF the variables
|
||||
# <dep_pkgname>_<pkgname>_VERSION|COMPONENTS are looked up to and added to the native
|
||||
# VERSION (selected highest version) and COMPONENTS (deduplicated) args.
|
||||
#
|
||||
# COMPONENTS and VERSION args are then just passed to the native find_package.
|
||||
#
|
||||
macro(find_package2 qualifier pkgname)
|
||||
cmake_parse_arguments(ARGS "" "VERSION" "COMPONENTS;ADD_REQUIREMENTS_OF" ${ARGN})
|
||||
|
||||
string(TOUPPER ${pkgname} pkgname_upper)
|
||||
set(__old_cpp__ ${CMAKE_PREFIX_PATH})
|
||||
set(CMAKE_PREFIX_PATH ${${pkgname_upper}_ROOT} $ENV{${pkgname_upper}_ROOT} ${CMAKE_PREFIX_PATH})
|
||||
|
||||
# build lists of required versions and components
|
||||
unset(__required_versions__)
|
||||
unset(__components__)
|
||||
if(ARGS_VERSION)
|
||||
list(APPEND __required_versions__ ${ARGS_VERSION})
|
||||
endif()
|
||||
if(ARGS_COMPONENTS)
|
||||
list(APPEND __components__ ${ARGS_COMPONENTS})
|
||||
endif()
|
||||
if(ARGS_ADD_REQUIREMENTS_OF)
|
||||
foreach(dep_pkgname IN LISTS ARGS_ADD_REQUIREMENTS_OF)
|
||||
if(${dep_pkgname}_${pkgname}_VERSION)
|
||||
list(APPEND __required_versions__ ${${dep_pkgname}_${pkgname}_VERSION})
|
||||
endif()
|
||||
if(${dep_pkgname}_${pkgname}_COMPONENTS)
|
||||
list(APPEND __components__ ${${dep_pkgname}_${pkgname}_COMPONENTS})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# select highest required version
|
||||
unset(__version__)
|
||||
if(__required_versions__)
|
||||
list(GET __required_versions__ 0 __version__)
|
||||
foreach(v IN LISTS __required_versions__)
|
||||
if(${v} VERSION_GREATER ${__version__})
|
||||
set(__version__ ${v})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
# deduplicate required component list
|
||||
if(__components__)
|
||||
list(REMOVE_DUPLICATES ARGS_COMPONENTS)
|
||||
endif()
|
||||
|
||||
# call native find_package
|
||||
if(__components__)
|
||||
find_package(${pkgname} ${__version__} QUIET COMPONENTS ${__components__} ${ARGS_UNPARSED_ARGUMENTS})
|
||||
else()
|
||||
find_package(${pkgname} ${__version__} QUIET ${ARGS_UNPARSED_ARGUMENTS})
|
||||
endif()
|
||||
|
||||
if(${pkgname}_FOUND)
|
||||
if(${qualifier} STREQUAL PRIVATE)
|
||||
set(PROJECT_${pkgname}_VERSION ${__version__})
|
||||
set(PROJECT_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
|
||||
set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname})
|
||||
elseif(${qualifier} STREQUAL PUBLIC)
|
||||
set(PROJECT_${pkgname}_VERSION ${__version__})
|
||||
set(PROJECT_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
|
||||
set(PROJECT_PACKAGE_DEPENDENCIES ${PROJECT_PACKAGE_DEPENDENCIES} ${pkgname})
|
||||
set(PROJECT_INTERFACE_${pkgname}_VERSION ${__version__})
|
||||
set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
|
||||
set(PROJECT_INTERFACE_PACKAGE_DEPENDENCIES ${PROJECT_INTERFACE_PACKAGE_DEPENDENCIES} ${pkgname})
|
||||
elseif(${qualifier} STREQUAL INTERFACE)
|
||||
set(PROJECT_INTERFACE_${pkgname}_VERSION ${__version__})
|
||||
set(PROJECT_INTERFACE_${pkgname}_COMPONENTS ${ARGS_COMPONENTS})
|
||||
set(PROJECT_INTERFACE_PACKAGE_DEPENDENCIES ${PROJECT_INTERFACE_PACKAGE_DEPENDENCIES} ${pkgname})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
unset(__version__)
|
||||
unset(__components__)
|
||||
unset(__required_versions__)
|
||||
set(CMAKE_PREFIX_PATH ${__old_cpp__})
|
||||
unset(__old_cpp__)
|
||||
endmacro()
|
||||
|
BIN
example.png
Normal file
BIN
example.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 220 KiB |
@@ -1,11 +1,11 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2014-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
#include <Logger.h>
|
||||
#include "Logger.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
@@ -13,59 +13,13 @@
|
||||
#include <chrono>
|
||||
#include <ctime> // strftime
|
||||
#include <iomanip> // setw, setfill
|
||||
#include <cstdio> // printf
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace fair
|
||||
{
|
||||
|
||||
enum class Color : int
|
||||
{
|
||||
fgBlack = 30,
|
||||
fgRed = 31,
|
||||
fgGreen = 32,
|
||||
fgYellow = 33,
|
||||
fgBlue = 34,
|
||||
fgMagenta = 35,
|
||||
fgCyan = 36,
|
||||
fgWhite = 37,
|
||||
fgDefault = 39,
|
||||
bgRed = 41,
|
||||
bgGreen = 42,
|
||||
bgBlue = 44,
|
||||
bgDefault = 49
|
||||
};
|
||||
|
||||
string startColor(Color color)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "\033[01;" << static_cast<int>(color) << "m";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
string endColor()
|
||||
{
|
||||
return "\033[0m";
|
||||
}
|
||||
|
||||
class ColorOut
|
||||
{
|
||||
public:
|
||||
ColorOut(Color color, const string& str)
|
||||
: fColor(color)
|
||||
, fStr(str)
|
||||
{}
|
||||
|
||||
friend ostream& operator<<(ostream& os, const ColorOut& w)
|
||||
{
|
||||
return os << "\033[01;" << static_cast<int>(w.fColor) << "m" << w.fStr << "\033[0m";
|
||||
}
|
||||
|
||||
private:
|
||||
Color fColor;
|
||||
const string& fStr;
|
||||
};
|
||||
|
||||
class ColoredSeverityWriter
|
||||
{
|
||||
public:
|
||||
@@ -75,43 +29,42 @@ class ColoredSeverityWriter
|
||||
|
||||
friend ostream& operator<<(ostream& os, const ColoredSeverityWriter& w)
|
||||
{
|
||||
switch (w.fSeverity)
|
||||
{
|
||||
switch (w.fSeverity) {
|
||||
case Severity::nolog:
|
||||
return os << "\033[01;" << static_cast<int>(Color::fgDefault) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::fgDefault) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
case Severity::fatal:
|
||||
return os << "\033[01;" << static_cast<int>(Color::bgRed) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::bgRed) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
case Severity::error:
|
||||
return os << "\033[01;" << static_cast<int>(Color::fgRed) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::fgRed) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
case Severity::warn:
|
||||
return os << "\033[01;" << static_cast<int>(Color::fgYellow) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::fgYellow) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
case Severity::state:
|
||||
return os << "\033[01;" << static_cast<int>(Color::fgMagenta) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::fgMagenta) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
case Severity::info:
|
||||
return os << "\033[01;" << static_cast<int>(Color::fgGreen) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::fgGreen) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
case Severity::debug:
|
||||
return os << "\033[01;" << static_cast<int>(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
case Severity::debug1:
|
||||
return os << "\033[01;" << static_cast<int>(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
case Severity::debug2:
|
||||
return os << "\033[01;" << static_cast<int>(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
case Severity::debug3:
|
||||
return os << "\033[01;" << static_cast<int>(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
case Severity::debug4:
|
||||
return os << "\033[01;" << static_cast<int>(Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::fgBlue) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
case Severity::trace:
|
||||
return os << "\033[01;" << static_cast<int>(Color::fgCyan) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
return os << "\033[01;" << static_cast<int>(Logger::Color::fgCyan) << "m" << Logger::SeverityName(w.fSeverity) << "\033[0m";
|
||||
break;
|
||||
default:
|
||||
return os << "UNKNOWN";
|
||||
@@ -132,6 +85,8 @@ Severity Logger::fMinSeverity = Severity::info;
|
||||
function<void()> Logger::fFatalCallback;
|
||||
unordered_map<string, pair<Severity, function<void(const string& content, const LogMetaData& metadata)>>> Logger::fCustomSinks;
|
||||
mutex Logger::fMtx;
|
||||
bool Logger::fIsDestructed = false;
|
||||
Logger::DestructionHelper fDestructionHelper;
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
const string Logger::fProcessName = getprogname();
|
||||
@@ -143,14 +98,20 @@ const string Logger::fProcessName = "?";
|
||||
|
||||
const unordered_map<string, Verbosity> Logger::fVerbosityMap =
|
||||
{
|
||||
{ "veryhigh", Verbosity::veryhigh },
|
||||
{ "high", Verbosity::high },
|
||||
{ "medium", Verbosity::medium },
|
||||
{ "low", Verbosity::low },
|
||||
{ "VERYHIGH", Verbosity::veryhigh },
|
||||
{ "HIGH", Verbosity::high },
|
||||
{ "MEDIUM", Verbosity::medium },
|
||||
{ "LOW", Verbosity::low }
|
||||
{ "veryhigh", Verbosity::veryhigh },
|
||||
{ "high", Verbosity::high },
|
||||
{ "medium", Verbosity::medium },
|
||||
{ "low", Verbosity::low },
|
||||
{ "verylow", Verbosity::verylow },
|
||||
{ "VERYHIGH", Verbosity::veryhigh },
|
||||
{ "HIGH", Verbosity::high },
|
||||
{ "MEDIUM", Verbosity::medium },
|
||||
{ "LOW", Verbosity::low },
|
||||
{ "VERYLOW", Verbosity::verylow },
|
||||
{ "user1", Verbosity::user1 },
|
||||
{ "user2", Verbosity::user2 },
|
||||
{ "user3", Verbosity::user3 },
|
||||
{ "user4", Verbosity::user4 }
|
||||
};
|
||||
|
||||
const unordered_map<string, Severity> Logger::fSeverityMap =
|
||||
@@ -161,16 +122,14 @@ const unordered_map<string, Severity> Logger::fSeverityMap =
|
||||
{ "ERROR", Severity::error },
|
||||
{ "warn", Severity::warn },
|
||||
{ "WARN", Severity::warn },
|
||||
{ "warning", Severity::warning },
|
||||
{ "WARNING", Severity::warning },
|
||||
{ "warning", Severity::warn },
|
||||
{ "WARNING", Severity::warn },
|
||||
{ "state", Severity::state },
|
||||
{ "STATE", Severity::state },
|
||||
{ "info", Severity::info },
|
||||
{ "INFO", Severity::info },
|
||||
{ "debug", Severity::debug },
|
||||
{ "DEBUG", Severity::debug },
|
||||
{ "trace", Severity::trace },
|
||||
{ "TRACE", Severity::trace },
|
||||
{ "debug1", Severity::debug1 },
|
||||
{ "DEBUG1", Severity::debug1 },
|
||||
{ "debug2", Severity::debug2 },
|
||||
@@ -178,7 +137,9 @@ const unordered_map<string, Severity> Logger::fSeverityMap =
|
||||
{ "debug3", Severity::debug3 },
|
||||
{ "DEBUG3", Severity::debug3 },
|
||||
{ "debug4", Severity::debug4 },
|
||||
{ "DEBUG4", Severity::debug4 }
|
||||
{ "DEBUG4", Severity::debug4 },
|
||||
{ "trace", Severity::trace },
|
||||
{ "TRACE", Severity::trace }
|
||||
};
|
||||
|
||||
const array<string, 12> Logger::fSeverityNames =
|
||||
@@ -199,9 +160,10 @@ const array<string, 12> Logger::fSeverityNames =
|
||||
}
|
||||
};
|
||||
|
||||
const array<string, 4> Logger::fVerbosityNames =
|
||||
const array<string, 5> Logger::fVerbosityNames =
|
||||
{
|
||||
{
|
||||
"verylow",
|
||||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
@@ -209,6 +171,25 @@ const array<string, 4> Logger::fVerbosityNames =
|
||||
}
|
||||
};
|
||||
|
||||
std::map<Verbosity, VerbositySpec> Logger::fVerbosities =
|
||||
{
|
||||
{ Verbosity::verylow, VerbositySpec::Make() },
|
||||
{ Verbosity::low, VerbositySpec::Make(VerbositySpec::Info::severity) },
|
||||
{ Verbosity::medium, VerbositySpec::Make(VerbositySpec::Info::timestamp_s,
|
||||
VerbositySpec::Info::severity) },
|
||||
{ Verbosity::high, VerbositySpec::Make(VerbositySpec::Info::process_name,
|
||||
VerbositySpec::Info::timestamp_s,
|
||||
VerbositySpec::Info::severity) },
|
||||
{ Verbosity::veryhigh, VerbositySpec::Make(VerbositySpec::Info::process_name,
|
||||
VerbositySpec::Info::timestamp_s,
|
||||
VerbositySpec::Info::severity,
|
||||
VerbositySpec::Info::file_line_function) },
|
||||
{ Verbosity::user1, VerbositySpec::Make(VerbositySpec::Info::severity) },
|
||||
{ Verbosity::user2, VerbositySpec::Make(VerbositySpec::Info::severity) },
|
||||
{ Verbosity::user3, VerbositySpec::Make(VerbositySpec::Info::severity) },
|
||||
{ Verbosity::user4, VerbositySpec::Make(VerbositySpec::Info::severity) }
|
||||
};
|
||||
|
||||
string Logger::SeverityName(Severity severity)
|
||||
{
|
||||
return fSeverityNames.at(static_cast<size_t>(severity));
|
||||
@@ -221,17 +202,19 @@ string Logger::VerbosityName(Verbosity verbosity)
|
||||
|
||||
Logger::Logger(Severity severity, const string& file, const string& line, const string& func)
|
||||
{
|
||||
chrono::time_point<chrono::system_clock> now = chrono::system_clock::now();
|
||||
size_t pos = file.rfind("/");
|
||||
if (!fIsDestructed) {
|
||||
chrono::time_point<chrono::system_clock> now = chrono::system_clock::now();
|
||||
size_t pos = file.rfind("/");
|
||||
|
||||
fMetaData.timestamp = chrono::system_clock::to_time_t(now);
|
||||
fMetaData.us = chrono::duration_cast<chrono::microseconds>(now.time_since_epoch()) % 1000000;
|
||||
fMetaData.process_name = fProcessName;
|
||||
fMetaData.file = file.substr(pos + 1);
|
||||
fMetaData.line = line;
|
||||
fMetaData.func = func;
|
||||
fMetaData.severity_name = fSeverityNames.at(static_cast<size_t>(severity));
|
||||
fMetaData.severity = severity;
|
||||
fMetaData.timestamp = chrono::system_clock::to_time_t(now);
|
||||
fMetaData.us = chrono::duration_cast<chrono::microseconds>(now.time_since_epoch()) % 1000000;
|
||||
fMetaData.process_name = fProcessName;
|
||||
fMetaData.file = file.substr(pos + 1);
|
||||
fMetaData.line = line;
|
||||
fMetaData.func = func;
|
||||
fMetaData.severity_name = fSeverityNames.at(static_cast<size_t>(severity));
|
||||
fMetaData.severity = severity;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::SetConsoleSeverity(const Severity severity)
|
||||
@@ -242,17 +225,19 @@ void Logger::SetConsoleSeverity(const Severity severity)
|
||||
|
||||
void Logger::SetConsoleSeverity(const string& severityStr)
|
||||
{
|
||||
if (fSeverityMap.count(severityStr))
|
||||
{
|
||||
if (fSeverityMap.count(severityStr)) {
|
||||
SetConsoleSeverity(fSeverityMap.at(severityStr));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
LOG(error) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'.";
|
||||
SetConsoleSeverity(Severity::info);
|
||||
}
|
||||
}
|
||||
|
||||
Severity Logger::GetConsoleSeverity()
|
||||
{
|
||||
return fConsoleSeverity;
|
||||
}
|
||||
|
||||
void Logger::SetFileSeverity(const Severity severity)
|
||||
{
|
||||
fFileSeverity = severity;
|
||||
@@ -261,12 +246,9 @@ void Logger::SetFileSeverity(const Severity severity)
|
||||
|
||||
void Logger::SetFileSeverity(const string& severityStr)
|
||||
{
|
||||
if (fSeverityMap.count(severityStr))
|
||||
{
|
||||
if (fSeverityMap.count(severityStr)) {
|
||||
SetFileSeverity(fSeverityMap.at(severityStr));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
LOG(error) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'.";
|
||||
SetFileSeverity(Severity::info);
|
||||
}
|
||||
@@ -280,25 +262,96 @@ void Logger::SetCustomSeverity(const string& key, const Severity severity)
|
||||
|
||||
void Logger::SetCustomSeverity(const string& key, const string& severityStr)
|
||||
{
|
||||
if (fSeverityMap.count(severityStr))
|
||||
{
|
||||
if (fSeverityMap.count(severityStr)) {
|
||||
SetCustomSeverity(key, fSeverityMap.at(severityStr));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
LOG(error) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'.";
|
||||
SetCustomSeverity(key, Severity::info);
|
||||
}
|
||||
}
|
||||
|
||||
auto Logger::CycleConsoleSeverityUp() -> void
|
||||
{
|
||||
int current = static_cast<int>(fConsoleSeverity);
|
||||
if (current == static_cast<int>(fSeverityNames.size()) - 1) {
|
||||
SetConsoleSeverity(static_cast<Severity>(0));
|
||||
} else {
|
||||
SetConsoleSeverity(static_cast<Severity>(current + 1));
|
||||
}
|
||||
int newCurrent = static_cast<int>(fConsoleSeverity);
|
||||
stringstream ss;
|
||||
|
||||
for (int i = 0; i < static_cast<int>(fSeverityNames.size()); ++i) {
|
||||
ss << (i == newCurrent ? ">" : " ") << fSeverityNames.at(i) << (i == newCurrent ? "<" : " ");
|
||||
}
|
||||
|
||||
ss << "\n\n";
|
||||
cout << ss.str() << flush;
|
||||
}
|
||||
|
||||
auto Logger::CycleConsoleSeverityDown() -> void
|
||||
{
|
||||
int current = static_cast<int>(fConsoleSeverity);
|
||||
if (current == 0) {
|
||||
SetConsoleSeverity(static_cast<Severity>(fSeverityNames.size() - 1));
|
||||
} else {
|
||||
SetConsoleSeverity(static_cast<Severity>(current - 1));
|
||||
}
|
||||
int newCurrent = static_cast<int>(fConsoleSeverity);
|
||||
stringstream ss;
|
||||
|
||||
for (int i = 0; i < static_cast<int>(fSeverityNames.size()); ++i) {
|
||||
ss << (i == newCurrent ? ">" : " ") << fSeverityNames.at(i) << (i == newCurrent ? "<" : " ");
|
||||
}
|
||||
|
||||
ss << "\n\n";
|
||||
cout << ss.str() << flush;
|
||||
}
|
||||
|
||||
auto Logger::CycleVerbosityUp() -> void
|
||||
{
|
||||
int current = static_cast<int>(fVerbosity);
|
||||
if (current == static_cast<int>(fVerbosityNames.size() - 1)) {
|
||||
SetVerbosity(static_cast<Verbosity>(0));
|
||||
} else {
|
||||
SetVerbosity(static_cast<Verbosity>(current + 1));
|
||||
}
|
||||
int newCurrent = static_cast<int>(fVerbosity);
|
||||
stringstream ss;
|
||||
|
||||
for (int i = 0; i < static_cast<int>(fVerbosityNames.size()); ++i) {
|
||||
ss << (i == newCurrent ? ">" : " ") << fVerbosityNames.at(i) << (i == newCurrent ? "<" : " ");
|
||||
}
|
||||
|
||||
ss << "\n\n";
|
||||
cout << ss.str() << flush;
|
||||
}
|
||||
|
||||
auto Logger::CycleVerbosityDown() -> void
|
||||
{
|
||||
int current = static_cast<int>(fVerbosity);
|
||||
if (current == 0) {
|
||||
SetVerbosity(static_cast<Verbosity>(fVerbosityNames.size() - 1));
|
||||
} else {
|
||||
SetVerbosity(static_cast<Verbosity>(current - 1));
|
||||
}
|
||||
int newCurrent = static_cast<int>(fVerbosity);
|
||||
stringstream ss;
|
||||
|
||||
for (int i = 0; i < static_cast<int>(fVerbosityNames.size()); ++i) {
|
||||
ss << (i == newCurrent ? ">" : " ") << fVerbosityNames.at(i) << (i == newCurrent ? "<" : " ");
|
||||
}
|
||||
|
||||
ss << "\n\n";
|
||||
cout << ss.str() << flush;
|
||||
}
|
||||
|
||||
void Logger::UpdateMinSeverity()
|
||||
{
|
||||
fMinSeverity = (fConsoleSeverity <= fFileSeverity) ? fFileSeverity : fConsoleSeverity;
|
||||
|
||||
for (auto& it : fCustomSinks)
|
||||
{
|
||||
if (fMinSeverity <= it.second.first)
|
||||
{
|
||||
for (auto& it : fCustomSinks) {
|
||||
if (fMinSeverity <= it.second.first) {
|
||||
fMinSeverity = it.second.first;
|
||||
}
|
||||
}
|
||||
@@ -306,16 +359,22 @@ void Logger::UpdateMinSeverity()
|
||||
|
||||
bool Logger::Logging(Severity severity)
|
||||
{
|
||||
if (Severity::fatal == severity)
|
||||
{
|
||||
if (Severity::fatal == severity) {
|
||||
return true;
|
||||
}
|
||||
if (severity <= fMinSeverity && severity > Severity::nolog)
|
||||
{
|
||||
if (severity <= fMinSeverity && severity > Severity::nolog) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
bool Logger::Logging(const std::string& severityStr)
|
||||
{
|
||||
if (fSeverityMap.count(severityStr)) {
|
||||
return Logging(fSeverityMap.at(severityStr));
|
||||
} else {
|
||||
LOG(error) << "Unknown severity setting: '" << severityStr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -327,17 +386,33 @@ void Logger::SetVerbosity(const Verbosity verbosity)
|
||||
|
||||
void Logger::SetVerbosity(const string& verbosityStr)
|
||||
{
|
||||
if (fVerbosityMap.count(verbosityStr))
|
||||
{
|
||||
if (fVerbosityMap.count(verbosityStr)) {
|
||||
fVerbosity = fVerbosityMap.at(verbosityStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
LOG(error) << "Unknown verbosity setting: '" << verbosityStr << "', setting to default 'low'.";
|
||||
fVerbosity = Verbosity::low;
|
||||
}
|
||||
}
|
||||
|
||||
Verbosity Logger::GetVerbosity()
|
||||
{
|
||||
return fVerbosity;
|
||||
}
|
||||
|
||||
void Logger::DefineVerbosity(const Verbosity verbosity, const VerbositySpec spec)
|
||||
{
|
||||
fVerbosities[verbosity] = spec;
|
||||
}
|
||||
|
||||
void Logger::DefineVerbosity(const std::string& verbosityStr, const VerbositySpec spec)
|
||||
{
|
||||
if (fVerbosityMap.count(verbosityStr)) {
|
||||
DefineVerbosity(fVerbosityMap.at(verbosityStr), spec);
|
||||
} else {
|
||||
LOG(error) << "Unknown verbosity: '" << verbosityStr;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::SetConsoleColor(const bool colored)
|
||||
{
|
||||
fColored = colored;
|
||||
@@ -346,15 +421,13 @@ void Logger::SetConsoleColor(const bool colored)
|
||||
void Logger::InitFileSink(const Severity severity, const string& filename, bool customizeName)
|
||||
{
|
||||
lock_guard<mutex> lock(fMtx);
|
||||
if (fFileStream.is_open())
|
||||
{
|
||||
if (fFileStream.is_open()) {
|
||||
fFileStream.close();
|
||||
}
|
||||
|
||||
string fullName = filename;
|
||||
|
||||
if (customizeName)
|
||||
{
|
||||
if (customizeName) {
|
||||
// TODO: customize file name
|
||||
auto now = chrono::system_clock::to_time_t(chrono::system_clock::now());
|
||||
stringstream ss;
|
||||
@@ -370,13 +443,10 @@ void Logger::InitFileSink(const Severity severity, const string& filename, bool
|
||||
|
||||
fFileStream.open(fullName, fstream::out | fstream::app);
|
||||
|
||||
if (fFileStream.is_open())
|
||||
{
|
||||
if (fFileStream.is_open()) {
|
||||
fFileSeverity = severity;
|
||||
UpdateMinSeverity();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
cout << "Error opening file: " << fullName;
|
||||
}
|
||||
|
||||
@@ -384,12 +454,9 @@ void Logger::InitFileSink(const Severity severity, const string& filename, bool
|
||||
|
||||
void Logger::InitFileSink(const string& severityStr, const string& filename, bool customizeName)
|
||||
{
|
||||
if (fSeverityMap.count(severityStr))
|
||||
{
|
||||
if (fSeverityMap.count(severityStr)) {
|
||||
InitFileSink(fSeverityMap.at(severityStr), filename, customizeName);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
LOG(error) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'.";
|
||||
InitFileSink(Severity::info, filename);
|
||||
}
|
||||
@@ -398,8 +465,7 @@ void Logger::InitFileSink(const string& severityStr, const string& filename, boo
|
||||
void Logger::RemoveFileSink()
|
||||
{
|
||||
lock_guard<mutex> lock(fMtx);
|
||||
if (fFileStream.is_open())
|
||||
{
|
||||
if (fFileStream.is_open()) {
|
||||
fFileStream.close();
|
||||
}
|
||||
}
|
||||
@@ -433,25 +499,19 @@ void Logger::OnFatal(function<void()> func)
|
||||
void Logger::AddCustomSink(const string& key, Severity severity, function<void(const string& content, const LogMetaData& metadata)> func)
|
||||
{
|
||||
lock_guard<mutex> lock(fMtx);
|
||||
if (fCustomSinks.count(key) == 0)
|
||||
{
|
||||
if (fCustomSinks.count(key) == 0) {
|
||||
fCustomSinks.insert(make_pair(key, make_pair(severity, func)));
|
||||
UpdateMinSeverity();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
cout << "Logger::AddCustomSink: sink '" << key << "' already exists, will not add again. Remove first with Logger::RemoveCustomSink(const string& key)" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::AddCustomSink(const string& key, const string& severityStr, function<void(const string& content, const LogMetaData& metadata)> func)
|
||||
{
|
||||
if (fSeverityMap.count(severityStr))
|
||||
{
|
||||
if (fSeverityMap.count(severityStr)) {
|
||||
AddCustomSink(key, fSeverityMap.at(severityStr), func);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
LOG(error) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'.";
|
||||
AddCustomSink(key, Severity::info, func);
|
||||
}
|
||||
@@ -459,67 +519,116 @@ void Logger::AddCustomSink(const string& key, const string& severityStr, functio
|
||||
|
||||
void Logger::RemoveCustomSink(const string& key)
|
||||
{
|
||||
if (fCustomSinks.count(key) > 0)
|
||||
{
|
||||
if (fCustomSinks.count(key) > 0) {
|
||||
fCustomSinks.erase(key);
|
||||
UpdateMinSeverity();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
cout << "Logger::RemoveCustomSink: sink '" << key << "' doesn't exists, will not remove." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
Logger& Logger::Log()
|
||||
{
|
||||
if (fIsDestructed) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
char tsstr[32];
|
||||
if (!strftime(tsstr, sizeof(tsstr), "%H:%M:%S", localtime(&(fMetaData.timestamp))))
|
||||
{
|
||||
tsstr[0] = 'u';
|
||||
lock_guard<mutex> lock(fMtx); // localtime is not threadsafe, guard it
|
||||
if (!strftime(tsstr, sizeof(tsstr), "%H:%M:%S", localtime(&(fMetaData.timestamp)))) {
|
||||
tsstr[0] = 'u';
|
||||
}
|
||||
}
|
||||
|
||||
if ((!fColored && LoggingToConsole()) || LoggingToFile())
|
||||
{
|
||||
if (fVerbosity >= Verbosity::high)
|
||||
{
|
||||
fBWOut << "[" << fMetaData.process_name << "]"
|
||||
<< "[" << tsstr << "." << setw(6) << setfill('0') << fMetaData.us.count() << "]";
|
||||
}
|
||||
else if (fVerbosity == Verbosity::medium)
|
||||
{
|
||||
fBWOut << "[" << tsstr << "]";
|
||||
auto spec = fVerbosities[fVerbosity];
|
||||
|
||||
if ((!fColored && LoggingToConsole()) || LoggingToFile()) {
|
||||
bool appendSpace = false;
|
||||
for (const auto info : spec.fOrder) {
|
||||
switch (info) {
|
||||
case VerbositySpec::Info::process_name:
|
||||
fBWOut << "[" << fMetaData.process_name << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::timestamp_us:
|
||||
fBWOut << "[" << tsstr << "." << setw(6) << setfill('0') << fMetaData.us.count() << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::timestamp_s:
|
||||
fBWOut << "[" << tsstr << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::severity:
|
||||
fBWOut << "[" << fMetaData.severity_name << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::file_line_function:
|
||||
fBWOut << "[" << fMetaData.file << ":" << fMetaData.line << ":" << fMetaData.func << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::file_line:
|
||||
fBWOut << "[" << fMetaData.file << ":" << fMetaData.line << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::file:
|
||||
fBWOut << "[" << fMetaData.file << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fBWOut << "[" << fMetaData.severity_name << "]";
|
||||
|
||||
if (fVerbosity == Verbosity::veryhigh)
|
||||
{
|
||||
fBWOut << "[" << fMetaData.file << ":" << fMetaData.line << ":" << fMetaData.func << "]";
|
||||
if (appendSpace) {
|
||||
fBWOut << " ";
|
||||
}
|
||||
|
||||
fBWOut << " ";
|
||||
}
|
||||
|
||||
if (fColored && (LoggingToConsole()))
|
||||
{
|
||||
if (fVerbosity >= Verbosity::high)
|
||||
{
|
||||
fColorOut << "[" << ColorOut(Color::fgBlue, fMetaData.process_name) << "]"
|
||||
<< "[" << startColor(Color::fgCyan) << tsstr << "." << setw(6) << setfill('0') << fMetaData.us.count() << endColor() << "]";
|
||||
}
|
||||
else if (fVerbosity == Verbosity::medium)
|
||||
{
|
||||
fColorOut << "[" << startColor(Color::fgCyan) << tsstr << endColor() << "]";
|
||||
if (fColored && LoggingToConsole()) {
|
||||
bool appendSpace = false;
|
||||
for (const auto info : spec.fOrder) {
|
||||
switch (info) {
|
||||
case VerbositySpec::Info::process_name:
|
||||
fColorOut << "[" << ColorOut(Color::fgBlue, fMetaData.process_name) << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::timestamp_us:
|
||||
fColorOut << "[" << startColor(Color::fgCyan) << tsstr << "."
|
||||
<< setw(6) << setfill('0') << fMetaData.us.count() << endColor() << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::timestamp_s:
|
||||
fColorOut << "[" << startColor(Color::fgCyan) << tsstr << endColor() << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::severity:
|
||||
fColorOut << "[" << ColoredSeverityWriter(fMetaData.severity) << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::file_line_function:
|
||||
fColorOut << "[" << ColorOut(Color::fgBlue, fMetaData.file) << ":"
|
||||
<< ColorOut(Color::fgYellow, fMetaData.line) << ":"
|
||||
<< ColorOut(Color::fgBlue, fMetaData.func) << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::file_line:
|
||||
fColorOut << "[" << ColorOut(Color::fgBlue, fMetaData.file) << ":"
|
||||
<< ColorOut(Color::fgYellow, fMetaData.line) << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
case VerbositySpec::Info::file:
|
||||
fColorOut << "[" << ColorOut(Color::fgBlue, fMetaData.file) << "]";
|
||||
appendSpace = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fColorOut << "[" << ColoredSeverityWriter(fMetaData.severity) << "]";
|
||||
|
||||
if (fVerbosity == Verbosity::veryhigh)
|
||||
{
|
||||
fColorOut << "[" << ColorOut(Color::fgBlue, fMetaData.file) << ":" << ColorOut(Color::fgYellow, fMetaData.line) << ":" << ColorOut(Color::fgBlue, fMetaData.func) << "]";
|
||||
if (appendSpace) {
|
||||
fColorOut << " ";
|
||||
}
|
||||
|
||||
fColorOut << " ";
|
||||
}
|
||||
|
||||
return *this;
|
||||
@@ -539,10 +648,13 @@ Logger& Logger::operator<<(ostream& (*manip) (ostream&))
|
||||
|
||||
Logger::~Logger() noexcept(false)
|
||||
{
|
||||
for (auto& it : fCustomSinks)
|
||||
{
|
||||
if (LoggingCustom(it.second.first))
|
||||
{
|
||||
if (fIsDestructed) {
|
||||
printf("post-static destruction output: %s\n", fContent.str().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& it : fCustomSinks) {
|
||||
if (LoggingCustom(it.second.first)) {
|
||||
lock_guard<mutex> lock(fMtx);
|
||||
it.second.second(fContent.str(), fMetaData);
|
||||
}
|
||||
@@ -552,32 +664,24 @@ Logger::~Logger() noexcept(false)
|
||||
|
||||
fBWOut << fContent.str();
|
||||
|
||||
if (LoggingToConsole())
|
||||
{
|
||||
if (fColored)
|
||||
{
|
||||
if (LoggingToConsole()) {
|
||||
if (fColored) {
|
||||
fColorOut << fContent.str();
|
||||
cout << fColorOut.str() << flush;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
cout << fBWOut.str() << flush;
|
||||
}
|
||||
}
|
||||
|
||||
if (LoggingToFile())
|
||||
{
|
||||
if (LoggingToFile()) {
|
||||
lock_guard<mutex> lock(fMtx);
|
||||
if (fFileStream.is_open())
|
||||
{
|
||||
if (fFileStream.is_open()) {
|
||||
fFileStream << fBWOut.str() << flush;
|
||||
}
|
||||
}
|
||||
|
||||
if (fMetaData.severity == Severity::fatal)
|
||||
{
|
||||
if (fFatalCallback)
|
||||
{
|
||||
if (fMetaData.severity == Severity::fatal) {
|
||||
if (fFatalCallback) {
|
||||
fFatalCallback();
|
||||
}
|
||||
}
|
||||
|
172
logger/Logger.h
172
logger/Logger.h
@@ -18,11 +18,19 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <utility> // pair
|
||||
#include <time.h> // time_t
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef FAIRLOGGER_USE_BOOST_PRETTY_FUNCTION
|
||||
#include <boost/current_function.hpp>
|
||||
#endif
|
||||
|
||||
namespace fair
|
||||
{
|
||||
@@ -59,21 +67,81 @@ enum class Severity : int
|
||||
};
|
||||
|
||||
// verbosity levels:
|
||||
// verylow: message
|
||||
// low: [severity] message
|
||||
// medium: [HH:MM:SS][severity] message
|
||||
// high: [process name][HH:MM:SS:µS][severity] message
|
||||
// veryhigh: [process name][HH:MM:SS:µS][severity][file:line:function] message
|
||||
enum class Verbosity : int
|
||||
{
|
||||
verylow,
|
||||
low,
|
||||
medium,
|
||||
high,
|
||||
veryhigh,
|
||||
// backwards-compatibility:
|
||||
VERYLOW = verylow,
|
||||
LOW = low,
|
||||
MEDIUM = medium,
|
||||
HIGH = high,
|
||||
VERYHIGH = veryhigh
|
||||
VERYHIGH = veryhigh,
|
||||
// extra slots for user-defined verbosities:
|
||||
user1,
|
||||
user2,
|
||||
user3,
|
||||
user4,
|
||||
};
|
||||
|
||||
struct VerbositySpec
|
||||
{
|
||||
enum class Info : int
|
||||
{
|
||||
__empty__ = 0, // used to initialize order array
|
||||
process_name, // [process name]
|
||||
timestamp_s, // [HH:MM:SS]
|
||||
timestamp_us, // [HH:MM:SS:µS]
|
||||
severity, // [severity]
|
||||
file, // [file]
|
||||
file_line, // [file:line]
|
||||
file_line_function, // [file:line:function]
|
||||
__max__ // needs to be last in enum
|
||||
};
|
||||
|
||||
std::array<Info, static_cast<int>(Info::__max__)> fOrder;
|
||||
|
||||
VerbositySpec() : fOrder({Info::__empty__}) {}
|
||||
|
||||
template<typename ... Ts>
|
||||
static VerbositySpec Make(Ts ... options)
|
||||
{
|
||||
static_assert(sizeof...(Ts) < static_cast<int>(Info::__max__),
|
||||
"Maximum number of VerbositySpec::Info parameters exceeded.");
|
||||
|
||||
return Make(VerbositySpec(), 0, options...);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T, typename ... Ts>
|
||||
static VerbositySpec Make(VerbositySpec spec, int i, T option, Ts ... options)
|
||||
{
|
||||
static_assert(std::is_same<T, Info>::value,
|
||||
"Only arguments of type VerbositySpec::Info are allowed.");
|
||||
|
||||
assert(option > Info::__empty__);
|
||||
assert(option < Info::__max__);
|
||||
|
||||
if (std::find(spec.fOrder.begin(), spec.fOrder.end(), option) == spec.fOrder.end()) {
|
||||
spec.fOrder[i] = option;
|
||||
++i;
|
||||
}
|
||||
|
||||
return Make(spec, i, options ...);
|
||||
}
|
||||
|
||||
static VerbositySpec Make(VerbositySpec spec, int)
|
||||
{
|
||||
return spec;
|
||||
}
|
||||
};
|
||||
|
||||
// non-std exception to avoid undesirable catches - fatal should exit in a way we want.
|
||||
@@ -114,8 +182,85 @@ class Logger
|
||||
public:
|
||||
Logger(Severity severity, const std::string& file, const std::string& line, const std::string& func);
|
||||
|
||||
enum class Color : int
|
||||
{
|
||||
bold = 1,
|
||||
dim = 2,
|
||||
underline = 4,
|
||||
blink = 5,
|
||||
reverse = 7,
|
||||
hidden = 8,
|
||||
|
||||
fgDefault = 39,
|
||||
fgBlack = 30,
|
||||
fgRed = 31,
|
||||
fgGreen = 32,
|
||||
fgYellow = 33,
|
||||
fgBlue = 34,
|
||||
fgMagenta = 35,
|
||||
fgCyan = 36,
|
||||
fgLightGray = 37,
|
||||
fgDarkGray = 90,
|
||||
fgLightRed = 91,
|
||||
fgLightGreen = 92,
|
||||
fgLightYellow = 93,
|
||||
fgLightBlue = 94,
|
||||
fgLightMagenta = 95,
|
||||
fgLightCyan = 96,
|
||||
fgWhite = 97,
|
||||
|
||||
bgDefault = 49,
|
||||
bgBlack = 40,
|
||||
bgRed = 41,
|
||||
bgGreen = 42,
|
||||
bgYellow = 43,
|
||||
bgBlue = 44,
|
||||
bgMagenta = 45,
|
||||
bgCyan = 46,
|
||||
bgLightGray = 47,
|
||||
bgDarkGray = 100,
|
||||
bgLightRed = 101,
|
||||
bgLightGreen = 102,
|
||||
bgLightYellow = 103,
|
||||
bgLightBlue = 104,
|
||||
bgLightMagenta = 105,
|
||||
bgLightCyan = 106,
|
||||
bgWhite = 107
|
||||
};
|
||||
|
||||
static std::string startColor(Color color)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "\033[01;" << static_cast<int>(color) << "m";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
static std::string endColor()
|
||||
{
|
||||
return "\033[0m";
|
||||
}
|
||||
|
||||
class ColorOut
|
||||
{
|
||||
public:
|
||||
ColorOut(Color color, const std::string& str)
|
||||
: fColor(color)
|
||||
, fStr(str)
|
||||
{}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const ColorOut& w)
|
||||
{
|
||||
return os << "\033[01;" << static_cast<int>(w.fColor) << "m" << w.fStr << "\033[0m";
|
||||
}
|
||||
|
||||
private:
|
||||
Color fColor;
|
||||
const std::string& fStr;
|
||||
};
|
||||
|
||||
static void SetConsoleSeverity(const Severity severity);
|
||||
static void SetConsoleSeverity(const std::string& severityStr);
|
||||
static Severity GetConsoleSeverity();
|
||||
|
||||
static void SetFileSeverity(const Severity severity);
|
||||
static void SetFileSeverity(const std::string& severityStr);
|
||||
@@ -123,10 +268,19 @@ class Logger
|
||||
static void SetCustomSeverity(const std::string& key, const Severity severity);
|
||||
static void SetCustomSeverity(const std::string& key, const std::string& severityStr);
|
||||
|
||||
static void CycleConsoleSeverityUp();
|
||||
static void CycleConsoleSeverityDown();
|
||||
static void CycleVerbosityUp();
|
||||
static void CycleVerbosityDown();
|
||||
|
||||
static bool Logging(const Severity severity);
|
||||
static bool Logging(const std::string& severityStr);
|
||||
|
||||
static void SetVerbosity(const Verbosity verbosity);
|
||||
static void SetVerbosity(const std::string& verbosityStr);
|
||||
static Verbosity GetVerbosity();
|
||||
static void DefineVerbosity(const Verbosity, VerbositySpec);
|
||||
static void DefineVerbosity(const std::string& verbosityStr, VerbositySpec);
|
||||
|
||||
static void SetConsoleColor(const bool colored = true);
|
||||
|
||||
@@ -177,10 +331,14 @@ class Logger
|
||||
static const std::unordered_map<std::string, Verbosity> fVerbosityMap;
|
||||
static const std::unordered_map<std::string, Severity> fSeverityMap;
|
||||
static const std::array<std::string, 12> fSeverityNames;
|
||||
static const std::array<std::string, 4> fVerbosityNames;
|
||||
static const std::array<std::string, 5> fVerbosityNames;
|
||||
|
||||
virtual ~Logger() noexcept(false);
|
||||
|
||||
// protection for use after static destruction took place
|
||||
static bool fIsDestructed;
|
||||
static struct DestructionHelper { ~DestructionHelper() { Logger::fIsDestructed = true; }} fDestructionHelper;
|
||||
|
||||
private:
|
||||
LogMetaData fMetaData;
|
||||
|
||||
@@ -206,6 +364,8 @@ class Logger
|
||||
bool LoggingCustom(const Severity) const;
|
||||
|
||||
static void UpdateMinSeverity();
|
||||
|
||||
static std::map<Verbosity, VerbositySpec> fVerbosities;
|
||||
};
|
||||
|
||||
} // namespace fair
|
||||
@@ -213,9 +373,15 @@ class Logger
|
||||
#define IMP_CONVERTTOSTRING(s) # s
|
||||
#define CONVERTTOSTRING(s) IMP_CONVERTTOSTRING(s)
|
||||
|
||||
#ifdef FAIRLOGGER_USE_BOOST_PRETTY_FUNCTION
|
||||
#define LOG(severity) \
|
||||
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(fair::Severity::severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
|
||||
fair::Logger(fair::Severity::severity, __FILE__, CONVERTTOSTRING(__LINE__), BOOST_CURRENT_FUNCTION).Log()
|
||||
#else
|
||||
#define LOG(severity) \
|
||||
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(fair::Severity::severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
|
||||
fair::Logger(fair::Severity::severity, __FILE__, CONVERTTOSTRING(__LINE__), __FUNCTION__).Log()
|
||||
#endif
|
||||
|
||||
// with custom file, line, function
|
||||
#define LOGD(severity, file, line, function) \
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2018-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -10,11 +10,10 @@
|
||||
|
||||
#define FAIRLOGGER_VERSION "@PROJECT_VERSION@"
|
||||
#define FAIRLOGGER_VERSION_DEC (@PROJECT_VERSION_MAJOR@ * 10000) + (@PROJECT_VERSION_MINOR@ * 100) + @PROJECT_VERSION_PATCH@
|
||||
#define FAIRLOGGER_VERSION_HEX (@PROJECT_VERSION_MAJOR@ << 16) + (@PROJECT_VERSION_MINOR@ << 8) + @PROJECT_VERSION_PATCH@
|
||||
#define FAIRLOGGER_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
|
||||
#define FAIRLOGGER_VERSION_MINOR @PROJECT_VERSION_MINOR@
|
||||
#define FAIRLOGGER_VERSION_PATCH @PROJECT_VERSION_PATCH@
|
||||
#define FAIRLOGGER_GIT_VERSION "@FairLogger_GIT_VERSION@"
|
||||
#define FAIRLOGGER_GIT_DATE "@FairLogger_GIT_DATE@"
|
||||
#define FAIRLOGGER_GIT_VERSION "@PROJECT_GIT_VERSION@"
|
||||
#define FAIRLOGGER_GIT_DATE "@PROJECT_GIT_DATE@"
|
||||
|
||||
#endif // FAIR_LOGGER_VERSION_H
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************
|
||||
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* Copyright (C) 2014-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
@@ -18,6 +18,9 @@
|
||||
using namespace std;
|
||||
using namespace fair;
|
||||
|
||||
namespace test
|
||||
{
|
||||
|
||||
void printEverySeverity()
|
||||
{
|
||||
static int i = 1;
|
||||
@@ -35,42 +38,74 @@ void printEverySeverity()
|
||||
LOG(trace) << "trace message " << i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void printAllVerbositiesWithSeverity(Severity sev)
|
||||
{
|
||||
Logger::SetConsoleSeverity(sev);
|
||||
|
||||
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'verylow' verbosity..." << endl;
|
||||
Logger::SetVerbosity(Verbosity::verylow);
|
||||
test::printEverySeverity();
|
||||
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'low' verbosity..." << endl;
|
||||
Logger::SetVerbosity(Verbosity::low);
|
||||
printEverySeverity();
|
||||
test::printEverySeverity();
|
||||
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'medium' verbosity..." << endl;
|
||||
Logger::SetVerbosity(Verbosity::medium);
|
||||
printEverySeverity();
|
||||
test::printEverySeverity();
|
||||
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'high' verbosity..." << endl;
|
||||
Logger::SetVerbosity(Verbosity::high);
|
||||
printEverySeverity();
|
||||
test::printEverySeverity();
|
||||
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'veryhigh' verbosity..." << endl;
|
||||
Logger::SetVerbosity(Verbosity::veryhigh);
|
||||
printEverySeverity();
|
||||
test::printEverySeverity();
|
||||
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user1' verbosity..." << endl;
|
||||
Logger::SetVerbosity(Verbosity::user1);
|
||||
test::printEverySeverity();
|
||||
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user2' verbosity..." << endl;
|
||||
Logger::SetVerbosity(Verbosity::user2);
|
||||
test::printEverySeverity();
|
||||
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user3' verbosity..." << endl;
|
||||
Logger::SetVerbosity(Verbosity::user3);
|
||||
test::printEverySeverity();
|
||||
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user4' verbosity..." << endl;
|
||||
Logger::SetVerbosity(Verbosity::user4);
|
||||
test::printEverySeverity();
|
||||
}
|
||||
|
||||
void silentlyPrintAllVerbositiesWithSeverity(Severity sev)
|
||||
{
|
||||
Logger::SetConsoleSeverity(sev);
|
||||
|
||||
Logger::SetVerbosity(Verbosity::verylow);
|
||||
test::printEverySeverity();
|
||||
Logger::SetVerbosity(Verbosity::low);
|
||||
printEverySeverity();
|
||||
test::printEverySeverity();
|
||||
Logger::SetVerbosity(Verbosity::medium);
|
||||
printEverySeverity();
|
||||
test::printEverySeverity();
|
||||
Logger::SetVerbosity(Verbosity::high);
|
||||
printEverySeverity();
|
||||
test::printEverySeverity();
|
||||
Logger::SetVerbosity(Verbosity::veryhigh);
|
||||
printEverySeverity();
|
||||
test::printEverySeverity();
|
||||
Logger::SetVerbosity(Verbosity::user1);
|
||||
test::printEverySeverity();
|
||||
Logger::SetVerbosity(Verbosity::user2);
|
||||
test::printEverySeverity();
|
||||
Logger::SetVerbosity(Verbosity::user3);
|
||||
test::printEverySeverity();
|
||||
Logger::SetVerbosity(Verbosity::user4);
|
||||
test::printEverySeverity();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Logger::SetConsoleColor(true);
|
||||
|
||||
auto spec = VerbositySpec::Make(VerbositySpec::Info::file_line_function,
|
||||
VerbositySpec::Info::process_name,VerbositySpec::Info::process_name);
|
||||
cout << "Defining custom verbosity \"user2\"" << endl;
|
||||
Logger::DefineVerbosity(Verbosity::user2, spec);
|
||||
|
||||
cout << "cout: testing severities..." << endl;
|
||||
|
||||
printAllVerbositiesWithSeverity(Severity::trace);
|
||||
@@ -128,7 +163,7 @@ int main()
|
||||
cout << "cout: ----------------------------" << endl;
|
||||
cout << "cout: open log file with severity 'error'" << endl;
|
||||
Logger::InitFileSink(Severity::error, "test_log", true);
|
||||
printEverySeverity();
|
||||
test::printEverySeverity();
|
||||
cout << "cout: closing log file" << endl;
|
||||
Logger::RemoveFileSink();
|
||||
|
||||
@@ -153,14 +188,13 @@ int main()
|
||||
cout << "CustomSink: \tfair::Severity severity: " << static_cast<int>(metadata.severity) << endl;
|
||||
});
|
||||
|
||||
printEverySeverity();
|
||||
test::printEverySeverity();
|
||||
|
||||
cout << endl << "cout: removing custom sink with info severity" << endl;
|
||||
|
||||
Logger::AddCustomSink("CustomSink", Severity::error, [](const string& content, const LogMetaData& metadata){});
|
||||
Logger::AddCustomSink("CustomSink", Severity::error, [](const string& /*content*/, const LogMetaData& /*metadata*/){});
|
||||
Logger::RemoveCustomSink("CustomSink");
|
||||
Logger::RemoveCustomSink("bla");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user