Compare commits

..

No commits in common. "master" and "v1.6.0" have entirely different histories.

27 changed files with 893 additions and 1582 deletions

View File

@ -1,85 +0,0 @@
name: CI
on:
push:
branches: [ master, dev ]
pull_request:
branches: [ master, dev ]
jobs:
build-linux:
runs-on: ubuntu-latest
strategy:
matrix:
fedora: [38, 39, 40]
include:
- fedora: 38
gcc: 13
- fedora: 39
gcc: 13
- fedora: 40
gcc: 14
container: ghcr.io/fairrootgroup/fairmq-dev/fedora-${{ matrix.fedora }}
steps:
- uses: actions/checkout@v4
- name: Install additional dependencies
run: |
dnf install -y fmt-devel || true
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DDISABLE_COLOR=ON \
-DUSE_EXTERNAL_FMT=ON \
-DUSE_BOOST_PRETTY_FUNCTION=ON
- name: Build
run: cmake --build build
- name: Test
run: |
cd build
ctest -V --output-on-failure
build-macos:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-13, macos-14, macos-15]
steps:
- uses: actions/checkout@v4
- name: Cache Homebrew packages
uses: actions/cache@v4
with:
path: |
~/Library/Caches/Homebrew
/usr/local/Homebrew/Library/Taps
key: ${{ runner.os }}-${{ matrix.os }}-brew-${{ hashFiles('.github/workflows/ci.yml') }}
restore-keys: |
${{ runner.os }}-${{ matrix.os }}-brew-
- name: Install dependencies
run: |
brew install cmake ninja boost fmt
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DDISABLE_COLOR=ON \
-DUSE_EXTERNAL_FMT=ON \
-DUSE_BOOST_PRETTY_FUNCTION=ON
- name: Build
run: cmake --build build
- name: Test
run: |
cd build
ctest -V --output-on-failure

1
.gitignore vendored
View File

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

View File

@ -1,5 +1,5 @@
################################################################################
# Copyright (C) 2018-2024 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,16 +7,15 @@
################################################################################
cmake_minimum_required(VERSION 3.9.4 FATAL_ERROR)
cmake_policy(VERSION 3.9...3.30)
cmake_policy(VERSION 3.9...3.14)
# Project ######################################################################
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(FairLoggerLib)
include(FairFindPackage2)
get_git_version()
project(FairLogger VERSION ${PROJECT_VERSION} LANGUAGES CXX)
project(FairLogger VERSION ${PROJECT_VERSION} LANGUAGES C CXX)
message(STATUS "${BWhite}${PROJECT_NAME}${CR} ${PROJECT_GIT_VERSION} from ${PROJECT_DATE}")
set_fairlogger_defaults()
@ -54,34 +53,32 @@ add_library(FairLogger
logger/Logger.cxx
logger/Logger.h
)
target_compile_features(FairLogger PUBLIC cxx_std_17)
if(USE_BOOST_PRETTY_FUNCTION)
target_link_libraries(FairLogger PUBLIC Boost::boost)
target_compile_definitions(FairLogger PUBLIC FAIRLOGGER_USE_BOOST_PRETTY_FUNCTION)
endif()
# legacy paths
list(APPEND FAIRLOGGER_INSTALL_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
if(USE_EXTERNAL_FMT)
target_link_libraries(FairLogger PUBLIC fmt::fmt)
else()
add_library(fmt INTERFACE)
target_include_directories(fmt INTERFACE
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/logger/bundled>
$<INSTALL_INTERFACE:${PROJECT_INSTALL_BUNDLEDINCDIR}>
$<INSTALL_INTERFACE:${PROJECT_INSTALL_INCDIR}/bundled>
)
target_compile_features(fmt INTERFACE cxx_std_11)
target_compile_definitions(fmt INTERFACE FMT_HEADER_ONLY)
target_link_libraries(FairLogger PUBLIC fmt)
endif()
if(DEFINED FAIR_MIN_SEVERITY)
target_compile_definitions(FairLogger PUBLIC "FAIR_MIN_SEVERITY=${FAIR_MIN_SEVERITY}")
list(APPEND FAIRLOGGER_INSTALL_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_INCDIR}/bundled)
endif()
target_include_directories(FairLogger
PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/logger>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/logger>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
set_target_properties(FairLogger PROPERTIES
VERSION ${PROJECT_GIT_VERSION}
@ -89,22 +86,8 @@ set_target_properties(FairLogger PROPERTIES
)
if(BUILD_TESTING)
add_executable(cycleTest test/cycle.cxx)
target_link_libraries(cycleTest FairLogger)
add_executable(loggerTest test/logger.cxx)
target_link_libraries(loggerTest FairLogger)
add_executable(macrosTest test/macros.cxx)
target_link_libraries(macrosTest FairLogger)
add_executable(nologTest test/nolog.cxx)
target_link_libraries(nologTest FairLogger)
add_executable(severityTest test/severity.cxx)
target_link_libraries(severityTest FairLogger)
add_executable(sinksTest test/sinks.cxx)
target_link_libraries(sinksTest FairLogger)
add_executable(threadsTest test/threads.cxx)
target_link_libraries(threadsTest FairLogger pthread)
add_executable(verbosityTest test/verbosity.cxx)
target_link_libraries(verbosityTest FairLogger)
add_executable(loggerTest test/loggerTest.cxx)
target_link_libraries(loggerTest FairLogger pthread)
endif()
################################################################################
@ -117,6 +100,7 @@ if(NOT USE_EXTERNAL_FMT)
endif()
install(TARGETS
FairLogger
${test_targets}
${fmt_target}
EXPORT ${PROJECT_EXPORT_SET}
@ -144,22 +128,7 @@ install_cmake_package()
# Testing ######################################################################
if(BUILD_TESTING)
add_test(NAME cycle COMMAND $<TARGET_FILE:cycleTest>)
add_test(NAME logger COMMAND $<TARGET_FILE:loggerTest>)
add_test(NAME macros COMMAND $<TARGET_FILE:macrosTest>)
add_test(NAME nolog COMMAND $<TARGET_FILE:nologTest>)
add_test(NAME severity COMMAND $<TARGET_FILE:severityTest>)
add_test(NAME sinks COMMAND $<TARGET_FILE:sinksTest>)
add_test(NAME threads COMMAND $<TARGET_FILE:threadsTest>)
add_test(NAME verbosity COMMAND $<TARGET_FILE:verbosityTest>)
endif()
################################################################################
# Utils ########################################################################
find_program(BASH bash HINTS "/bin")
find_program(SINGULARITY singularity)
if(BASH AND SINGULARITY)
add_subdirectory(test/ci)
add_test(NAME loggerTest COMMAND $<TARGET_FILE:loggerTest>)
endif()
################################################################################
@ -244,12 +213,6 @@ else()
endif()
message(STATUS " ${BWhite}tests${CR} ${testing_summary}")
message(STATUS " ")
if(DEFINED FAIR_MIN_SEVERITY)
message(STATUS " ${Cyan}FAIR_MIN_SEVERITY${CR} ${BGreen}${FAIR_MIN_SEVERITY}${CR} (change with ${BMagenta}-DFAIR_MIN_SEVERITY=...${CR})")
else()
message(STATUS " ${Cyan}FAIR_MIN_SEVERITY${CR} not defined${CR}, enabling all severities (change with ${BMagenta}-DFAIR_MIN_SEVERITY=...${CR})")
endif()
message(STATUS " ")
message(STATUS " ${Cyan}INSTALL PREFIX${CR} ${BGreen}${CMAKE_INSTALL_PREFIX}${CR} (change with ${BMagenta}-DCMAKE_INSTALL_PREFIX=...${CR})")
message(STATUS " ")
################################################################################

133
Dart.sh Executable file
View File

@ -0,0 +1,133 @@
#!/bin/bash
function print_example(){
echo "##################################################################"
echo "# To set the required parameters as source and the build #"
echo "# directory for ctest, the linux flavour and the SIMPATH #"
echo "# put the export commands below to a separate file which is read #"
echo "# during execution and which is defined on the command line. #"
echo "# Set all parameters according to your needs. #"
echo "# LINUX_FLAVOUR should be set to the distribution you are using #"
echo "# eg Debian, SuSe etc. #"
echo "# An additional varibale NCPU can overwrite the default number #"
echo "# of parallel processes used to compile the project. #"
echo "# This can be usefull if one can use a distributed build system #"
echo "# like icecream. #"
echo "# For example #"
echo "#!/bin/bash #"
echo "export LINUX_FLAVOUR=<your linux flavour> #"
echo "export FAIRSOFT_VERSION=<version of FairSoft> #"
echo "export SIMPATH=<path to your FairSoft version> #"
echo "export GIT_BRANCH=< master or dev> #"
echo "export BUILDDIR=<dir where the build files go> #"
echo "export SOURCEDIR=<location of the FairRoot sources> #"
echo "#export NCPU=100 #"
echo "##################################################################"
}
if [ "$#" -lt "2" ]; then
echo ""
echo "-- Error -- Please start script with two parameters"
echo "-- Error -- The first parameter is the ctest model."
echo "-- Error -- Possible arguments are Nightly, Experimental, "
echo "-- Error -- Continuous or Profile."
echo "-- Error -- The second parameter is the file containg the"
echo "-- Error -- Information about the setup at the client"
echo "-- Error -- installation (see example below)."
echo ""
print_example
exit 1
fi
# test if a valid ctest model is defined
if [ "$1" == "Experimental" -o "$1" == "Nightly" -o "$1" == "Continuous" -o "$1" == "Profile" -o "$1" == "alfa_ci" ]; then
echo ""
else
echo "-- Error -- This ctest model is not supported."
echo "-- Error -- Possible arguments are Nightly, Experimental, Continuous or Profile."
exit 1
fi
# test if the input file exists and execute it
if [ -e "$2" ];then
source $2
else
echo "-- Error -- Input file does not exist."
echo "-- Error -- Please choose existing input file."
exit 1
fi
# set the ctest model to command line parameter
if [ "$1" == "alfa_ci" ]; then
export ctest_model=Experimental
else
export ctest_model=$1
fi
# test for architecture
arch=$(uname -s | tr '[A-Z]' '[a-z]')
chip=$(uname -m | tr '[A-Z]' '[a-z]')
# extract information about the system and the machine and set
# environment variables used by ctest
SYSTEM=$arch-$chip
if test -z $CXX ; then
if [ "$arch" == "darwin" ]; then
COMPILER=$(clang --version | head -n 1 | cut -d' ' -f1,2,4 | tr -d ' ')
else
COMPILER=gcc$(gcc -dumpversion)
fi
else
COMPILER=$CXX$($CXX -dumpversion)
fi
if [ "$1" == "alfa_ci" ]; then
export LABEL1=alfa_ci-$COMPILER-FairLogger_$GIT_BRANCH
export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g')
else
export LABEL1=${LINUX_FLAVOUR}-$chip-$COMPILER-FairLogger_$GIT_BRANCH
export LABEL=$(echo $LABEL1 | sed -e 's#/#_#g')
fi
# get the number of processors
# and information about the host
if [ "$arch" = "linux" ];
then
if [ "$NCPU" != "" ];
then
export number_of_processors=$NCPU
else
export number_of_processors=$(cat /proc/cpuinfo | grep processor | wc -l)
fi
if [ -z "$SITE" ]; then
export SITE=$(hostname -f)
if [ -z "$SITE" ]; then
export SITE=$(uname -n)
fi
fi
elif [ "$arch" = "darwin" ];
then
if [ "$NCPU" != "" ];
then
export number_of_processors=$NCPU
else
export number_of_processors=$(sysctl -n hw.ncpu)
fi
if [ -z "$SITE" ]; then
export SITE=$(hostname -s)
fi
fi
echo "************************"
date
echo "LABEL: " $LABEL
echo "SITE: " $SITE
echo "Model: " ${ctest_model}
echo "Nr. of processes: " $number_of_processors
echo "************************"
cd $SOURCEDIR
ctest -S FairLoggerTest.cmake -V --VV

View File

@ -1,58 +1,69 @@
################################################################################
# Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# Copyright (C) 2014 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" #
################################################################################
Set(CTEST_SOURCE_DIRECTORY $ENV{SOURCEDIR})
Set(CTEST_BINARY_DIRECTORY $ENV{BUILDDIR})
Set(CTEST_SITE $ENV{SITE})
Set(CTEST_BUILD_NAME $ENV{LABEL})
Set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
Set(CTEST_PROJECT_NAME "FairLogger")
cmake_host_system_information(RESULT fqdn QUERY FQDN)
Find_Program(CTEST_GIT_COMMAND NAMES git)
Set(CTEST_UPDATE_COMMAND "${CTEST_GIT_COMMAND}")
set(CTEST_SOURCE_DIRECTORY .)
set(CTEST_BINARY_DIRECTORY build)
set(CTEST_CMAKE_GENERATOR "Ninja")
set(CTEST_USE_LAUNCHERS ON)
set(CTEST_CONFIGURATION_TYPE "RelWithDebInfo")
Set(BUILD_COMMAND "make")
Set(CTEST_BUILD_COMMAND "${BUILD_COMMAND} -j$ENV{number_of_processors}")
if(NOT NCPUS)
include(ProcessorCount)
ProcessorCount(NCPUS)
if(NCPUS EQUAL 0)
set(NCPUS 1)
endif()
endif()
String(TOUPPER $ENV{ctest_model} _Model)
Set(configure_options "-DCMAKE_BUILD_TYPE=${_Model}")
if ("$ENV{CTEST_SITE}" STREQUAL "")
set(CTEST_SITE "${fqdn}")
else()
set(CTEST_SITE $ENV{CTEST_SITE})
endif()
Set(CTEST_USE_LAUNCHERS 1)
Set(configure_options "${configure_options};-DCTEST_USE_LAUNCHERS=${CTEST_USE_LAUNCHERS}")
if ("$ENV{CTEST_BUILD_NAME}" STREQUAL "")
set(CTEST_BUILD_NAME "build")
else()
set(CTEST_BUILD_NAME $ENV{CTEST_BUILD_NAME})
endif()
Set(configure_options "${configure_options};-DDISABLE_COLOR=ON")
ctest_start(Continuous)
Set(EXTRA_FLAGS $ENV{EXTRA_FLAGS})
If(EXTRA_FLAGS)
Set(configure_options "${configure_options};${EXTRA_FLAGS}")
EndIf()
list(APPEND options
"-DDISABLE_COLOR=ON"
"-DUSE_EXTERNAL_FMT=ON"
"-DUSE_BOOST_PRETTY_FUNCTION=ON"
)
list(JOIN options ";" optionsstr)
ctest_configure(OPTIONS "${optionsstr}")
If($ENV{ctest_model} MATCHES Nightly OR $ENV{ctest_model} MATCHES Profile)
ctest_build(FLAGS "-j${NCPUS}")
Find_Program(GCOV_COMMAND gcov)
If(GCOV_COMMAND)
Message("Found GCOV: ${GCOV_COMMAND}")
Set(CTEST_COVERAGE_COMMAND ${GCOV_COMMAND})
EndIf(GCOV_COMMAND)
ctest_test(BUILD "${CTEST_BINARY_DIRECTORY}"
PARALLEL_LEVEL 1
SCHEDULE_RANDOM ON
RETURN_VALUE _ctest_test_ret_val)
Set(ENV{ctest_model} Nightly)
ctest_submit()
CTEST_EMPTY_BINARY_DIRECTORY(${CTEST_BINARY_DIRECTORY})
if(_ctest_test_ret_val)
EndIf()
Ctest_Start($ENV{ctest_model})
Ctest_Configure(BUILD "${CTEST_BINARY_DIRECTORY}"
OPTIONS "${configure_options}"
)
Ctest_Build(BUILD "${CTEST_BINARY_DIRECTORY}")
Ctest_Test(BUILD "${CTEST_BINARY_DIRECTORY}"
PARALLEL_LEVEL $ENV{number_of_processors}
RETURN_VALUE _ctest_test_ret_val
)
If(GCOV_COMMAND)
Ctest_Coverage(BUILD "${CTEST_BINARY_DIRECTORY}")
EndIf()
Ctest_Submit()
if (_ctest_test_ret_val)
Message(FATAL_ERROR "Some tests failed.")
endif()

79
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,79 @@
#!groovy
def specToLabel(Map spec) {
return "${spec.os}-${spec.arch}-${spec.compiler}-FairSoft_${spec.fairsoft}"
}
def jobMatrix(String prefix, 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["${prefix}/${label}"] = {
node(label) {
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 =~ /gcc9/) {
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/9.1.0" >> 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: "${prefix}/${label}", description: 'Success', status: 'SUCCESS')
} catch (e) {
deleteDir()
githubNotify(context: "${prefix}/${label}", description: 'Error', status: 'ERROR')
throw e
}
}
}
}
return nodes
}
pipeline{
agent none
stages {
stage("Run CI Matrix") {
steps{
script {
parallel(jobMatrix('alfa-ci/build', [
[os: 'Debian8', arch: 'x86_64', compiler: 'gcc9.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 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 =~ /gcc9/) {
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/9.1.0" >> 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: 'gcc9.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'
})
}
}
}
}
}

View File

@ -42,7 +42,7 @@ If FairLogger is built with `-DUSE_BOOST_PRETTY_FUNCTION=ON` and/or `-DUSE_EXTER
```cmake
find_package(FairLogger)
foreach(dep IN LISTS FairLogger_PACKAGE_DEPENDENCIES)
find_package(${dep} ${FairLogger_${dep}_VERSION})
find_package(${dep} ${FairLogger_${dep}_VERSION})
endforeach()
```
@ -66,13 +66,11 @@ All log calls go through the provided LOG(severity) macro. Output through this m
A number of additional logging macros are provided:
- `LOGV(severity, verbosity)` Log the line with the provided verbosity, e.g. `LOG(info, veryhigh) << "abcd";`
- `LOGF(severity, ...)` The arguments are given to `fmt::printf`, which formats the string using a [printf syntax](https://fmt.dev/dev/api.html#printf-formatting) and the result is logged, e.g. `LOGF(info, "Hello %s!", "world");`
- `LOGP(severity, ...)` The arguments are given to `fmt::format`, which formats the string using a [Python-like syntax](https://fmt.dev/dev/syntax.html) and the result is logged, e.g. `LOGP(info, "Hello {}!", "world");`
- `LOGPD(severity, ...)` Same as `LOGP`, but accepts dynamic severity (runtime variable), e.g. `LOGPD(dynamicSeverity, "Hello {}!", "world");`
- `LOGFD(severity, ...)` Same as `LOGF`, but accepts dynamic severity (runtime variable), e.g. `LOGFD(dynamicSeverity, "Hello %s!", "world");`
- `LOGF(severity, ...)` The arguments are given to `fmt::format` and the result is logged, e.g. `LOGF(info, "Hello {}!", "world");`
- `LOGP(severity, ...)` The arguments are given to `fmt::printf` and the result is logged, e.g. `LOGP(info, "Hello %s!", "world");`
- `LOGN(severity)` Logs an empty line, e.g. `LOGN(info);`
- `LOG_IF(severity, condition)` Logs the line if the provided condition if true
- `LOGD(severity, file, line, f)` Logs the line with the provided file, line and function parameters (accepts severity as a variable), e.g. `LOGD(dynamicSeverity, "main.cpp", "42", "main");`
- `LOGD(severity, file, line, f)` Logs the line with the provided file, line and function parameters (only if the active verbosity allows it).
## 3. Severity
@ -89,36 +87,21 @@ where severity level is one of the following:
```C++
"nolog",
"trace",
"debug4",
"debug3",
"debug2",
"debug1",
"debug",
"detail",
"info",
"state",
"warn",
"important",
"alarm",
"error",
"critical",
"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.1 Compile-time severity switch
The minimum severity level can be configured at compile time via definition of `FAIR_MIN_SEVERITY`:
```
cmake -DFAIR_MIN_SEVERITY=warn ..
```
The above would only log severities equal to or above `warn`.
When `FAIR_MIN_SEVERITY` is not provided all severities are enabled.
## 4. Verbosity
The log verbosity is controlled via:
@ -132,8 +115,8 @@ it is same for all sinks, and is one of the following values: `verylow`, `low`,
verylow: message
low: [severity] message
medium: [HH:MM:SS][severity] message
high: [process_name][HH:MM:SS][severity] message
veryhigh: [process_name][HH:MM:SS:µS][severity][file:line:function] message
high: [process name][HH:MM:SS][severity] message
veryhigh: [process name][HH:MM:SS:µS][severity][file:line:function] message
user1: [severity] message
user2: [severity] message
user3: [severity] message
@ -152,12 +135,12 @@ 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
// results in [HH:MM:SS][process name] message
```
| **Argument** | **Result** |
| --- | --- |
| `fair::VerbositySpec::Info::process_name` | `[process_name]` |
| `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]` |
@ -224,20 +207,8 @@ Here is an example adding a custom sink for all severities ("trace" and above).
If only output from custom sinks is desirable, console/file sinks must be deactivated by setting their severity to `"nolog"`.
## Naming conflicts?
By default, `<fairlogger/Logger.h>` defines unprefixed macros: `LOG`, `LOGV`, `LOGF`, `LOGP`, `LOGPD`, `LOGFD`, `LOGN`, `LOGD`, `LOG_IF`.
Define an option `FAIR_NO_LOG*` to prevent the above unprefixed macros to be defined, e.g.
```C++
#define FAIR_NO_LOG
#define FAIR_NO_LOGF
#include <fairlogger/Logger.h>
```
## License
GNU Lesser General Public Licence (LGPL) version 3, see [LICENSE](LICENSE).
Copyright (C) 2017-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
Copyright (C) 2017-2018 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH

View File

@ -1,102 +0,0 @@
################################################################################
# Copyright (C) 2018-2021 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" #
################################################################################
#
# 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()

View File

@ -1,5 +1,5 @@
################################################################################
# Copyright (C) 2018-2021 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, #
@ -15,8 +15,8 @@ set(@PROJECT_NAME@_GIT_DATE @PROJECT_GIT_DATE@)
set_and_check(@PROJECT_NAME@_PREFIX @PACKAGE_CMAKE_INSTALL_PREFIX@)
set(@PROJECT_NAME@_BINDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_BINDIR@)
set(@PROJECT_NAME@_INCDIR @PACKAGE_INSTALL_INCDIRS@)
set(@PROJECT_NAME@_INCDIRS @PACKAGE_INSTALL_INCDIRS@)
set(@PROJECT_NAME@_INCDIR @FAIRLOGGER_INSTALL_INCLUDE_DIRS@)
set(@PROJECT_NAME@_INCDIRS @FAIRLOGGER_INSTALL_INCLUDE_DIRS@)
set_and_check(@PROJECT_NAME@_LIBDIR @PACKAGE_CMAKE_INSTALL_PREFIX@/@PROJECT_INSTALL_LIBDIR@)
set(@PROJECT_NAME@_CXX_STANDARD_REQUIRED @CMAKE_CXX_STANDARD_REQUIRED@)

View File

@ -1,5 +1,5 @@
################################################################################
# Copyright (C) 2018-2021 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, #
@ -94,22 +94,24 @@ macro(set_fairlogger_defaults)
endif()
# Handle C++ standard level
set(PROJECT_MIN_CXX_STANDARD 17)
if(CMAKE_CXX_STANDARD LESS PROJECT_MIN_CXX_STANDARD)
set(PROJECT_MIN_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT CMAKE_CXX_STANDARD)
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)
if(NOT DEFINED CMAKE_EXPORT_COMPILE_COMMANDS)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
endif()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(NOT DEFINED BUILD_SHARED_LIBS)
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 DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
if(NOT CMAKE_POSITION_INDEPENDENT_CODE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
@ -120,7 +122,6 @@ macro(set_fairlogger_defaults)
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_BUNDLEDINCDIR ${PROJECT_INSTALL_INCDIR}/bundled)
set(PROJECT_INSTALL_DATADIR ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME_LOWER})
# https://cmake.org/Wiki/CMake_RPATH_handling
@ -128,13 +129,13 @@ macro(set_fairlogger_defaults)
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_LIBDIR}" isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--enable-new-dtags")
string(APPEND CMAKE_SHARED_LINKER_FLAGS " -Wl,--enable-new-dtags")
list(APPEND CMAKE_INSTALL_RPATH "$ORIGIN/../${PROJECT_INSTALL_LIBDIR}")
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")
list(APPEND CMAKE_INSTALL_RPATH "@loader_path/../${PROJECT_INSTALL_LIBDIR}")
set(CMAKE_INSTALL_RPATH "@loader_path/../${PROJECT_INSTALL_LIBDIR}")
else()
list(APPEND CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_LIBDIR}")
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_LIBDIR}")
endif()
endif()
@ -226,13 +227,6 @@ macro(install_cmake_package)
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)
unset(PACKAGE_INSTALL_INCDIRS)
list(APPEND PACKAGE_INSTALL_INCDIRS
\$\{PACKAGE_PREFIX_DIR\}/${CMAKE_INSTALL_INCLUDEDIR})
if(NOT USE_EXTERNAL_FMT)
list(APPEND PACKAGE_INSTALL_INCDIRS
\$\{PACKAGE_PREFIX_DIR\}/${PROJECT_INSTALL_BUNDLEDINCDIR})
endif()
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}})
@ -248,3 +242,98 @@ macro(install_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()

View File

@ -1,22 +1,16 @@
/********************************************************************************
* Copyright (C) 2014-2025 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 <string_view>
#if FMT_VERSION < 60000
#include <fmt/time.h>
#else
#include <fmt/chrono.h>
#endif
#include <cstdio> // printf
#include <iostream>
#include <iterator> // std::back_inserter
using namespace std;
@ -25,12 +19,31 @@ namespace fair
using VSpec = VerbositySpec;
string GetColoredSeverityString(Severity severity)
{
switch (severity) {
case Severity::nolog: return "\033[01;39mNOLOG\033[0m"; break;
case Severity::fatal: return "\033[01;31mFATAL\033[0m"; break;
case Severity::error: return "\033[01;31mERROR\033[0m"; break;
case Severity::warn: return "\033[01;33mWARN\033[0m"; break;
case Severity::state: return "\033[01;35mSTATE\033[0m"; break;
case Severity::info: return "\033[01;32mINFO\033[0m"; break;
case Severity::debug: return "\033[01;34mDEBUG\033[0m"; break;
case Severity::debug1: return "\033[01;34mDEBUG1\033[0m"; break;
case Severity::debug2: return "\033[01;34mDEBUG2\033[0m"; break;
case Severity::debug3: return "\033[01;34mDEBUG3\033[0m"; break;
case Severity::debug4: return "\033[01;34mDEBUG4\033[0m"; break;
case Severity::trace: return "\033[01;36mTRACE\033[0m"; break;
default: return "UNKNOWN"; break;
}
}
bool Logger::fColored = false;
fstream Logger::fFileStream;
Verbosity Logger::fVerbosity = Verbosity::low;
Severity Logger::fConsoleSeverity = Severity::FAIR_MIN_SEVERITY > Severity::info ? Severity::FAIR_MIN_SEVERITY : Severity::info;
Severity Logger::fMinSeverity = Severity::FAIR_MIN_SEVERITY > Severity::info ? Severity::FAIR_MIN_SEVERITY : Severity::info;
Severity Logger::fConsoleSeverity = Severity::info;
Severity Logger::fFileSeverity = Severity::nolog;
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;
@ -45,81 +58,71 @@ const string Logger::fProcessName = program_invocation_short_name;
const string Logger::fProcessName = "?";
#endif
const unordered_map<string_view, Verbosity> Logger::fVerbosityMap =
const unordered_map<string, Verbosity> Logger::fVerbosityMap =
{
{ {"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 }
{ "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_view, Severity> Logger::fSeverityMap =
const unordered_map<string, Severity> Logger::fSeverityMap =
{
{ {"nolog"}, Severity::nolog },
{ {"NOLOG"}, Severity::nolog },
{ {"fatal"}, Severity::fatal },
{ {"FATAL"}, Severity::fatal },
{ {"critical"}, Severity::critical },
{ {"error"}, Severity::error },
{ {"ERROR"}, Severity::error },
{ {"alarm"}, Severity::alarm },
{ {"important"}, Severity::important },
{ {"warn"}, Severity::warn },
{ {"WARN"}, Severity::warn },
{ {"warning"}, Severity::warn },
{ {"WARNING"}, Severity::warn },
{ {"state"}, Severity::state },
{ {"STATE"}, Severity::state },
{ {"info"}, Severity::info },
{ {"INFO"}, Severity::info },
{ {"detail"}, Severity::detail },
{ {"debug"}, Severity::debug },
{ {"DEBUG"}, Severity::debug },
{ {"debug1"}, Severity::debug1 },
{ {"DEBUG1"}, Severity::debug1 },
{ {"debug2"}, Severity::debug2 },
{ {"DEBUG2"}, Severity::debug2 },
{ {"debug3"}, Severity::debug3 },
{ {"DEBUG3"}, Severity::debug3 },
{ {"debug4"}, Severity::debug4 },
{ {"DEBUG4"}, Severity::debug4 },
{ {"trace"}, Severity::trace },
{ {"TRACE"}, Severity::trace }
{ "nolog", Severity::nolog },
{ "NOLOG", Severity::nolog },
{ "error", Severity::error },
{ "ERROR", Severity::error },
{ "warn", Severity::warn },
{ "WARN", Severity::warn },
{ "warning", Severity::warn },
{ "WARNING", Severity::warn },
{ "state", Severity::state },
{ "STATE", Severity::state },
{ "info", Severity::info },
{ "INFO", Severity::info },
{ "debug", Severity::debug },
{ "DEBUG", Severity::debug },
{ "debug1", Severity::debug1 },
{ "DEBUG1", Severity::debug1 },
{ "debug2", Severity::debug2 },
{ "DEBUG2", Severity::debug2 },
{ "debug3", Severity::debug3 },
{ "DEBUG3", Severity::debug3 },
{ "debug4", Severity::debug4 },
{ "DEBUG4", Severity::debug4 },
{ "trace", Severity::trace },
{ "TRACE", Severity::trace }
};
const array<string_view, 16> Logger::fSeverityNames =
const array<string, 12> Logger::fSeverityNames =
{
{
"NOLOG",
"TRACE",
"DEBUG4",
"DEBUG3",
"DEBUG2",
"DEBUG1",
"DEBUG",
"DETAIL",
"INFO",
"STATE",
"WARN",
"IMPORTANT",
"ALARM",
"FATAL",
"ERROR",
"CRITICAL",
"FATAL"
"WARN",
"STATE",
"INFO",
"DEBUG",
"DEBUG1",
"DEBUG2",
"DEBUG3",
"DEBUG4",
"TRACE"
}
};
const array<string_view, 9> Logger::fVerbosityNames =
const array<string, 9> Logger::fVerbosityNames =
{
{
"verylow",
@ -147,11 +150,12 @@ map<Verbosity, VSpec> Logger::fVerbosities =
{ Verbosity::user4, VSpec::Make(VSpec::Info::severity) }
};
Logger::Logger(Severity severity, Verbosity verbosity, std::string_view file, std::string_view line, std::string_view func)
Logger::Logger(Severity severity, Verbosity verbosity, const string& file, const string& line, const string& func)
: fTimeCalculated(false)
{
if (!fIsDestructed) {
size_t pos = file.rfind("/");
// fInfos.timestamp is filled conditionally
// fInfos.us is filled conditionally
fInfos.process_name = fProcessName;
@ -167,27 +171,27 @@ Logger::Logger(Severity severity, Verbosity verbosity, std::string_view file, st
for (const auto info : spec.fInfos) {
switch (info) {
case VSpec::Info::process_name:
fmt::format_to(std::back_inserter(fBWPrefix), "[{}]", fInfos.process_name);
fmt::format_to(fBWPrefix, "[{}]", fInfos.process_name);
break;
case VSpec::Info::timestamp_us:
FillTimeInfos();
fmt::format_to(std::back_inserter(fBWPrefix), "[{:%H:%M:%S}.{:06}]", fmt::localtime(fInfos.timestamp), fInfos.us.count());
fmt::format_to(fBWPrefix, "[{:%H:%M:%S}.{:06}]", fmt::localtime(fInfos.timestamp), fInfos.us.count());
break;
case VSpec::Info::timestamp_s:
FillTimeInfos();
fmt::format_to(std::back_inserter(fBWPrefix), "[{:%H:%M:%S}]", fmt::localtime(fInfos.timestamp));
fmt::format_to(fBWPrefix, "[{:%H:%M:%S}]", fmt::localtime(fInfos.timestamp));
break;
case VSpec::Info::severity:
fmt::format_to(std::back_inserter(fBWPrefix), "[{}]", fInfos.severity_name);
fmt::format_to(fBWPrefix, "[{}]", fInfos.severity_name);
break;
case VSpec::Info::file_line_function:
fmt::format_to(std::back_inserter(fBWPrefix), "[{}:{}:{}]", fInfos.file, fInfos.line, fInfos.func);
fmt::format_to(fBWPrefix, "[{}:{}:{}]", fInfos.file, fInfos.line, fInfos.func);
break;
case VSpec::Info::file_line:
fmt::format_to(std::back_inserter(fBWPrefix), "[{}:{}]", fInfos.file, fInfos.line);
fmt::format_to(fBWPrefix, "[{}:{}]", fInfos.file, fInfos.line);
break;
case VSpec::Info::file:
fmt::format_to(std::back_inserter(fBWPrefix), "[{}]", fInfos.file);
fmt::format_to(fBWPrefix, "[{}]", fInfos.file);
break;
default:
break;
@ -195,7 +199,7 @@ Logger::Logger(Severity severity, Verbosity verbosity, std::string_view file, st
}
if (spec.fSize > 0) {
fmt::format_to(std::back_inserter(fBWPrefix), " ");
fmt::format_to(fBWPrefix, " ");
}
}
@ -203,27 +207,27 @@ Logger::Logger(Severity severity, Verbosity verbosity, std::string_view file, st
for (const auto info : spec.fInfos) {
switch (info) {
case VSpec::Info::process_name:
fmt::format_to(std::back_inserter(fColorPrefix), "[{}]", ColorOut(Color::fgBlue, fInfos.process_name));
fmt::format_to(fColorPrefix, "[{}]", ColorOut(Color::fgBlue, fInfos.process_name));
break;
case VSpec::Info::timestamp_us:
FillTimeInfos();
fmt::format_to(std::back_inserter(fColorPrefix), "[{}{:%H:%M:%S}.{:06}{}]", startColor(Color::fgCyan), fmt::localtime(fInfos.timestamp), fInfos.us.count(), endColor());
fmt::format_to(fColorPrefix, "[{}{:%H:%M:%S}.{:06}{}]", startColor(Color::fgCyan), fmt::localtime(fInfos.timestamp), fInfos.us.count(), endColor());
break;
case VSpec::Info::timestamp_s:
FillTimeInfos();
fmt::format_to(std::back_inserter(fColorPrefix), "[{}{:%H:%M:%S}{}]", startColor(Color::fgCyan), fmt::localtime(fInfos.timestamp), endColor());
fmt::format_to(fColorPrefix, "[{}{:%H:%M:%S}{}]", startColor(Color::fgCyan), fmt::localtime(fInfos.timestamp), endColor());
break;
case VSpec::Info::severity:
fmt::format_to(std::back_inserter(fColorPrefix), "[{}]", GetColoredSeverityString(fInfos.severity));
fmt::format_to(fColorPrefix, "[{}]", GetColoredSeverityString(fInfos.severity));
break;
case VSpec::Info::file_line_function:
fmt::format_to(std::back_inserter(fColorPrefix), "[{}:{}:{}]", ColorOut(Color::fgBlue, fInfos.file), ColorOut(Color::fgYellow, fInfos.line), ColorOut(Color::fgBlue, fInfos.func));
fmt::format_to(fColorPrefix, "[{}:{}:{}]", ColorOut(Color::fgBlue, fInfos.file), ColorOut(Color::fgYellow, fInfos.line), ColorOut(Color::fgBlue, fInfos.func));
break;
case VSpec::Info::file_line:
fmt::format_to(std::back_inserter(fColorPrefix), "[{}:{}]", ColorOut(Color::fgBlue, fInfos.file), ColorOut(Color::fgYellow, fInfos.line));
fmt::format_to(fColorPrefix, "[{}:{}]", ColorOut(Color::fgBlue, fInfos.file), ColorOut(Color::fgYellow, fInfos.line));
break;
case VSpec::Info::file:
fmt::format_to(std::back_inserter(fColorPrefix), "[{}]", ColorOut(Color::fgBlue, fInfos.file));
fmt::format_to(fColorPrefix, "[{}]", ColorOut(Color::fgBlue, fInfos.file));
break;
default:
break;
@ -231,7 +235,7 @@ Logger::Logger(Severity severity, Verbosity verbosity, std::string_view file, st
}
if (spec.fSize > 0) {
fmt::format_to(std::back_inserter(fColorPrefix), " ");
fmt::format_to(fColorPrefix, " ");
}
}
@ -286,35 +290,8 @@ void Logger::LogEmptyLine()
// this call just to prevent any output to be added to the logger object
}
string Logger::GetColoredSeverityString(Severity severity)
{
switch (severity) {
case Severity::nolog: return "\033[01;39mNOLOG\033[0m"; break;
case Severity::fatal: return "\033[01;31mFATAL\033[0m"; break;
case Severity::critical: return "\033[01;31mCRITICAL\033[0m"; break;
case Severity::error: return "\033[01;31mERROR\033[0m"; break;
case Severity::alarm: return "\033[01;33mALARM\033[0m"; break;
case Severity::important: return "\033[01;32mIMPORTANT\033[0m"; break;
case Severity::warn: return "\033[01;33mWARN\033[0m"; break;
case Severity::state: return "\033[01;35mSTATE\033[0m"; break;
case Severity::info: return "\033[01;32mINFO\033[0m"; break;
case Severity::detail: return "\033[01;32mDETAIL\033[0m"; break;
case Severity::debug: return "\033[01;34mDEBUG\033[0m"; break;
case Severity::debug1: return "\033[01;34mDEBUG1\033[0m"; break;
case Severity::debug2: return "\033[01;34mDEBUG2\033[0m"; break;
case Severity::debug3: return "\033[01;34mDEBUG3\033[0m"; break;
case Severity::debug4: return "\033[01;34mDEBUG4\033[0m"; break;
case Severity::trace: return "\033[01;36mTRACE\033[0m"; break;
default: return "UNKNOWN"; break;
}
}
void Logger::SetConsoleSeverity(const Severity severity)
{
if (severity < Severity::FAIR_MIN_SEVERITY && severity != Severity::nolog) {
cout << "Requested severity is higher than the enabled compile-time FAIR_MIN_SEVERITY (" << Severity::FAIR_MIN_SEVERITY << "), ignoring" << endl;
return;
}
fConsoleSeverity = severity;
UpdateMinSeverity();
}
@ -336,10 +313,6 @@ Severity Logger::GetConsoleSeverity()
void Logger::SetFileSeverity(const Severity severity)
{
if (severity < Severity::FAIR_MIN_SEVERITY && severity != Severity::nolog) {
cout << "Requested severity is higher than the enabled compile-time FAIR_MIN_SEVERITY (" << Severity::FAIR_MIN_SEVERITY << "), ignoring" << endl;
return;
}
fFileSeverity = severity;
UpdateMinSeverity();
}
@ -356,17 +329,8 @@ void Logger::SetFileSeverity(const string& severityStr)
void Logger::SetCustomSeverity(const string& key, const Severity severity)
{
try {
if (severity < Severity::FAIR_MIN_SEVERITY && severity != Severity::nolog) {
cout << "Requested severity is higher than the enabled compile-time FAIR_MIN_SEVERITY (" << Severity::FAIR_MIN_SEVERITY << "), ignoring" << endl;
return;
}
fCustomSinks.at(key).first = severity;
UpdateMinSeverity();
} catch (const out_of_range& oor) {
LOG(error) << "No custom sink with id '" << key << "' found";
throw;
}
fCustomSinks.at(key).first = severity; // TODO: range checks
UpdateMinSeverity();
}
void Logger::SetCustomSeverity(const string& key, const string& severityStr)
@ -379,21 +343,11 @@ void Logger::SetCustomSeverity(const string& key, const string& severityStr)
}
}
Severity Logger::GetCustomSeverity(const std::string& key)
{
try {
return fCustomSinks.at(key).first;
} catch (const out_of_range& oor) {
LOG(error) << "No custom sink with id '" << key << "' found";
throw;
}
}
void Logger::CycleConsoleSeverityUp()
{
int current = static_cast<int>(fConsoleSeverity);
if (current == static_cast<int>(fSeverityNames.size()) - 1) {
SetConsoleSeverity(Severity::FAIR_MIN_SEVERITY);
SetConsoleSeverity(static_cast<Severity>(0));
} else {
SetConsoleSeverity(static_cast<Severity>(current + 1));
}
@ -401,7 +355,7 @@ void Logger::CycleConsoleSeverityUp()
stringstream ss;
for (int i = 0; i < static_cast<int>(fSeverityNames.size()); ++i) {
ss << (i == newCurrent ? "<" : " ") << fSeverityNames.at(i) << (i == newCurrent ? ">" : " ");
ss << (i == newCurrent ? ">" : " ") << fSeverityNames.at(i) << (i == newCurrent ? "<" : " ");
}
ss << "\n\n";
@ -411,7 +365,7 @@ void Logger::CycleConsoleSeverityUp()
void Logger::CycleConsoleSeverityDown()
{
int current = static_cast<int>(fConsoleSeverity);
if (current == static_cast<int>(Severity::FAIR_MIN_SEVERITY)) {
if (current == 0) {
SetConsoleSeverity(static_cast<Severity>(fSeverityNames.size() - 1));
} else {
SetConsoleSeverity(static_cast<Severity>(current - 1));
@ -420,7 +374,7 @@ void Logger::CycleConsoleSeverityDown()
stringstream ss;
for (int i = 0; i < static_cast<int>(fSeverityNames.size()); ++i) {
ss << (i == newCurrent ? "<" : " ") << fSeverityNames.at(i) << (i == newCurrent ? ">" : " ");
ss << (i == newCurrent ? ">" : " ") << fSeverityNames.at(i) << (i == newCurrent ? "<" : " ");
}
ss << "\n\n";
@ -439,7 +393,7 @@ void Logger::CycleVerbosityUp()
stringstream ss;
for (int i = 0; i < static_cast<int>(fVerbosityNames.size()); ++i) {
ss << (i == newCurrent ? "<" : " ") << fVerbosityNames.at(i) << (i == newCurrent ? ">" : " ");
ss << (i == newCurrent ? ">" : " ") << fVerbosityNames.at(i) << (i == newCurrent ? "<" : " ");
}
ss << "\n\n";
@ -458,7 +412,7 @@ void Logger::CycleVerbosityDown()
stringstream ss;
for (int i = 0; i < static_cast<int>(fVerbosityNames.size()); ++i) {
ss << (i == newCurrent ? "<" : " ") << fVerbosityNames.at(i) << (i == newCurrent ? ">" : " ");
ss << (i == newCurrent ? ">" : " ") << fVerbosityNames.at(i) << (i == newCurrent ? "<" : " ");
}
ss << "\n\n";
@ -467,21 +421,27 @@ void Logger::CycleVerbosityDown()
void Logger::UpdateMinSeverity()
{
if (fFileSeverity == Severity::nolog) {
fMinSeverity = fConsoleSeverity;
} else {
fMinSeverity = std::max(fConsoleSeverity, fFileSeverity);
}
fMinSeverity = (fConsoleSeverity <= fFileSeverity) ? fFileSeverity : fConsoleSeverity;
for (auto& it : fCustomSinks) {
if (fMinSeverity == Severity::nolog) {
fMinSeverity = std::max(fMinSeverity, it.second.first);
} else if (it.second.first != Severity::nolog) {
fMinSeverity = std::min(fMinSeverity, it.second.first);
if (fMinSeverity <= it.second.first) {
fMinSeverity = it.second.first;
}
}
}
bool Logger::Logging(Severity severity)
{
if (Severity::fatal == severity) {
return true;
}
if (severity <= fMinSeverity && severity > Severity::nolog) {
return true;
} else {
return false;
}
}
bool Logger::Logging(const string& severityStr)
{
if (fSeverityMap.count(severityStr)) {
@ -531,7 +491,7 @@ void Logger::SetConsoleColor(const bool colored)
fColored = colored;
}
string Logger::InitFileSink(const Severity severity, const string& filename, bool customizeName)
void Logger::InitFileSink(const Severity severity, const string& filename, bool customizeName)
{
lock_guard<mutex> lock(fMtx);
if (fFileStream.is_open()) {
@ -556,27 +516,21 @@ string Logger::InitFileSink(const Severity severity, const string& filename, boo
fFileStream.open(fullName, fstream::out | fstream::app);
if (fFileStream.is_open()) {
if (severity < Severity::FAIR_MIN_SEVERITY && severity != Severity::nolog) {
cout << "Requested file sink severity is higher than the enabled compile-time FAIR_MIN_SEVERITY (" << Severity::FAIR_MIN_SEVERITY << "), setting to " << Severity::FAIR_MIN_SEVERITY << endl;
fFileSeverity = Severity::FAIR_MIN_SEVERITY;
} else {
fFileSeverity = severity;
}
fFileSeverity = severity;
UpdateMinSeverity();
} else {
cout << "Error opening file: " << fullName;
}
return fullName;
}
string Logger::InitFileSink(const string& severityStr, const string& filename, bool customizeName)
void Logger::InitFileSink(const string& severityStr, const string& filename, bool customizeName)
{
if (fSeverityMap.count(severityStr)) {
return InitFileSink(fSeverityMap.at(severityStr), filename, customizeName);
InitFileSink(fSeverityMap.at(severityStr), filename, customizeName);
} else {
LOG(error) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'.";
return InitFileSink(Severity::info, filename);
InitFileSink(Severity::info, filename);
}
}
@ -585,29 +539,27 @@ void Logger::RemoveFileSink()
lock_guard<mutex> lock(fMtx);
if (fFileStream.is_open()) {
fFileStream.close();
fFileSeverity = Severity::nolog;
UpdateMinSeverity();
}
}
bool Logger::LoggingToConsole() const
{
return (fInfos.severity >= fConsoleSeverity &&
fConsoleSeverity > Severity::nolog) ||
return (fInfos.severity <= fConsoleSeverity &&
fInfos.severity > Severity::nolog) ||
fInfos.severity == Severity::fatal;
}
bool Logger::LoggingToFile() const
{
return (fInfos.severity >= fFileSeverity &&
fFileSeverity > Severity::nolog) ||
return (fInfos.severity <= fFileSeverity &&
fInfos.severity > Severity::nolog) ||
fInfos.severity == Severity::fatal;
}
bool Logger::LoggingCustom(const Severity severity) const
{
return (fInfos.severity >= severity &&
severity > Severity::nolog) ||
return (fInfos.severity <= severity &&
fInfos.severity > Severity::nolog) ||
fInfos.severity == Severity::fatal;
}
@ -620,16 +572,10 @@ void Logger::AddCustomSink(const string& key, Severity severity, function<void(c
{
lock_guard<mutex> lock(fMtx);
if (fCustomSinks.count(key) == 0) {
if (severity < Severity::FAIR_MIN_SEVERITY && severity != Severity::nolog) {
cout << "Requested custom sink severity is higher than the enabled compile-time FAIR_MIN_SEVERITY (" << Severity::FAIR_MIN_SEVERITY << "), setting to " << Severity::FAIR_MIN_SEVERITY << endl;
fCustomSinks.insert(make_pair(key, make_pair(Severity::FAIR_MIN_SEVERITY, func)));
} else {
fCustomSinks.insert(make_pair(key, make_pair(severity, func)));
}
fCustomSinks.insert(make_pair(key, make_pair(severity, func)));
UpdateMinSeverity();
} else {
cout << "Logger::AddCustomSink: sink '" << key << "' already exists, will not add again. Remove first with Logger::RemoveCustomSink(const string& key)" << endl;
throw runtime_error("Adding a sink with a key that already exists. Remove first.");
}
}
@ -650,7 +596,6 @@ void Logger::RemoveCustomSink(const string& key)
UpdateMinSeverity();
} else {
cout << "Logger::RemoveCustomSink: sink '" << key << "' doesn't exists, will not remove." << endl;
throw runtime_error("Trying to remove a sink with a key that does not exist.");
}
}

View File

@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (C) 2014-2025 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, *
@ -13,10 +13,6 @@
#warning "The symbol 'DEBUG' is used in FairRoot Logger. undefining..."
#endif
#ifndef FAIR_MIN_SEVERITY
#define FAIR_MIN_SEVERITY nolog
#endif
#ifdef FAIRLOGGER_USE_BOOST_PRETTY_FUNCTION
#include <boost/current_function.hpp>
#endif
@ -26,7 +22,6 @@
#include <fmt/core.h>
#include <fmt/printf.h>
#include <fmt/ostream.h>
#pragma GCC diagnostic pop
@ -40,12 +35,10 @@
#include <mutex>
#include <ostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <time.h> // time_t
#include <type_traits> // is_same
#include <type_traits>
#include <unordered_map>
#include <string_view>
#include <utility> // pair
namespace fair
@ -53,64 +46,59 @@ namespace fair
enum class Severity : int
{
nolog = 0,
trace = 1,
debug4 = 2,
debug3 = 3,
debug2 = 4,
debug1 = 5,
debug = 6,
detail = 7,
info = 8,
state = 9,
warn = 10,
important = 11,
alarm = 12,
error = 13,
critical = 14,
fatal = 15,
// aliases
nolog,
fatal,
error,
warn,
state,
info,
debug,
debug1,
debug2,
debug3,
debug4,
trace,
// backwards-compatibility:
NOLOG = nolog,
FATAL = fatal,
ERROR = error,
WARN = warn,
warning = warn,
// backwards-compatibility
NOLOG __attribute__((deprecated("Use LOG(nolog) instead (lowercase severity name)."))) = nolog,
FATAL __attribute__((deprecated("Use LOG(fatal) instead (lowercase severity name)."))) = fatal,
ERROR __attribute__((deprecated("Use LOG(error) instead (lowercase severity name)."))) = error,
WARN __attribute__((deprecated("Use LOG(warn) instead (lowercase severity name)."))) = warn,
WARNING __attribute__((deprecated("Use LOG(warning) instead (lowercase severity name)."))) = warn,
STATE __attribute__((deprecated("Use LOG(state) instead (lowercase severity name)."))) = state,
INFO __attribute__((deprecated("Use LOG(info) instead (lowercase severity name)."))) = info,
DEBUG __attribute__((deprecated("Use LOG(debug) instead (lowercase severity name)."))) = debug,
DEBUG1 __attribute__((deprecated("Use LOG(debug1) instead (lowercase severity name)."))) = debug1,
DEBUG2 __attribute__((deprecated("Use LOG(debug2) instead (lowercase severity name)."))) = debug2,
DEBUG3 __attribute__((deprecated("Use LOG(debug3) instead (lowercase severity name)."))) = debug3,
DEBUG4 __attribute__((deprecated("Use LOG(debug4) instead (lowercase severity name)."))) = debug4,
TRACE __attribute__((deprecated("Use LOG(trace) instead (lowercase severity name)."))) = trace
WARNING = warn,
STATE = state,
INFO = info,
DEBUG = debug,
DEBUG1 = debug1,
DEBUG2 = debug2,
DEBUG3 = debug3,
DEBUG4 = debug4,
TRACE = trace
};
// verbosity levels:
// verylow: message
// low: [severity] message
// medium: [HH:MM:SS][severity] message
// high: [process_name][HH:MM:SS][severity] message
// veryhigh: [process_name][HH:MM:SS:µS][severity][file:line:function] message
// high: [process name][HH:MM:SS][severity] message
// veryhigh: [process name][HH:MM:SS:µS][severity][file:line:function] message
enum class Verbosity : int
{
verylow = 0,
verylow,
low,
medium,
high,
veryhigh,
// extra slots for user-defined verbosities:
user1,
user2,
user3,
user4,
// 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
@ -118,7 +106,7 @@ struct VerbositySpec
enum class Info : int
{
__empty__ = 0, // used to initialize order array
process_name, // [process_name]
process_name, // [process name]
timestamp_s, // [HH:MM:SS]
timestamp_us, // [HH:MM:SS:µS]
severity, // [severity]
@ -177,19 +165,19 @@ struct LogMetaData
{
std::time_t timestamp;
std::chrono::microseconds us;
std::string_view process_name;
std::string_view file;
std::string_view line;
std::string_view func;
std::string_view severity_name;
std::string process_name;
std::string file;
std::string line;
std::string func;
std::string severity_name;
fair::Severity severity;
};
class Logger
{
public:
Logger(Severity severity, Verbosity verbosity, std::string_view file, std::string_view line, std::string_view func);
Logger(Severity severity, std::string_view file, std::string_view line, std::string_view func)
Logger(Severity severity, Verbosity verbosity, const std::string& file, const std::string& line, const std::string& func);
Logger(Severity severity, const std::string& file, const std::string& line, const std::string& func)
: Logger(severity, fVerbosity, file, line, func)
{}
virtual ~Logger() noexcept(false);
@ -246,8 +234,7 @@ class Logger
static std::string startColor(Color color) { return fmt::format("\033[01;{}m", static_cast<int>(color)); }
static std::string endColor() { return "\033[0m"; }
static std::string ColorOut(Color c, std::string_view s) { return fmt::format("\033[01;{}m{}\033[0m", static_cast<int>(c), s); }
static std::string GetColoredSeverityString(Severity severity);
static std::string ColorOut(Color c, const std::string& s) { return fmt::format("\033[01;{}m{}\033[0m", static_cast<int>(c), s); }
static void SetConsoleSeverity(const Severity severity);
static void SetConsoleSeverity(const std::string& severityStr);
@ -255,23 +242,16 @@ class Logger
static void SetFileSeverity(const Severity severity);
static void SetFileSeverity(const std::string& severityStr);
static Severity GetFileSeverity() { return fFileSeverity; }
static void SetCustomSeverity(const std::string& key, const Severity severity);
static void SetCustomSeverity(const std::string& key, const std::string& severityStr);
static Severity GetCustomSeverity(const std::string& key);
static void CycleConsoleSeverityUp();
static void CycleConsoleSeverityDown();
static void CycleVerbosityUp();
static void CycleVerbosityDown();
static bool Logging(const Severity severity)
{
return (severity >= fMinSeverity &&
fMinSeverity > Severity::nolog) ||
severity == Severity::fatal;
}
static bool Logging(const Severity severity);
static bool Logging(const std::string& severityStr);
static void SetVerbosity(const Verbosity verbosity);
@ -282,13 +262,13 @@ class Logger
static void SetConsoleColor(const bool colored = true);
static std::string InitFileSink(const Severity severity, const std::string& filename, bool customizeName = true);
static std::string InitFileSink(const std::string& severityStr, const std::string& filename, bool customizeName = true);
static void InitFileSink(const Severity severity, const std::string& filename, bool customizeName = true);
static void InitFileSink(const std::string& severityStr, const std::string& filename, bool customizeName = true);
static void RemoveFileSink();
static std::string_view SeverityName(Severity s) { return fSeverityNames.at(static_cast<size_t>(s)); }
static std::string_view VerbosityName(Verbosity v) { return fVerbosityNames.at(static_cast<size_t>(v)); }
static std::string SeverityName(Severity s) { return fSeverityNames.at(static_cast<size_t>(s)); }
static std::string VerbosityName(Verbosity v) { return fVerbosityNames.at(static_cast<size_t>(v)); }
static void OnFatal(std::function<void()> func);
@ -324,20 +304,15 @@ class Logger
Logger& operator<<(std::ios_base& (*manip) (std::ios_base&));
Logger& operator<<(std::ostream& (*manip) (std::ostream&));
static const std::unordered_map<std::string_view, Verbosity> fVerbosityMap;
static const std::unordered_map<std::string_view, Severity> fSeverityMap;
static const std::array<std::string_view, 16> fSeverityNames;
static const std::array<std::string_view, 9> fVerbosityNames;
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, 9> fVerbosityNames;
// protection for use after static destruction took place
static bool fIsDestructed;
static struct DestructionHelper { ~DestructionHelper() { Logger::fIsDestructed = true; }} fDestructionHelper;
static bool constexpr SuppressSeverity(Severity sev)
{
return sev < Severity::FAIR_MIN_SEVERITY;
}
private:
LogMetaData fInfos;
@ -370,9 +345,6 @@ class Logger
static std::map<Verbosity, VerbositySpec> fVerbosities;
};
inline std::ostream& operator<<(std::ostream& os, const Severity& s) { return os << Logger::SeverityName(s); }
inline std::ostream& operator<<(std::ostream& os, const Verbosity& v) { return os << Logger::VerbosityName(v); }
} // namespace fair
#define IMP_CONVERTTOSTRING(s) # s
@ -384,94 +356,32 @@ inline std::ostream& operator<<(std::ostream& os, const Verbosity& v) { return o
#define MSG_ORIGIN __FILE__, CONVERTTOSTRING(__LINE__), static_cast<const char*>(__FUNCTION__)
#endif
// allow user of this header file to prevent definition of the LOG macro, by defining FAIR_NO_LOG before including this header
#ifndef FAIR_NO_LOG
#undef LOG
#define LOG FAIR_LOG
#endif
// allow user of this header file to prevent definition of the LOGV macro, by defining FAIR_NO_LOGV before including this header
#ifndef FAIR_NO_LOGV
#undef LOGV
#define LOGV FAIR_LOGV
#endif
// allow user of this header file to prevent definition of the LOGP macro, by defining FAIR_NO_LOGP before including this header
#ifndef FAIR_NO_LOGP
#undef LOGP
#define LOGP FAIR_LOGP
#endif
// allow user of this header file to prevent definition of the LOGF macro, by defining FAIR_NO_LOGF before including this header
#ifndef FAIR_NO_LOGF
#undef LOGF
#define LOGF FAIR_LOGF
#endif
// allow user of this header file to prevent definition of the LOGN macro, by defining FAIR_NO_LOGN before including this header
#ifndef FAIR_NO_LOGN
#undef LOGN
#define LOGN FAIR_LOGN
#endif
// allow user of this header file to prevent definition of the LOGD macro, by defining FAIR_NO_LOGD before including this header
#ifndef FAIR_NO_LOGD
#undef LOGD
#define LOGD FAIR_LOGD
#endif
// allow user of this header file to prevent definition of the LOG_IF macro, by defining FAIR_NO_LOG_IF before including this header
#ifndef FAIR_NO_LOG_IF
#undef LOG_IF
#define LOG_IF FAIR_LOG_IF
#endif
// allow user of this header file to prevent definition of the LOGPD macro, by defining FAIR_NO_LOGPD before including this header
#ifndef FAIR_NO_LOGPD
#undef LOGPD
#define LOGPD FAIR_LOGPD
#endif
// allow user of this header file to prevent definition of the LOGFD macro, by defining FAIR_NO_LOGFD before including this header
#ifndef FAIR_NO_LOGFD
#undef LOGFD
#define LOGFD FAIR_LOGFD
#endif
// Log line if the provided severity is below or equals the configured one
#define FAIR_LOG(severity) \
for (bool fairLOggerunLikelyvariable3 = false; !fair::Logger::SuppressSeverity(fair::Severity::severity) && !fairLOggerunLikelyvariable3; fairLOggerunLikelyvariable3 = true) \
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(fair::Severity::severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
fair::Logger(fair::Severity::severity, MSG_ORIGIN)
#define LOG(severity) \
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(fair::Severity::severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
fair::Logger(fair::Severity::severity, MSG_ORIGIN)
// Log line with the given verbosity if the provided severity is below or equals the configured one
#define FAIR_LOGV(severity, verbosity) \
for (bool fairLOggerunLikelyvariable3 = false; !fair::Logger::SuppressSeverity(fair::Severity::severity) && !fairLOggerunLikelyvariable3; fairLOggerunLikelyvariable3 = true) \
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(fair::Severity::severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
fair::Logger(fair::Severity::severity, fair::Verbosity::verbosity, MSG_ORIGIN)
#define LOGV(severity, verbosity) \
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(fair::Severity::severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
fair::Logger(fair::Severity::severity, fair::Verbosity::verbosity, MSG_ORIGIN)
// Log with fmt- or printf-like formatting
#define FAIR_LOGP(severity, ...) FAIR_LOG(severity) << fmt::format(__VA_ARGS__)
#define FAIR_LOGF(severity, ...) FAIR_LOG(severity) << fmt::sprintf(__VA_ARGS__)
// Log with fmt- or printf-like formatting (dynamic severity)
#define FAIR_LOGPD(severity, ...) \
for (bool fairLOggerunLikelyvariable3 = false; !fair::Logger::SuppressSeverity(severity) && !fairLOggerunLikelyvariable3; fairLOggerunLikelyvariable3 = true) \
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
fair::Logger(severity, MSG_ORIGIN) << fmt::format(__VA_ARGS__)
#define FAIR_LOGFD(severity, ...) \
for (bool fairLOggerunLikelyvariable3 = false; !fair::Logger::SuppressSeverity(severity) && !fairLOggerunLikelyvariable3; fairLOggerunLikelyvariable3 = true) \
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
fair::Logger(severity, MSG_ORIGIN) << fmt::sprintf(__VA_ARGS__)
#define LOGF(severity, ...) LOG(severity) << fmt::format(__VA_ARGS__)
#define LOGP(severity, ...) LOG(severity) << fmt::sprintf(__VA_ARGS__)
// Log an empty line
#define FAIR_LOGN(severity) \
for (bool fairLOggerunLikelyvariable3 = false; !fair::Logger::SuppressSeverity(fair::Severity::severity) && !fairLOggerunLikelyvariable3; fairLOggerunLikelyvariable3 = true) \
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(fair::Severity::severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
fair::Logger(fair::Severity::severity, fair::Verbosity::verylow, MSG_ORIGIN).LogEmptyLine()
#define LOGN(severity) \
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(fair::Severity::severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
fair::Logger(fair::Severity::severity, fair::Verbosity::verylow, MSG_ORIGIN).LogEmptyLine()
// Log with custom file, line, function
#define FAIR_LOGD(severity, file, line, f) \
for (bool fairLOggerunLikelyvariable3 = false; !fair::Logger::SuppressSeverity(severity) && !fairLOggerunLikelyvariable3; fairLOggerunLikelyvariable3 = true) \
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
fair::Logger(severity, file, line, f)
#define LOGD(severity, file, line, f) \
for (bool fairLOggerunLikelyvariable = false; fair::Logger::Logging(severity) && !fairLOggerunLikelyvariable; fairLOggerunLikelyvariable = true) \
fair::Logger(severity, file, line, f)
#define FAIR_LOG_IF(severity, condition) \
for (bool fairLOggerunLikelyvariable4 = false; !fair::Logger::SuppressSeverity(fair::Severity::severity) && !fairLOggerunLikelyvariable4; fairLOggerunLikelyvariable4 = true) \
for (bool fairLOggerunLikelyvariable2 = false; condition && !fairLOggerunLikelyvariable2; fairLOggerunLikelyvariable2 = true) \
FAIR_LOG(severity)
#define LOG_IF(severity, condition) \
for (bool fairLOggerunLikelyvariable2 = false; condition && !fairLOggerunLikelyvariable2; fairLOggerunLikelyvariable2 = true) \
LOG(severity)
#endif // FAIR_LOGGER_H

View File

@ -1,100 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-2020 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" *
********************************************************************************/
#ifndef FAIR_LOGGER_TEST_COMMON_H
#define FAIR_LOGGER_TEST_COMMON_H
#include <fstream>
#include <functional>
#include <iostream>
#include <regex>
#include <stdexcept>
#include <sstream>
#include <string>
#include <stdio.h> // fflush
#include <unistd.h> // dup, dup2, close
namespace fair
{
namespace logger
{
namespace test
{
template<typename ... T>
auto ToStr(T&&... t) -> std::string
{
std::stringstream ss;
(void)std::initializer_list<int>{(ss << t, 0)...};
return ss.str();
}
template<int S>
class StreamCapturer
{
public:
explicit StreamCapturer()
: mFd(S)
, mOriginalFd(dup(S)) // create a copy of the given file descriptor
{
char name[] = "/tmp/fairlogger_test_capture.XXXXXX";
const int capturedFd = mkstemp(name); // create a unique temporary file
if (capturedFd == -1) {
std::cout << "Could not create tmp file " << name << " for test; does the test have access to the /tmp directory?" << std::endl;
throw std::runtime_error("Could not create tmp file for test; does the test have access to the /tmp directory?");
}
mTmpFile = name;
fflush(nullptr); // flushes all open output streams
dup2(capturedFd, mFd);
close(capturedFd);
}
std::string GetCapture()
{
fflush(nullptr); // flushes all open output streams
std::ifstream t(mTmpFile);
std::stringstream buffer;
buffer << t.rdbuf();
return buffer.str();
}
~StreamCapturer()
{
dup2(mOriginalFd, mFd);
close(mOriginalFd);
remove(mTmpFile.c_str());
}
private:
const int mFd;
int mOriginalFd;
std::string mTmpFile;
};
void CheckOutput(std::string const& expected, std::function<void()> f)
{
std::string output;
{
StreamCapturer<1> c;
f();
output = c.GetCapture();
}
const std::regex e(expected);
if (!std::regex_match(output, e)) {
throw std::runtime_error(std::string("MISMATCH:\n##### expected (regex):\n" + expected + "\n##### found:\n" + output));
}
}
} // namespace test
} // namespace logger
} // namespace fair
#endif // FAIR_LOGGER_TEST_COMMON_H

View File

@ -1,41 +0,0 @@
################################################################################
# Copyright (C) 2021 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" #
################################################################################
function(container)
cmake_parse_arguments(ARGS "" "OS;VERSION" "" ${ARGN})
set(container "${ARGS_OS}.${ARGS_VERSION}")
set(def "${container}.def")
set(log "${container}.log")
set(target "${container}.sif")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/linux.def.in" ${def} @ONLY)
add_custom_command(OUTPUT ${target}
COMMAND ${CMAKE_COMMAND} -E env ${BASH} -c
"${SINGULARITY} build -f -F ${target} ${def} > ${log} 2>&1"
VERBATIM
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Building fairlogger test container ${target}, logging to ${CMAKE_CURRENT_BINARY_DIR}/${log}"
DEPENDS ${PACKAGE_SETUP_SCRIPT} ${bootstrap_cmake_script}
)
list(APPEND containers ${target})
set(containers ${containers} PARENT_SCOPE)
endfunction()
container(OS fedora VERSION 32)
container(OS fedora VERSION 33)
container(OS fedora VERSION 34)
container(OS fedora VERSION 35)
container(OS fedora VERSION 36)
container(OS fedora VERSION 37)
container(OS fedora VERSION 38)
container(OS fedora VERSION 39)
add_custom_target(all-containers DEPENDS ${containers})

View File

@ -1,8 +0,0 @@
Bootstrap: docker
From: @ARGS_OS@:@ARGS_VERSION@
%files
@CMAKE_CURRENT_SOURCE_DIR@/setup-@ARGS_OS@.sh /setup.sh
%post
bash /setup.sh @ARGS_VERSION@

View File

@ -1,7 +0,0 @@
#! /bin/bash
dnf -y update
dnf -y install https://alfa-ci.gsi.de/packages/rpm/fedora-$1-x86_64/fairsoft-release-dev.rpm
dnf -y install boost-devel ninja-build 'dnf-command(builddep)' libasan liblsan libtsan libubsan clang-tools-extra
dnf -y builddep fairlogger
dnf -y clean all

View File

@ -1,35 +0,0 @@
#! /bin/bash
label="$1"
jobsh="$2"
ALFACI_SLURM_CPUS=4
if [ -z "$ALFACI_SLURM_EXTRA_OPTS" ]
then
ALFACI_SLURM_EXTRA_OPTS="--hint=compute_bound"
fi
ALFACI_SLURM_TIMEOUT=10
if [ -z "$ALFACI_SLURM_QUEUE" ]
then
ALFACI_SLURM_QUEUE=main
fi
echo "*** Slurm request options :"
echo "*** Working directory ..: $PWD"
echo "*** Queue ..............: $ALFACI_SLURM_QUEUE"
echo "*** CPUs ...............: $ALFACI_SLURM_CPUS"
echo "*** Wall Time ..........: $ALFACI_SLURM_TIMEOUT min"
echo "*** Job Name ...........: ${label}"
echo "*** Extra Options ......: ${ALFACI_SLURM_EXTRA_OPTS}"
echo "*** Submitting job at ....: $(date -R)"
(
set -x
srun -p $ALFACI_SLURM_QUEUE -c $ALFACI_SLURM_CPUS -n 1 \
-t $ALFACI_SLURM_TIMEOUT \
--job-name="${label}" \
${ALFACI_SLURM_EXTRA_OPTS} \
bash "${jobsh}"
)
retval=$?
echo "*** Exit Code ............: $retval"
exit "$retval"

View File

@ -1,81 +0,0 @@
/********************************************************************************
* Copyright (C) 2015-2025 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 "Common.h"
#include <Logger.h>
#include <iostream>
using namespace std;
using namespace fair;
using namespace fair::logger::test;
int main()
{
try {
Logger::SetConsoleColor(false);
Logger::SetVerbosity(Verbosity::user4);
cout << "initial verbosity >" << Logger::GetVerbosity() << "<" << endl << endl;
array<Verbosity, 10> verbositiesUp{{ Verbosity::verylow, Verbosity::low, Verbosity::medium, Verbosity::high, Verbosity::veryhigh, Verbosity::user1, Verbosity::user2, Verbosity::user3, Verbosity::user4, Verbosity::verylow }};
for (unsigned int i = 0; i < verbositiesUp.size(); ++i) {
Logger::CycleVerbosityUp();
if (Logger::GetVerbosity() != verbositiesUp.at(i)) { throw runtime_error(ToStr("Expected verbosity to be ", verbositiesUp.at(i), ", but it is ", Logger::GetVerbosity())); }
}
array<Verbosity, 10> verbositiesDown{{ Verbosity::user4, Verbosity::user3, Verbosity::user2, Verbosity::user1, Verbosity::veryhigh, Verbosity::high, Verbosity::medium, Verbosity::low, Verbosity::verylow, Verbosity::user4 }};
for (unsigned int i = 0; i < verbositiesDown.size(); ++i) {
Logger::CycleVerbosityDown();
if (Logger::GetVerbosity() != verbositiesDown.at(i)) { throw runtime_error(ToStr("Expected verbosity to be ", verbositiesDown.at(i), ", but it is ", Logger::GetVerbosity())); }
}
Logger::SetConsoleSeverity(Severity::fatal);
cout << "initial severity >" << Logger::GetConsoleSeverity() << "<" << endl << endl;
array<Severity, 16> severitiesUp{{ Severity::nolog, Severity::trace, Severity::debug4, Severity::debug3, Severity::debug2, Severity::debug1, Severity::debug, Severity::detail, Severity::info, Severity::state, Severity::warn, Severity::important, Severity::alarm, Severity::error, Severity::critical, Severity::fatal }};
#ifdef FAIR_MIN_SEVERITY
for (unsigned int i = static_cast<int>(Severity::FAIR_MIN_SEVERITY); i < severitiesUp.size(); ++i) {
#else
for (unsigned int i = 0; i < severitiesUp.size(); ++i) {
#endif
Logger::CycleConsoleSeverityUp();
if (Logger::GetConsoleSeverity() != severitiesUp.at(i)) { throw runtime_error(ToStr("Expected severity to be ", severitiesUp.at(i), ", but it is ", Logger::GetConsoleSeverity())); }
}
Logger::CycleConsoleSeverityUp();
#ifdef FAIR_MIN_SEVERITY
if (Logger::GetConsoleSeverity() != Severity::FAIR_MIN_SEVERITY) { throw runtime_error(ToStr("Expected severity to be ", Severity::nolog, ", but it is ", Logger::GetConsoleSeverity())); }
#else
if (Logger::GetConsoleSeverity() != Severity::nolog) { throw runtime_error(ToStr("Expected severity to be ", Severity::nolog, ", but it is ", Logger::GetConsoleSeverity())); }
#endif
Logger::SetConsoleSeverity(Severity::fatal);
cout << "initial severity >" << Logger::GetConsoleSeverity() << "<" << endl << endl;
array<Severity, 16> severitiesDown{{ Severity::critical, Severity::error, Severity::alarm, Severity::important, Severity::warn, Severity::state, Severity::info, Severity::detail, Severity::debug, Severity::debug1, Severity::debug2, Severity::debug3, Severity::debug4, Severity::trace, Severity::nolog, Severity::fatal }};
#ifdef FAIR_MIN_SEVERITY
for (unsigned int i = 0; i < severitiesDown.size() - static_cast<int>(Severity::FAIR_MIN_SEVERITY) - 1; ++i) {
#else
for (unsigned int i = 0; i < severitiesDown.size(); ++i) {
#endif
Logger::CycleConsoleSeverityDown();
if (Logger::GetConsoleSeverity() != severitiesDown.at(i)) { throw runtime_error(ToStr("Expected severity to be ", severitiesDown.at(i), ", but it is ", Logger::GetConsoleSeverity())); }
}
Logger::CycleConsoleSeverityDown();
#ifdef FAIR_MIN_SEVERITY
if (Logger::GetConsoleSeverity() != Severity::fatal) { throw runtime_error(ToStr("Expected severity to be ", Severity::fatal, ", but it is ", Logger::GetConsoleSeverity())); }
#else
if (Logger::GetConsoleSeverity() != Severity::error) { throw runtime_error(ToStr("Expected severity to be ", Severity::error, ", but it is ", Logger::GetConsoleSeverity())); }
#endif
} catch (runtime_error& rte) {
cout << rte.what() << endl;
return 1;
}
return 0;
}

View File

@ -1,62 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-2020 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 <iostream>
using namespace std;
using namespace fair;
void printEverySeverity()
{
static int i = 1;
LOG(nolog) << "nolog message, counter: " << i++;
LOG(trace) << "trace message, counter: " << i++;
LOG(debug4) << "debug4 message, counter: " << i++;
LOG(debug3) << "debug3 message, counter: " << i++;
LOG(debug2) << "debug2 message, counter: " << i++;
LOG(debug1) << "debug1 message, counter: " << i++;
LOG(debug) << "debug message, counter: " << i++;
LOG(detail) << "detail message, counter: " << i++;
LOG(info) << "info message, counter: " << i++;
LOG(state) << "state message, counter: " << i++;
LOG(warn) << "warning message, counter: " << i++;
LOG(important) << "important message, counter: " << i++;
LOG(alarm) << "alarm message, counter: " << i++;
LOG(error) << "error message, counter: " << i++;
LOG(critical) << "critical message, counter: " << i++;
LOG(fatal) << "fatal message, counter: " << i++;
}
void printAllVerbositiesWithSeverity(Severity sev)
{
Logger::SetConsoleSeverity(sev);
for (uint32_t i = 0; i < Logger::fVerbosityNames.size(); ++i) {
cout << "##### testing severity '" << sev << "' with verbosity '" << Logger::fVerbosityNames.at(i) << "'" << endl;
Logger::SetVerbosity(static_cast<Verbosity>(i));
printEverySeverity();
}
}
int main()
{
Logger::SetConsoleColor(true);
Logger::SetVerbosity(Verbosity::veryhigh);
cout << "##### GetConsoleSeverity = " << Logger::SeverityName(Logger::GetConsoleSeverity()) << endl;
cout << "##### testing severities..." << endl;
for (uint32_t i = 0; i < Logger::fSeverityNames.size(); ++i) {
printAllVerbositiesWithSeverity(static_cast<Severity>(i));
}
return 0;
}

208
test/loggerTest.cxx Normal file
View File

@ -0,0 +1,208 @@
/********************************************************************************
* 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 <iostream>
#include <vector>
#include <thread>
using namespace std;
using namespace fair;
void printEverySeverity()
{
static int i = 1;
LOG(nolog) << "nolog message " << i++;
LOG(error) << "error message " << i++;
LOG(warn) << "warning message " << i++;
LOG(state) << "state message " << i++;
LOG(info) << "info message " << i++;
LOG(debug) << "debug message " << i++;
LOG(debug1) << "debug1 message " << i++;
LOG(debug2) << "debug2 message " << i++;
LOG(debug3) << "debug3 message " << i++;
LOG(debug4) << "debug4 message " << i++;
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);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'low' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::low);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'medium' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::medium);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'high' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::high);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'veryhigh' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::veryhigh);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user1' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::user1);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user2' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::user2);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user3' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::user3);
printEverySeverity();
cout << endl << "cout: >>> testing severity '" << Logger::SeverityName(sev) << "' with 'user4' verbosity..." << endl;
Logger::SetVerbosity(Verbosity::user4);
printEverySeverity();
}
void silentlyPrintAllVerbositiesWithSeverity(Severity sev)
{
Logger::SetConsoleSeverity(sev);
Logger::SetVerbosity(Verbosity::verylow);
printEverySeverity();
Logger::SetVerbosity(Verbosity::low);
printEverySeverity();
Logger::SetVerbosity(Verbosity::medium);
printEverySeverity();
Logger::SetVerbosity(Verbosity::high);
printEverySeverity();
Logger::SetVerbosity(Verbosity::veryhigh);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user1);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user2);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user3);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user4);
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);
printAllVerbositiesWithSeverity(Severity::debug4);
printAllVerbositiesWithSeverity(Severity::debug3);
printAllVerbositiesWithSeverity(Severity::debug2);
printAllVerbositiesWithSeverity(Severity::debug1);
printAllVerbositiesWithSeverity(Severity::debug);
printAllVerbositiesWithSeverity(Severity::info);
printAllVerbositiesWithSeverity(Severity::state);
printAllVerbositiesWithSeverity(Severity::warn);
printAllVerbositiesWithSeverity(Severity::error);
printAllVerbositiesWithSeverity(Severity::nolog);
cout << endl;
cout << "cout: setting severity to 'info' and verbosity to 'medium'" << endl;
Logger::SetConsoleSeverity(Severity::info);
Logger::SetVerbosity(Verbosity::medium);
cout << "cout: is logging trace: " << fair::Logger::Logging(Severity::trace) << endl;
cout << "cout: is logging debug4: " << fair::Logger::Logging(Severity::debug) << endl;
cout << "cout: is logging debug3: " << fair::Logger::Logging(Severity::debug) << endl;
cout << "cout: is logging debug2: " << fair::Logger::Logging(Severity::debug) << endl;
cout << "cout: is logging debug1: " << fair::Logger::Logging(Severity::debug) << endl;
cout << "cout: is logging debug: " << fair::Logger::Logging(Severity::debug) << endl;
cout << "cout: is logging info: " << fair::Logger::Logging(Severity::info) << endl;
cout << "cout: is logging state: " << fair::Logger::Logging(Severity::state) << endl;
cout << "cout: is logging warn: " << fair::Logger::Logging(Severity::warn) << endl;
cout << "cout: is logging error: " << fair::Logger::Logging(Severity::error) << endl;
cout << "cout: is logging fatal: " << fair::Logger::Logging(Severity::fatal) << endl;
cout << "cout: is logging nolog: " << fair::Logger::Logging(Severity::nolog) << endl;
for (int i = 0; i < 1000000; ++i) {
silentlyPrintAllVerbositiesWithSeverity(Severity::nolog);
}
cout << endl;
cout << "cout: setting severity to 'trace' and verbosity to 'veryhigh'" << endl;
Logger::SetConsoleSeverity(Severity::trace);
Logger::SetVerbosity(Verbosity::veryhigh);
cout << endl;
cout << "cout: testing conditional logging..." << endl;
int x = 0;
LOG(info) << "x = " << x << " (initial)";
LOG_IF(info, (x == 0)) << "incrementing x to " << ++x;
LOG(info) << "x = " << x << " (after increment)";
LOG_IF(info, (x == 0)) << "this should not be printed and x not incremented: " << ++x;
LOG(info) << "x = " << x << " (after conditional increment)";
cout << endl;
cout << "cout: setting severity to 'nolog'" << endl;
Logger::SetConsoleSeverity(Severity::nolog);
cout << "cout: ----------------------------" << endl;
cout << "cout: open log file with severity 'error'" << endl;
Logger::InitFileSink(Severity::error, "test_log", true);
printEverySeverity();
cout << "cout: closing log file" << endl;
Logger::RemoveFileSink();
cout << "cout: setting severity to 'nolog'" << endl;
Logger::SetConsoleSeverity(Severity::nolog);
cout << "cout: ----------------------------" << endl;
cout << "cout: adding custom sink with error severity" << endl << endl;
Logger::AddCustomSink("CustomSink", "error", [](const string& content, const LogMetaData& metadata)
{
cout << "CustomSink: content: " << content << endl;
cout << "CustomSink: available metadata: " << endl;
cout << "CustomSink: \tstd::time_t timestamp: " << metadata.timestamp << endl;
cout << "CustomSink: \tstd::chrono::microseconds us: " << metadata.us.count() << endl;
cout << "CustomSink: \tstd::string process_name: " << metadata.process_name << endl;
cout << "CustomSink: \tstd::string file: " << metadata.file << endl;
cout << "CustomSink: \tstd::string line: " << metadata.line << endl;
cout << "CustomSink: \tstd::string func: " << metadata.func << endl;
cout << "CustomSink: \tstd::string severity_name: " << metadata.severity_name << endl;
cout << "CustomSink: \tfair::Severity severity: " << static_cast<int>(metadata.severity) << endl;
});
printEverySeverity();
cout << endl << "cout: removing custom sink with info severity" << endl;
Logger::AddCustomSink("CustomSink", Severity::error, [](const string& /*content*/, const LogMetaData& /*metadata*/){});
Logger::RemoveCustomSink("CustomSink");
Logger::RemoveCustomSink("bla");
cout << "cout: setting severity to 'trace'" << endl;
Logger::SetConsoleSeverity(Severity::trace);
LOGF(info, "Hello {} {}!", "world", ":-)");
LOGP(info, "Hello %s %s!", "world", ":-)");
cout << "cout: setting verbosity to 'high'" << endl;
Logger::SetVerbosity(Verbosity::high);
LOGV(info, verylow) << "I should be printed with very low verbosity";
cout << "cout: pushing 4 new lines with LOGN() in info verbosity" << endl;
LOGN(info);
LOGN(info);
LOGN(info);
LOGN(info);
return 0;
}

View File

@ -1,67 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-2020 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 "Common.h"
#include <Logger.h>
#include <iostream>
using namespace std;
using namespace fair;
using namespace fair::logger::test;
int main()
{
try {
Logger::SetConsoleColor(false);
Logger::SetConsoleSeverity(Severity::fatal);
Logger::SetVerbosity(Verbosity::verylow);
int x = 0;
CheckOutput("^incrementing x to 1\n$", [&]() { LOG_IF(fatal, true) << "incrementing x to " << ++x; });
if (x != 1) {
throw runtime_error(ToStr("expected x to be 1, but it is: ", x));
}
CheckOutput("^$", [&]() { LOG_IF(fatal, false) << "incrementing x to " << ++x; });
if (x != 1) {
throw runtime_error(ToStr("expected x to be 1, but it is: ", x));
}
CheckOutput("^Hello world :-\\)!\n$", []() { LOGP(fatal, "Hello {} {}!", "world", ":-)"); });
CheckOutput("^Hello world :-\\)!\n$", []() { LOGF(fatal, "Hello %s %s!", "world", ":-)"); });
CheckOutput(ToStr(R"(^\[FATAL\])", " content\n$"), []() { LOGV(fatal, low) << "content"; });
CheckOutput("^\n\n\n\n$", []() {
LOGN(fatal);
LOGN(fatal);
LOGN(fatal);
LOGN(fatal);
});
Logger::SetVerbosity(Verbosity::veryhigh);
CheckOutput(ToStr(R"(^\[.*\]\[\d{2}:\d{2}:\d{2}\.\d{6}\]\[FATAL\]\[a:4:b\])", " c\n$"), []() {
LOGD(Severity::fatal, "a", "4", "b") << "c";
});
// Test dynamic severity macros
Logger::SetVerbosity(Verbosity::verylow);
Severity dynamicSeverity = Severity::fatal;
CheckOutput("^Hello dynamic world :-\\)!\n$", [&]() { LOGPD(dynamicSeverity, "Hello {} {}!", "dynamic world", ":-)"); });
CheckOutput("^Hello dynamic world :-\\)!\n$", [&]() { LOGFD(dynamicSeverity, "Hello %s %s!", "dynamic world", ":-)"); });
} catch (runtime_error& rte) {
cout << rte.what() << endl;
return 1;
}
return 0;
}

View File

@ -1,64 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-2020 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>
using namespace std;
using namespace fair;
void printEverySeverity()
{
LOG(nolog) << "nolog message ";
LOG(trace) << "trace message ";
LOG(debug4) << "debug4 message ";
LOG(debug3) << "debug3 message ";
LOG(debug2) << "debug2 message ";
LOG(debug1) << "debug1 message ";
LOG(debug) << "debug message ";
LOG(detail) << "detail message ";
LOG(info) << "info message ";
LOG(state) << "state message ";
LOG(warn) << "warning message ";
LOG(important) << "important message ";
LOG(alarm) << "alarm message ";
LOG(error) << "error message ";
LOG(critical) << "critical message ";
}
void silentlyPrintAllVerbositiesWithSeverity(Severity sev)
{
Logger::SetConsoleSeverity(sev);
Logger::SetVerbosity(Verbosity::verylow);
printEverySeverity();
Logger::SetVerbosity(Verbosity::low);
printEverySeverity();
Logger::SetVerbosity(Verbosity::medium);
printEverySeverity();
Logger::SetVerbosity(Verbosity::high);
printEverySeverity();
Logger::SetVerbosity(Verbosity::veryhigh);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user1);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user2);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user3);
printEverySeverity();
Logger::SetVerbosity(Verbosity::user4);
printEverySeverity();
}
int main()
{
for (int i = 0; i < 1000000; ++i) {
silentlyPrintAllVerbositiesWithSeverity(Severity::nolog);
}
return 0;
}

View File

@ -1,102 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-2020 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 "Common.h"
#include <Logger.h>
#include <cstdint>
#include <iostream>
#include <stdexcept>
#include <string>
using namespace std;
using namespace fair;
using namespace fair::logger::test;
uint32_t printEverySeverity(uint32_t i)
{
LOG(nolog) << "nolog message, counter: " << i++;
LOG(trace) << "trace message, counter: " << i++;
LOG(debug4) << "debug4 message, counter: " << i++;
LOG(debug3) << "debug3 message, counter: " << i++;
LOG(debug2) << "debug2 message, counter: " << i++;
LOG(debug1) << "debug1 message, counter: " << i++;
LOG(debug) << "debug message, counter: " << i++;
LOG(detail) << "detail message, counter: " << i++;
LOG(info) << "info message, counter: " << i++;
LOG(state) << "state message, counter: " << i++;
LOG(warn) << "warning message, counter: " << i++;
LOG(important) << "important message, counter: " << i++;
LOG(alarm) << "alarm message, counter: " << i++;
LOG(error) << "error message, counter: " << i++;
LOG(critical) << "critical message, counter: " << i++;
LOG(fatal) << "fatal message, counter: " << i++;
return i;
}
void CheckSeverity(Severity severity)
{
Logger::SetConsoleSeverity(severity);
auto sev = Logger::GetConsoleSeverity();
cout << "##### testing severity '" << Logger::SeverityName(sev) << "' (" << static_cast<int>(sev) << "), Logging(): " << std::boolalpha << Logger::Logging(sev) << endl;
for (uint32_t i = 0; i < Logger::fSeverityNames.size(); ++i) {
if (sev == Severity::nolog) {
if (i == static_cast<int>(fair::Severity::fatal)) {
if (!Logger::Logging(static_cast<Severity>(i))) {
throw runtime_error(ToStr("expecting to be logging ", Logger::fSeverityNames.at(i), " during ", sev, ", but it is not."));
}
} else {
if (Logger::Logging(static_cast<Severity>(i))) {
throw runtime_error(ToStr("expecting to NOT be logging ", Logger::fSeverityNames.at(i), " during ", sev, ", but it is."));
}
}
} else {
if (i >= static_cast<unsigned int>(sev)) {
if (!Logger::Logging(static_cast<Severity>(i))) {
throw runtime_error(ToStr("expecting to be logging ", Logger::fSeverityNames.at(i), " during ", sev, ", but it is not."));
}
} else {
if (Logger::Logging(static_cast<Severity>(i))) {
throw runtime_error(ToStr("expecting to NOT be logging ", Logger::fSeverityNames.at(i), " during ", sev, ", but it is."));
}
}
}
}
uint32_t i = 0;
i = printEverySeverity(i);
if (sev == Severity::nolog) {
if (i != 1) {
throw runtime_error(ToStr("expected: i==1, found: i==", i));
}
} else {
if (i != Logger::fSeverityNames.size() - static_cast<int>(sev)) {
throw runtime_error(ToStr("expected: i==", Logger::fSeverityNames.size() - static_cast<int>(sev) - 1, ", found: i==", i));
}
}
}
int main()
{
try {
Logger::SetConsoleColor(true);
cout << "##### testing " << Logger::fSeverityNames.size() << " severities..." << endl;
for (uint32_t i = 0; i < Logger::fSeverityNames.size(); ++i) {
CheckSeverity(static_cast<Severity>(i));
}
} catch (runtime_error& rte) {
cout << rte.what() << endl;
return 1;
}
return 0;
}

View File

@ -1,151 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-2020 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 "Common.h"
#include <Logger.h>
#include <fstream>
#include <iostream>
#include <random>
#include <sstream>
using namespace std;
using namespace fair;
using namespace fair::logger::test;
int main()
{
#ifdef FAIR_MIN_SEVERITY
if (static_cast<int>(Severity::FAIR_MIN_SEVERITY) > static_cast<int>(Severity::warn)) {
cout << "test requires at least FAIR_MIN_SEVERITY == warn to run, skipping" << endl;
return 0;
}
#endif
try {
Logger::SetConsoleColor(false);
Logger::SetConsoleSeverity(Severity::nolog);
Logger::SetVerbosity(Verbosity::low);
if (Logger::Logging(Severity::warn)) { cout << "Logger expected to NOT log warn, but it reports to do so" << endl; return 1; }
if (Logger::Logging(Severity::error)) { cout << "Logger expected to NOT log error, but it reports to do so" << endl; return 1; }
if (!Logger::Logging(Severity::fatal)) { cout << "Logger expected to log fatal, but it reports not to" << endl; return 1; }
cout << "##### adding file sink with warn severity" << endl;
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> distrib(1, 65536);
string name = Logger::InitFileSink(Severity::warn, string("test_log_" + to_string(distrib(gen))), true);
if (Logger::GetFileSeverity() != Severity::warn) {
throw runtime_error(ToStr("File sink severity (", Logger::GetFileSeverity(), ") does not match the expected one (", Severity::warn, ")"));
}
CheckOutput("^\\[FATAL\\] fatal\n$", [](){
LOG(state) << "state";
LOG(warn) << "warning";
LOG(error) << "error";
LOG(fatal) << "fatal";
});
if (Logger::Logging(Severity::state)) { cout << "Logger expected to NOT log warn, but it reports to do so" << endl; return 1; }
if (!Logger::Logging(Severity::warn)) { cout << "Logger expected to log warn, but it reports not to" << endl; return 1; }
if (!Logger::Logging(Severity::error)) { cout << "Logger expected to log error, but it reports not to" << endl; return 1; }
if (!Logger::Logging(Severity::fatal)) { cout << "Logger expected to log fatal, but it reports not to" << endl; return 1; }
ifstream t(name);
stringstream buffer;
buffer << t.rdbuf();
string fileContent = buffer.str();
if (fileContent != "[WARN] warning\n[ERROR] error\n[FATAL] fatal\n") {
throw runtime_error(ToStr("unexpected file sink output. expected:\n[WARN] warning\n[ERROR] error\n[FATAL] fatal\nfound:\n", fileContent));
}
cout << "##### removing file sink with warn severity" << endl;
Logger::RemoveFileSink();
if (Logger::Logging(Severity::warn)) { cout << "Logger expected to NOT log warn, but it reports to do so" << endl; return 1; }
if (Logger::Logging(Severity::error)) { cout << "Logger expected to NOT log error, but it reports to do so" << endl; return 1; }
if (!Logger::Logging(Severity::fatal)) { cout << "Logger expected to log fatal, but it reports not to" << endl; return 1; }
cout << "##### adding custom sink with warn severity" << endl;
Logger::AddCustomSink("CustomSink", "warn", [](const string& content, const LogMetaData& metadata)
{
cout << "CustomSink " << content << endl;
if (metadata.severity != Severity::warn && metadata.severity != Severity::error && metadata.severity != Severity::fatal) {
throw runtime_error(ToStr("unexpected severity message arrived at custom sink that accepts only warn,error,fatal: ", metadata.severity));
}
if (metadata.severity_name != "WARN" && metadata.severity_name != "ERROR" && metadata.severity_name != "FATAL") {
throw runtime_error(ToStr("unexpected severity name arrived at custom sink that accepts only warn,error,fatal: ", metadata.severity_name));
}
});
if (Logger::GetCustomSeverity("CustomSink") != Severity::warn) {
throw runtime_error(ToStr("File sink severity (", Logger::GetCustomSeverity("CustomSink"), ") does not match the expected one (", Severity::warn, ")"));
}
bool oorThrown = false;
try {
Logger::GetCustomSeverity("NonExistentSink");
} catch (const out_of_range& oor) {
oorThrown = true;
}
if (!oorThrown) {
throw runtime_error("Did not detect a severity request from a non-existent sink");
}
CheckOutput("^CustomSink warning\nCustomSink error\nCustomSink fatal\n\\[FATAL\\] fatal\n$", [](){
LOG(state) << "state";
LOG(warn) << "warning";
LOG(error) << "error";
LOG(fatal) << "fatal";
});
if (Logger::Logging(Severity::state)) { cout << "Logger expected to NOT log warn, but it reports to do so" << endl; return 1; }
if (!Logger::Logging(Severity::warn)) { cout << "Logger expected to log warn, but it reports not to" << endl; return 1; }
if (!Logger::Logging(Severity::error)) { cout << "Logger expected to log error, but it reports not to" << endl; return 1; }
if (!Logger::Logging(Severity::fatal)) { cout << "Logger expected to log fatal, but it reports not to" << endl; return 1; }
cout << "##### removing custom sink with error severity" << endl;
bool caught = false;
try {
Logger::AddCustomSink("CustomSink", Severity::error, [](const string& /*content*/, const LogMetaData& /*metadata*/){});
} catch (runtime_error& rte) {
caught = true;
}
if (!caught) {
throw runtime_error("expected to throw a runtime_error upon adding sink with same key, but none was thrown");
}
Logger::RemoveCustomSink("CustomSink");
if (Logger::Logging(Severity::warn)) { cout << "Logger expected to NOT log warn, but it reports to do so" << endl; return 1; }
if (Logger::Logging(Severity::error)) { cout << "Logger expected to NOT log error, but it reports to do so" << endl; return 1; }
if (!Logger::Logging(Severity::fatal)) { cout << "Logger expected to log fatal, but it reports not to" << endl; return 1; }
caught = false;
try {
Logger::RemoveCustomSink("bla");
} catch (runtime_error& rte) {
caught = true;
}
if (!caught) {
throw runtime_error("expected to throw a runtime_error upon removing non-existent sink, but none was thrown");
}
} catch (runtime_error& rte) {
cout << rte.what() << endl;
return 1;
}
return 0;
}

View File

@ -1,67 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-2020 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 "Common.h"
#include <Logger.h>
#include <iostream>
#include <thread>
#include <vector>
using namespace std;
using namespace fair;
using namespace fair::logger::test;
void f()
{
LOG(fatal) << "a" << "b" << "c" << "d" << "e" << "f" << "g" << "h" << "i" << "j" << "k" << "l" << "m" << "n" << "o" << "p" << "q" << "r" << "s" << "t" << "u" << "v" << "w" << "x" << "y" << "z";
}
int main()
{
try {
Logger::SetConsoleColor(false);
Logger::SetConsoleSeverity(Severity::fatal);
Logger::SetVerbosity(Verbosity::veryhigh);
CheckOutput(
R"(^\[.*\]\[\d{2}:\d{2}:\d{2}\.\d{6}\]\[FATAL\]\[.*:\d+:.*\] abcdefghijklmnopqrstuvwxyz
\[.*\]\[\d{2}:\d{2}:\d{2}\.\d{6}\]\[FATAL\]\[.*:\d+:.*\] abcdefghijklmnopqrstuvwxyz
\[.*\]\[\d{2}:\d{2}:\d{2}\.\d{6}\]\[FATAL\]\[.*:\d+:.*\] abcdefghijklmnopqrstuvwxyz
\[.*\]\[\d{2}:\d{2}:\d{2}\.\d{6}\]\[FATAL\]\[.*:\d+:.*\] abcdefghijklmnopqrstuvwxyz
\[.*\]\[\d{2}:\d{2}:\d{2}\.\d{6}\]\[FATAL\]\[.*:\d+:.*\] abcdefghijklmnopqrstuvwxyz
$)", []() {
thread t1(f);
thread t2(f);
thread t3(f);
thread t4(f);
thread t5(f);
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
});
thread t1(f);
thread t2(f);
thread t3(f);
thread t4(f);
thread t5(f);
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
} catch (runtime_error& rte) {
cout << rte.what() << endl;
return 1;
}
return 0;
}

View File

@ -1,102 +0,0 @@
/********************************************************************************
* Copyright (C) 2014-2020 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 "Common.h"
#include <Logger.h>
#include <iostream>
#include <string>
using namespace std;
using namespace fair;
using namespace fair::logger::test;
int main()
{
try {
Logger::SetConsoleColor(false);
Logger::SetConsoleSeverity(Severity::fatal);
auto spec1 = VerbositySpec::Make(VerbositySpec::Info::file_line_function, VerbositySpec::Info::process_name);
auto spec2 = VerbositySpec::Make(VerbositySpec::Info::process_name, VerbositySpec::Info::file_line_function);
Logger::DefineVerbosity(Verbosity::user1, spec1);
Logger::SetVerbosity(Verbosity::user1); // spec1 on user1
CheckOutput(ToStr(R"(^\[.*:\d{2}:.*\]\[.*\])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::DefineVerbosity(Verbosity::user1, spec2);
Logger::SetVerbosity(Verbosity::user1); // spec2 on user1
CheckOutput(ToStr(R"(^\[.*\]\[.*:\d{2}:.*\])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::DefineVerbosity(Verbosity::user2, spec1);
Logger::SetVerbosity(Verbosity::user2); // spec1 on user2
CheckOutput(ToStr(R"(^\[.*:\d{2}:.*\]\[.*\])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::verylow); // content
CheckOutput("^content\n$", []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::low); // [severity] content
CheckOutput(ToStr(R"(^\[FATAL\])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::medium); // [HH:MM:SS][severity] content
CheckOutput(ToStr(R"(^\[\d{2}:\d{2}:\d{2}\]\[FATAL\])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::high); // [process_name][HH:MM:SS][severity] content
CheckOutput(ToStr(R"(^\[.*\]\[\d{2}:\d{2}:\d{2}\]\[FATAL\])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::veryhigh); // [process_name][HH:MM:SS:µS][severity][file:line:function] content
CheckOutput(ToStr(R"(^\[.*\]\[\d{2}:\d{2}:\d{2}\.\d{6}\]\[FATAL\]\[.*:\d+:.*\])", " content\n$"), []() { LOG(fatal) << "content"; });
Logger::SetConsoleColor(true);
Logger::SetVerbosity(Verbosity::verylow); // content
CheckOutput(
"^"
"content\n"
"$", []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::low); // [severity] content
CheckOutput(
"^"
"\\[\033\\[01;31mFATAL\033\\[0m\\]"
" content\n"
"$", []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::medium); // [HH:MM:SS][severity] content
CheckOutput(
"^"
"\\[\033\\[01;36m\\d{2}:\\d{2}:\\d{2}\033\\[0m\\]"
"\\[\033\\[01;31mFATAL\033\\[0m\\]"
" content\n"
"$", []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::high); // [process_name][HH:MM:SS][severity] content
CheckOutput(
"^"
"\\[\033\\[01;34m.*\033\\[0m\\]"
"\\[\033\\[01;36m\\d{2}:\\d{2}:\\d{2}\033\\[0m\\]"
"\\[\033\\[01;31mFATAL\033\\[0m\\]"
" content\n"
"$", []() { LOG(fatal) << "content"; });
Logger::SetVerbosity(Verbosity::veryhigh); // [process_name][HH:MM:SS:µS][severity][file:line:function] content
CheckOutput(
"^"
"\\[\033\\[01;34m.*\033\\[0m\\]"
"\\[\033\\[01;36m\\d{2}:\\d{2}:\\d{2}\\.\\d{6}\033\\[0m\\]"
"\\[\033\\[01;31mFATAL\033\\[0m\\]"
"\\[\033\\[01;34m.*\033\\[0m:\033\\[01;33m\\d+\033\\[0m:\033\\[01;34m.*\033\\[0m\\]"
" content\n"
"$", []() { LOG(fatal) << "content"; });
} catch (runtime_error& rte) {
cout << rte.what() << endl;
return 1;
}
return 0;
}