Compare commits

..

42 Commits

Author SHA1 Message Date
Dennis Klein
19e18ca05c Release 1.5.0-4 2019-08-10 01:46:25 +02:00
Dennis Klein
8cb955837e Refine package descriptions 2019-08-10 01:44:28 +02:00
Dennis Klein
ad55efc82b Release 1.5.0-3 2019-08-10 01:05:33 +02:00
Dennis Klein
210e1aa0b0 Fix dependency 2019-08-10 01:04:29 +02:00
Dennis Klein
b5a00887cd Release 1.5.0-2 2019-08-10 00:43:31 +02:00
Dennis Klein
6c41eceb05 Fix lib package 2019-08-10 00:43:43 +02:00
Dennis Klein
54e0ac2a83 Release 1.5.0-1 2019-08-10 00:43:31 +02:00
Dennis Klein
9949e83a14 Fix -Wsign-compare 2019-06-27 13:18:26 +02:00
Dennis Klein
4b462d2aa2 Fix -Wunused-parameter 2019-06-27 13:18:26 +02:00
Dennis Klein
28882b70ca CMake: Add dependency summary 2019-06-27 13:18:26 +02:00
Dennis Klein
1e427a2e55 CMake: Add summary about CXX flags 2019-06-27 13:18:26 +02:00
Dennis Klein
128bcceade CMake: Update CXX standard handling
* Print summary
2019-06-27 13:18:26 +02:00
Dennis Klein
bee04a260c CMake: Adopt find_package2
* Adds support for Boost 1.70

Resolves #14
2019-06-27 13:18:26 +02:00
Dennis Klein
8e9d91c596 CMake: Update CMake package
* Adopt generate_package_dependencies

Resolves #14
2019-06-27 13:18:26 +02:00
Dennis Klein
27dcf93d7f CMake: Update version logic 2019-06-27 13:18:26 +02:00
Dennis Klein
8976d98913 CMake: Set policies by version 2019-06-27 13:18:26 +02:00
Alexey Rybalchenko
3a5afe2d6a Add MacOS10.14 test machine to Jenkins 2019-01-23 18:12:33 +01:00
Alexey Rybalchenko
aaacaf316e Update alfa ci 2019-01-17 16:32:21 +01:00
Alexey Rybalchenko
180acaae26 Allow use after static destruction took place 2019-01-17 14:12:14 +01:00
Alexey Rybalchenko
2d5dd004cb Expose color tools 2019-01-02 09:18:30 +01:00
Alexey Rybalchenko
4c2c238030 Format 2019-01-02 09:18:30 +01:00
Dennis Klein
3e1de0a17b Support user-defined verbosity formats
* Add `fair::Logger::DefineVerbosity(...)` API
* Add documentation to README
* Optionally support `BOOST_PRETTY_FUNCTION`
2019-01-02 09:18:30 +01:00
Giulio Eulisse
7d0411b939 Use quotes to include local headers
In general angular brackets are used for external headers, while quotes are used for internal ones. Is there any particular reason not to follow the conventions? While this is admittedly left to the compiler implementor by the standard, some implementations, like gcc, do have a peculiar behavior for the two kind of `include` and the current solution might end up including something unwanted, especially given the quite "common" name (Logger) used.
2019-01-01 15:50:00 +01:00
Dennis Klein
9a8acdf6eb Enable PIC by default 2018-09-19 18:31:45 +02:00
Dennis Klein
0c2532e6b9 Reflect git version in build artifacts 2018-09-19 18:20:29 +02:00
Dennis Klein
49a6e9389d Support BUILD_SHARED_LIBS cmake variable 2018-09-19 18:19:55 +02:00
Alexey Rybalchenko
0901655a65 Update build machines 2018-07-30 19:46:30 +02:00
Alexey Rybalchenko
1f600fa981 guard localtime with a mutex to avoid race 2018-07-30 19:46:30 +02:00
Alexey Rybalchenko
63820e5f2c Add cycle methods and verylow verbosity (msg only) 2018-05-09 15:30:01 +02:00
Alexey Rybalchenko
de02bd068f add string version of Logging() 2018-05-02 15:32:06 +02:00
Dennis Klein
24001470e5 Add nightly/profile build pipeline 2018-05-02 14:56:55 +02:00
Dennis Klein
5696fef902 Generate relative RPATH 2018-04-20 20:03:12 +02:00
Dennis Klein
80b5eb6fb1 Do not install lib in its own directory 2018-04-19 19:49:05 +02:00
Dennis Klein
c26d4ba013 Remove cmake version constraint from CMake package 2018-04-18 15:47:19 +02:00
Dennis Klein
661bd88d81 Export CXX standard config 2018-04-18 15:34:57 +02:00
Dennis Klein
65068fd959 Enable install RPATH 2018-04-18 15:34:40 +02:00
Dennis Klein
00e7468b25 Add library versioning 2018-04-18 15:34:22 +02:00
Dennis Klein
af288551aa Export the correct include path 2018-04-18 00:01:26 +02:00
Dennis Klein
8f68cef9e3 Enable C language to get rid of a warning in alfa-ci
This should rather be solved in the build environment, which is work on
the todo list.
2018-04-12 21:36:05 +02:00
Dennis Klein
6d71d22986 Use status messages 2018-04-12 21:10:56 +02:00
Dennis Klein
e72a0409a6 Remove check for share directory which does not exist 2018-04-12 19:53:17 +02:00
Dennis Klein
88c13b67cc Update 2018-04-11 16:11:36 +02:00
25 changed files with 1302 additions and 305 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
build/
.vscode

View File

@@ -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 " ")
################################################################################

View File

@@ -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
View File

@@ -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
View 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
View File

@@ -2,6 +2,8 @@
Lightweight and fast C++ Logging Library
![example output](example.png)
| Branch | Build Status |
| :---: | :--- |
| `master` | ![build status master branch](https://alfa-ci.gsi.de/buildStatus/icon?job=FairRootGroup/FairLogger/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

View File

@@ -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)

View File

@@ -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()

23
debian/changelog vendored Normal file
View File

@@ -0,0 +1,23 @@
fairlogger (1.5.0-4) bionic; urgency=low
* Refine package descriptions
-- Dennis Klein <d.klein@gsi.de> Sat, 10 Aug 2019 01:44:53 +0200
fairlogger (1.5.0-3) bionic; urgency=high
* Fix dependency
-- Dennis Klein <d.klein@gsi.de> Sat, 10 Aug 2019 01:04:53 +0200
fairlogger (1.5.0-2) bionic; urgency=high
* Fix lib package
-- Dennis Klein <d.klein@gsi.de> Sat, 10 Aug 2019 00:41:10 +0200
fairlogger (1.5.0-1) bionic; urgency=medium
* Initial release
-- Dennis Klein <d.klein@gsi.de> Fri, 09 Aug 2019 19:43:33 +0200

1
debian/compat vendored Normal file
View File

@@ -0,0 +1 @@
10

26
debian/control vendored Normal file
View File

@@ -0,0 +1,26 @@
Source: fairlogger
Priority: optional
Maintainer: Dennis Klein <d.klein@gsi.de>
Build-Depends: debhelper (>= 10), cmake (>= 3.9.4), libboost1.65-dev
Standards-Version: 4.1.2
Section: libs
Homepage: https://github.com/FairRootGroup/FairLogger
Vcs-Git: https://github.com/FairRootGroup/FairLogger
Vcs-Browser: https://github.com/FairRootGroup/FairLogger
Package: fairlogger1
Architecture: amd64
Multi-Arch: same
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Lightweight and fast C++ Logging Library
* Log to stdout, file, and/or custom sinks.
* Configurable verbosity and severity levels.
* Thread-safe ostream logging via convenient LOG(severity) macro.
Package: fairlogger-dev
Architecture: amd64
Multi-Arch: same
Section: libdevel
Depends: fairlogger1, libboost1.65-dev, ${shlibs:Depends}, ${misc:Depends}
Description: FairLogger development files
This package provides the development header files and the CMake package.

30
debian/copyright vendored Normal file
View File

@@ -0,0 +1,30 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: FairLogger
Source: https://github.com/FairRootGroup/FairLogger
Files: *
Copyright: 2014-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
2014-2019 Alexey Rybalchenko <alexryba@gmail.com>
2014-2019 Dennis Klein <d.klein@gsi.de>
License: LGPL-3.0+
Files: debian/*
Copyright: 2019 Dennis Klein <d.klein@gsi.de>
License: LGPL-3.0+
License: LGPL-3.0+
This package is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU Lesser General
Public License can be found in "/usr/share/common-licenses/LGPL-3".

2
debian/fairlogger-dev.install vendored Normal file
View File

@@ -0,0 +1,2 @@
usr/include/*/*
usr/lib/*/cmake/*

1
debian/fairlogger1.install vendored Normal file
View File

@@ -0,0 +1 @@
usr/lib/*/lib*.so*

View File

@@ -0,0 +1,35 @@
From: Dennis Klein <d.klein@gsi.de>
Date: Fri, 9 Aug 2019 22:16:06 +0200
Subject: CMake: Do not bake git version into installed files
---
CMakeLists.txt | 2 +-
cmake/FairLoggerLib.cmake | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 673e2ac..159cda3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,7 +62,7 @@ target_include_directories(FairLogger
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
set_target_properties(FairLogger PROPERTIES
- VERSION ${PROJECT_GIT_VERSION}
+ VERSION ${PROJECT_VERSION}
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
)
diff --git a/cmake/FairLoggerLib.cmake b/cmake/FairLoggerLib.cmake
index b038058..ca4f52f 100644
--- a/cmake/FairLoggerLib.cmake
+++ b/cmake/FairLoggerLib.cmake
@@ -215,7 +215,7 @@ endfunction()
macro(install_cmake_package)
include(CMakePackageConfigHelpers)
set(PACKAGE_INSTALL_DESTINATION
- ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_GIT_VERSION}
+ ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}-${PROJECT_VERSION}
)
install(EXPORT ${PROJECT_EXPORT_SET}
NAMESPACE ${PROJECT_NAME}::

View File

@@ -0,0 +1,26 @@
From: Dennis Klein <d.klein@gsi.de>
Date: Fri, 9 Aug 2019 22:18:31 +0200
Subject: CMake: Disable relative install RPATH
---
cmake/FairLoggerLib.cmake | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/cmake/FairLoggerLib.cmake b/cmake/FairLoggerLib.cmake
index ca4f52f..d15d163 100644
--- a/cmake/FairLoggerLib.cmake
+++ b/cmake/FairLoggerLib.cmake
@@ -131,11 +131,9 @@ macro(set_fairlogger_defaults)
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}")
+ # 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}")
+ # set(CMAKE_INSTALL_RPATH "@loader_path/../${PROJECT_INSTALL_LIBDIR}")
endif()
endif()

View File

@@ -0,0 +1,21 @@
From: Dennis Klein <d.klein@gsi.de>
Date: Fri, 9 Aug 2019 22:24:46 +0200
Subject: CMake: Workaround broken pristine tar
---
CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 159cda3..7a457cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,7 +13,7 @@ cmake_policy(VERSION 3.9...3.14)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(FairLoggerLib)
-get_git_version()
+get_git_version(DEFAULT_VERSION 1.5.0)
project(FairLogger VERSION ${PROJECT_VERSION} LANGUAGES C CXX)
message(STATUS "${BWhite}${PROJECT_NAME}${CR} ${PROJECT_GIT_VERSION} from ${PROJECT_DATE}")

3
debian/patches/series vendored Normal file
View File

@@ -0,0 +1,3 @@
0001-CMake-Do-not-bake-git-version-into-installed-files.patch
0002-CMake-Disable-relative-install-RPATH.patch
0003-CMake-Workaround-broken-pristine-tar.patch

15
debian/rules vendored Executable file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/make -f
# output every command that modifies files on the build system.
export DH_VERBOSE = 1
%:
dh $@ --builddirectory=build
override_dh_auto_configure:
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTING=OFF -DUSE_BOOST_PRETTY_FUNCTION=ON -DCMAKE_BUILD_TYPE=Release ..
override_dh_auto_build:
cd build && make
override_dh_auto_install:
cd build && make install DESTDIR=../debian/tmp

1
debian/source/format vendored Normal file
View File

@@ -0,0 +1 @@
3.0 (quilt)

BIN
example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

View File

@@ -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();
}
}

View File

@@ -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) \

View File

@@ -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

View File

@@ -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;
}