Compare commits

...

48 Commits

Author SHA1 Message Date
Alexey Rybalchenko
71aac1199a Add GitHub CI workflow 2025-07-02 13:28:30 +02:00
Alexey Rybalchenko
2a4be75246 Add LOGFD and LOGPD macros 2025-07-02 13:28:30 +02:00
Alexey Rybalchenko
290070cbcf Use prefixed macros in case non-prefixed ones are undefined 2025-07-02 13:28:30 +02:00
Alexey Rybalchenko
832376101d add install/ to git ignore 2025-07-02 13:28:30 +02:00
Alexey Rybalchenko
cd9e392ce0 CMake: remove C from project versions 2025-05-19 12:40:32 +02:00
Alexey Rybalchenko
27527ad87b Add critical severity level between fatal and error 2025-02-06 15:20:41 +01:00
Dennis Klein
f3d68fb4ba build: Adopt all CMake policies up to 3.30 2024-08-20 15:56:57 +02:00
Giulio Eulisse
0ae9a697b4 Avoid extra allocation when creating the LogMetaData
By using a std::string_view for LogMetaData strings we avoid an implicit
memory allocation when passing __file__, etc. which are char const*
(notice this is also the case for the standardized
std::source_location::file_name etc).
2024-05-23 19:47:55 +02:00
Giulio Eulisse
fdbc047591 Bump minimum required C++ standard to C++17 2024-05-23 19:47:55 +02:00
Alexey Rybalchenko
ea4067c474 Update CI nodes 2024-02-22 10:31:38 +01:00
Alexey Rybalchenko
067dcc0e26 Update CI nodes 2024-02-21 13:54:16 +01:00
Alexey Rybalchenko
0ab390c465 Avoid semicolon insertion when modifying linker flags 2024-02-19 11:36:33 +01:00
Alexey Rybalchenko
56b90a7445 Avoid "Unknown severity" message also for uppercase fatal 2022-06-28 11:23:57 +02:00
Giulio Eulisse
7fc05f3808 Avoid "Unknown severity" message for fatal 2022-06-28 11:23:57 +02:00
Dennis Klein
d93fb0870b ci: Update macOS builds 2022-04-17 06:10:15 +02:00
Alexey Rybalchenko
953eac19c8 Add 'detail' severity between debug and info 2022-04-12 11:00:41 +02:00
Alexey Rybalchenko
9a6644c931 Adapt to fmt's deprecation of format_to memory buffer overload 2021-11-26 11:23:42 +01:00
Alexey Rybalchenko
27040ea292 Deprecate uppercase severity names 2021-11-25 14:29:18 +01:00
David Rohr
6545d0efa2 Include fmt/ostream.h, needed for on the fly std::ostream usage 2021-11-15 10:52:33 +01:00
Dennis Klein
159a21c24b ci: Add macos-11-arm64 (apple-clang-13) build 2021-10-01 17:10:13 +02:00
Dennis Klein
2494a9e85a Revert "Deprecate uppercase severity names"
This reverts commit ba7da2f79a.
2021-09-21 12:54:42 +02:00
Dennis Klein
d0b109015d ci: Update envs 2021-09-10 18:54:43 +02:00
Alexey Rybalchenko
ba7da2f79a Deprecate uppercase severity names 2021-09-10 14:25:31 +02:00
Alexey Rybalchenko
1c7e7f566a Bump C++ requirement to C++14 2021-09-10 14:25:31 +02:00
Alexey Rybalchenko
b2dfdd1768 Add 'alarm' and 'important' severities 2021-09-10 14:25:31 +02:00
Christian Tacke
13ebedca3d Extract find_package2 into own File
To make it easier to share find_package2 across projects
let's move it into its own file.
2021-04-09 14:26:36 +02:00
Christian Tacke
1c43450582 bundled fmt: Fix target_compile_feature
When using the bundled fmt, the declared "INTERFACE" target
can only declare INTERFACE compile features via
target_compile_feature.
2021-04-09 14:25:10 +02:00
Dennis Klein
f9af3a7269 CMake: Do not unconditionally override settings without good reason
relates FairRootGroup/FairMQ#342
2021-03-22 06:37:16 +01:00
Dennis Klein
064e034d25 Update README 2021-03-22 06:37:16 +01:00
Dennis Klein
3f55a16850 CMake: Require language level per target
https://cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html#requiring-language-standards
2021-03-22 06:37:16 +01:00
Dennis Klein
340b005997 Export relocatable include dirs 2021-03-07 11:16:40 +01:00
Dennis Klein
f012a870e7 CI: Migrate to new alfa-ci infrastructure 2021-03-05 03:06:08 +01:00
David Rohr
bcfe438862 Use for instead of if syntax to avoid compiler warnings 2020-08-25 18:53:01 +02:00
Alexey Rybalchenko
4b3e6d3837 Always define FAIR_MIN_SEVERITY 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
b30cacab12 Adjust regex expressions 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
c8d59d11fb Add test for cycle methods 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
a737a1de9c Add output operator for severities, verbosities 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
1cb941021c Add getters for file & custom sink severity 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
de1014dabb Add unit tests 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
ce64f628b0 Remove NDEBUG check 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
35ebc10204 Consider FAIR_MIN_SEVERITY when setting severities 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
1253bbbac8 Throw if removing non-existing sink or adding existing 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
e9bd3f2b62 InitFileSink(): return name of the created file 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
1f3b2a2c82 Minor formatting 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
2b37d0147e make GetColoredSeverityString public 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
f0cbe0bd47 Move Logging() to header 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
5f7197d987 Fix file sink and update fMinSeverity on its removal 2020-07-17 11:40:15 +02:00
Alexey Rybalchenko
b1cb6f8a99 Add CMake variable to control FAIR_MIN_SEVERITY 2020-07-17 11:40:15 +02:00
27 changed files with 1464 additions and 856 deletions

85
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,85 @@
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,2 +1,3 @@
build/
.vscode
install/

View File

@ -1,5 +1,5 @@
################################################################################
# Copyright (C) 2018-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# Copyright (C) 2018-2024 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
@ -7,15 +7,16 @@
################################################################################
cmake_minimum_required(VERSION 3.9.4 FATAL_ERROR)
cmake_policy(VERSION 3.9...3.15)
cmake_policy(VERSION 3.9...3.30)
# Project ######################################################################
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(FairLoggerLib)
include(FairFindPackage2)
get_git_version()
project(FairLogger VERSION ${PROJECT_VERSION} LANGUAGES C CXX)
project(FairLogger VERSION ${PROJECT_VERSION} LANGUAGES CXX)
message(STATUS "${BWhite}${PROJECT_NAME}${CR} ${PROJECT_GIT_VERSION} from ${PROJECT_DATE}")
set_fairlogger_defaults()
@ -53,32 +54,34 @@ 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_INCDIR}/bundled>
$<INSTALL_INTERFACE:${PROJECT_INSTALL_BUNDLEDINCDIR}>
)
target_compile_features(fmt INTERFACE cxx_std_11)
target_compile_definitions(fmt INTERFACE FMT_HEADER_ONLY)
target_link_libraries(FairLogger PUBLIC fmt)
list(APPEND FAIRLOGGER_INSTALL_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_INCDIR}/bundled)
endif()
if(DEFINED FAIR_MIN_SEVERITY)
target_compile_definitions(FairLogger PUBLIC "FAIR_MIN_SEVERITY=${FAIR_MIN_SEVERITY}")
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}
@ -86,8 +89,22 @@ set_target_properties(FairLogger PROPERTIES
)
if(BUILD_TESTING)
add_executable(loggerTest test/loggerTest.cxx)
target_link_libraries(loggerTest FairLogger pthread)
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)
endif()
################################################################################
@ -127,7 +144,22 @@ install_cmake_package()
# Testing ######################################################################
if(BUILD_TESTING)
add_test(NAME loggerTest COMMAND $<TARGET_FILE:loggerTest>)
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)
endif()
################################################################################
@ -212,6 +244,12 @@ 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
View File

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

79
Jenkinsfile vendored
View File

@ -1,79 +0,0 @@
#!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'
})
}
}
}
}
}

View File

@ -1,77 +0,0 @@
#!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

@ -68,9 +68,11 @@ 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");`
- `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 (only if the active verbosity allows it).
- `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");`
## 3. Severity
@ -93,10 +95,14 @@ where severity level is one of the following:
"debug2",
"debug1",
"debug",
"detail",
"info",
"state",
"warn",
"important",
"alarm",
"error",
"critical",
"fatal",
```
@ -106,12 +112,12 @@ Logger will log the chosen severity and all above it (except "nolog", which deac
The minimum severity level can be configured at compile time via definition of `FAIR_MIN_SEVERITY`:
```C++
#define FAIR_MIN_SEVERITY warn // only allow severities >= warn
#include <fairlogger/Logger.h>
```
cmake -DFAIR_MIN_SEVERITY=warn ..
```
The above would only log severities equal to or above `warn`.
When `FAIR_MIN_SEVERITY` is not provided, it will be set to `info` if `NDEBUG` is defined, otherwise all severities will be enabled.
When `FAIR_MIN_SEVERITY` is not provided all severities are enabled.
## 4. Verbosity
@ -126,8 +132,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
@ -146,12 +152,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]` |
@ -220,7 +226,7 @@ If only output from custom sinks is desirable, console/file sinks must be deacti
## Naming conflicts?
By default, `<fairlogger/Logger.h>` defines unprefixed macros: `LOG`, `LOGV`, `LOGF`, `LOGP`, `LOGN`, `LOGD`, `LOG_IF`.
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.
@ -234,4 +240,4 @@ Define an option `FAIR_NO_LOG*` to prevent the above unprefixed macros to be def
GNU Lesser General Public Licence (LGPL) version 3, see [LICENSE](LICENSE).
Copyright (C) 2017-2020 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
Copyright (C) 2017-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH

View File

@ -0,0 +1,102 @@
################################################################################
# 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-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# 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, #
@ -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 @FAIRLOGGER_INSTALL_INCLUDE_DIRS@)
set(@PROJECT_NAME@_INCDIRS @FAIRLOGGER_INSTALL_INCLUDE_DIRS@)
set(@PROJECT_NAME@_INCDIR @PACKAGE_INSTALL_INCDIRS@)
set(@PROJECT_NAME@_INCDIRS @PACKAGE_INSTALL_INCDIRS@)
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-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# 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, #
@ -94,24 +94,22 @@ macro(set_fairlogger_defaults)
endif()
# Handle C++ standard level
set(PROJECT_MIN_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD ${PROJECT_MIN_CXX_STANDARD})
elseif(${CMAKE_CXX_STANDARD} LESS ${PROJECT_MIN_CXX_STANDARD})
set(PROJECT_MIN_CXX_STANDARD 17)
if(CMAKE_CXX_STANDARD LESS PROJECT_MIN_CXX_STANDARD)
message(FATAL_ERROR "A minimum CMAKE_CXX_STANDARD of ${PROJECT_MIN_CXX_STANDARD} is required.")
endif()
set(CMAKE_CXX_EXTENSIONS OFF)
# Generate compile_commands.json file (https://clang.llvm.org/docs/JSONCompilationDatabase.html)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(NOT DEFINED CMAKE_EXPORT_COMPILE_COMMANDS)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
endif()
if(NOT BUILD_SHARED_LIBS)
if(NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON CACHE BOOL "Whether to build shared libraries or static archives")
endif()
# Set -fPIC as default for all library types
if(NOT CMAKE_POSITION_INDEPENDENT_CODE)
if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
@ -122,6 +120,7 @@ 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
@ -129,13 +128,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")
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}")
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}")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(CMAKE_INSTALL_RPATH "@loader_path/../${PROJECT_INSTALL_LIBDIR}")
list(APPEND CMAKE_INSTALL_RPATH "@loader_path/../${PROJECT_INSTALL_LIBDIR}")
else()
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_LIBDIR}")
list(APPEND CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_LIBDIR}")
endif()
endif()
@ -227,6 +226,13 @@ 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}})
@ -242,98 +248,3 @@ 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,11 +1,12 @@
/********************************************************************************
* Copyright (C) 2014-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* Copyright (C) 2014-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 "Logger.h"
#include <string_view>
#if FMT_VERSION < 60000
#include <fmt/time.h>
@ -15,6 +16,7 @@
#include <cstdio> // printf
#include <iostream>
#include <iterator> // std::back_inserter
using namespace std;
@ -23,31 +25,12 @@ 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::info;
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::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;
@ -62,53 +45,59 @@ const string Logger::fProcessName = program_invocation_short_name;
const string Logger::fProcessName = "?";
#endif
const unordered_map<string, Verbosity> Logger::fVerbosityMap =
const unordered_map<string_view, 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, Severity> Logger::fSeverityMap =
const unordered_map<string_view, Severity> Logger::fSeverityMap =
{
{ "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 }
{ {"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 }
};
const array<string, 12> Logger::fSeverityNames =
const array<string_view, 16> Logger::fSeverityNames =
{
{
"NOLOG",
@ -118,15 +107,19 @@ const array<string, 12> Logger::fSeverityNames =
"DEBUG2",
"DEBUG1",
"DEBUG",
"DETAIL",
"INFO",
"STATE",
"WARN",
"IMPORTANT",
"ALARM",
"ERROR",
"CRITICAL",
"FATAL"
}
};
const array<string, 9> Logger::fVerbosityNames =
const array<string_view, 9> Logger::fVerbosityNames =
{
{
"verylow",
@ -154,12 +147,11 @@ map<Verbosity, VSpec> Logger::fVerbosities =
{ Verbosity::user4, VSpec::Make(VSpec::Info::severity) }
};
Logger::Logger(Severity severity, Verbosity verbosity, const string& file, const string& line, const string& func)
Logger::Logger(Severity severity, Verbosity verbosity, std::string_view file, std::string_view line, std::string_view func)
: fTimeCalculated(false)
{
if (!fIsDestructed) {
size_t pos = file.rfind("/");
// fInfos.timestamp is filled conditionally
// fInfos.us is filled conditionally
fInfos.process_name = fProcessName;
@ -175,27 +167,27 @@ Logger::Logger(Severity severity, Verbosity verbosity, const string& file, const
for (const auto info : spec.fInfos) {
switch (info) {
case VSpec::Info::process_name:
fmt::format_to(fBWPrefix, "[{}]", fInfos.process_name);
fmt::format_to(std::back_inserter(fBWPrefix), "[{}]", fInfos.process_name);
break;
case VSpec::Info::timestamp_us:
FillTimeInfos();
fmt::format_to(fBWPrefix, "[{:%H:%M:%S}.{:06}]", fmt::localtime(fInfos.timestamp), fInfos.us.count());
fmt::format_to(std::back_inserter(fBWPrefix), "[{:%H:%M:%S}.{:06}]", fmt::localtime(fInfos.timestamp), fInfos.us.count());
break;
case VSpec::Info::timestamp_s:
FillTimeInfos();
fmt::format_to(fBWPrefix, "[{:%H:%M:%S}]", fmt::localtime(fInfos.timestamp));
fmt::format_to(std::back_inserter(fBWPrefix), "[{:%H:%M:%S}]", fmt::localtime(fInfos.timestamp));
break;
case VSpec::Info::severity:
fmt::format_to(fBWPrefix, "[{}]", fInfos.severity_name);
fmt::format_to(std::back_inserter(fBWPrefix), "[{}]", fInfos.severity_name);
break;
case VSpec::Info::file_line_function:
fmt::format_to(fBWPrefix, "[{}:{}:{}]", fInfos.file, fInfos.line, fInfos.func);
fmt::format_to(std::back_inserter(fBWPrefix), "[{}:{}:{}]", fInfos.file, fInfos.line, fInfos.func);
break;
case VSpec::Info::file_line:
fmt::format_to(fBWPrefix, "[{}:{}]", fInfos.file, fInfos.line);
fmt::format_to(std::back_inserter(fBWPrefix), "[{}:{}]", fInfos.file, fInfos.line);
break;
case VSpec::Info::file:
fmt::format_to(fBWPrefix, "[{}]", fInfos.file);
fmt::format_to(std::back_inserter(fBWPrefix), "[{}]", fInfos.file);
break;
default:
break;
@ -203,7 +195,7 @@ Logger::Logger(Severity severity, Verbosity verbosity, const string& file, const
}
if (spec.fSize > 0) {
fmt::format_to(fBWPrefix, " ");
fmt::format_to(std::back_inserter(fBWPrefix), " ");
}
}
@ -211,27 +203,27 @@ Logger::Logger(Severity severity, Verbosity verbosity, const string& file, const
for (const auto info : spec.fInfos) {
switch (info) {
case VSpec::Info::process_name:
fmt::format_to(fColorPrefix, "[{}]", ColorOut(Color::fgBlue, fInfos.process_name));
fmt::format_to(std::back_inserter(fColorPrefix), "[{}]", ColorOut(Color::fgBlue, fInfos.process_name));
break;
case VSpec::Info::timestamp_us:
FillTimeInfos();
fmt::format_to(fColorPrefix, "[{}{:%H:%M:%S}.{:06}{}]", startColor(Color::fgCyan), fmt::localtime(fInfos.timestamp), fInfos.us.count(), endColor());
fmt::format_to(std::back_inserter(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(fColorPrefix, "[{}{:%H:%M:%S}{}]", startColor(Color::fgCyan), fmt::localtime(fInfos.timestamp), endColor());
fmt::format_to(std::back_inserter(fColorPrefix), "[{}{:%H:%M:%S}{}]", startColor(Color::fgCyan), fmt::localtime(fInfos.timestamp), endColor());
break;
case VSpec::Info::severity:
fmt::format_to(fColorPrefix, "[{}]", GetColoredSeverityString(fInfos.severity));
fmt::format_to(std::back_inserter(fColorPrefix), "[{}]", GetColoredSeverityString(fInfos.severity));
break;
case VSpec::Info::file_line_function:
fmt::format_to(fColorPrefix, "[{}:{}:{}]", ColorOut(Color::fgBlue, fInfos.file), ColorOut(Color::fgYellow, fInfos.line), ColorOut(Color::fgBlue, fInfos.func));
fmt::format_to(std::back_inserter(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(fColorPrefix, "[{}:{}]", ColorOut(Color::fgBlue, fInfos.file), ColorOut(Color::fgYellow, fInfos.line));
fmt::format_to(std::back_inserter(fColorPrefix), "[{}:{}]", ColorOut(Color::fgBlue, fInfos.file), ColorOut(Color::fgYellow, fInfos.line));
break;
case VSpec::Info::file:
fmt::format_to(fColorPrefix, "[{}]", ColorOut(Color::fgBlue, fInfos.file));
fmt::format_to(std::back_inserter(fColorPrefix), "[{}]", ColorOut(Color::fgBlue, fInfos.file));
break;
default:
break;
@ -239,7 +231,7 @@ Logger::Logger(Severity severity, Verbosity verbosity, const string& file, const
}
if (spec.fSize > 0) {
fmt::format_to(fColorPrefix, " ");
fmt::format_to(std::back_inserter(fColorPrefix), " ");
}
}
@ -294,8 +286,35 @@ 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();
}
@ -317,6 +336,10 @@ 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();
}
@ -333,8 +356,17 @@ void Logger::SetFileSeverity(const string& severityStr)
void Logger::SetCustomSeverity(const string& key, const Severity severity)
{
fCustomSinks.at(key).first = severity; // TODO: range checks
UpdateMinSeverity();
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;
}
}
void Logger::SetCustomSeverity(const string& key, const string& severityStr)
@ -347,11 +379,21 @@ 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(static_cast<Severity>(0));
SetConsoleSeverity(Severity::FAIR_MIN_SEVERITY);
} else {
SetConsoleSeverity(static_cast<Severity>(current + 1));
}
@ -359,7 +401,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";
@ -369,7 +411,7 @@ void Logger::CycleConsoleSeverityUp()
void Logger::CycleConsoleSeverityDown()
{
int current = static_cast<int>(fConsoleSeverity);
if (current == 0) {
if (current == static_cast<int>(Severity::FAIR_MIN_SEVERITY)) {
SetConsoleSeverity(static_cast<Severity>(fSeverityNames.size() - 1));
} else {
SetConsoleSeverity(static_cast<Severity>(current - 1));
@ -378,7 +420,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";
@ -397,7 +439,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";
@ -416,7 +458,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";
@ -428,7 +470,7 @@ void Logger::UpdateMinSeverity()
if (fFileSeverity == Severity::nolog) {
fMinSeverity = fConsoleSeverity;
} else {
fMinSeverity = std::min(fConsoleSeverity, fFileSeverity);
fMinSeverity = std::max(fConsoleSeverity, fFileSeverity);
}
for (auto& it : fCustomSinks) {
@ -440,13 +482,6 @@ void Logger::UpdateMinSeverity()
}
}
bool Logger::Logging(Severity severity)
{
return (severity >= fMinSeverity &&
fMinSeverity > Severity::nolog) ||
severity == Severity::fatal;
}
bool Logger::Logging(const string& severityStr)
{
if (fSeverityMap.count(severityStr)) {
@ -496,7 +531,7 @@ void Logger::SetConsoleColor(const bool colored)
fColored = colored;
}
void Logger::InitFileSink(const Severity severity, const string& filename, bool customizeName)
string Logger::InitFileSink(const Severity severity, const string& filename, bool customizeName)
{
lock_guard<mutex> lock(fMtx);
if (fFileStream.is_open()) {
@ -521,21 +556,27 @@ void Logger::InitFileSink(const Severity severity, const string& filename, bool
fFileStream.open(fullName, fstream::out | fstream::app);
if (fFileStream.is_open()) {
fFileSeverity = severity;
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;
}
UpdateMinSeverity();
} else {
cout << "Error opening file: " << fullName;
}
return fullName;
}
void Logger::InitFileSink(const string& severityStr, const string& filename, bool customizeName)
string Logger::InitFileSink(const string& severityStr, const string& filename, bool customizeName)
{
if (fSeverityMap.count(severityStr)) {
InitFileSink(fSeverityMap.at(severityStr), filename, customizeName);
return InitFileSink(fSeverityMap.at(severityStr), filename, customizeName);
} else {
LOG(error) << "Unknown severity setting: '" << severityStr << "', setting to default 'info'.";
InitFileSink(Severity::info, filename);
return InitFileSink(Severity::info, filename);
}
}
@ -544,6 +585,8 @@ void Logger::RemoveFileSink()
lock_guard<mutex> lock(fMtx);
if (fFileStream.is_open()) {
fFileStream.close();
fFileSeverity = Severity::nolog;
UpdateMinSeverity();
}
}
@ -577,10 +620,16 @@ void Logger::AddCustomSink(const string& key, Severity severity, function<void(c
{
lock_guard<mutex> lock(fMtx);
if (fCustomSinks.count(key) == 0) {
fCustomSinks.insert(make_pair(key, make_pair(severity, func)));
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)));
}
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.");
}
}
@ -601,6 +650,7 @@ 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-2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* Copyright (C) 2014-2025 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
@ -13,8 +13,8 @@
#warning "The symbol 'DEBUG' is used in FairRoot Logger. undefining..."
#endif
#if !defined(FAIR_MIN_SEVERITY) && defined(NDEBUG)
#define FAIR_MIN_SEVERITY info
#ifndef FAIR_MIN_SEVERITY
#define FAIR_MIN_SEVERITY nolog
#endif
#ifdef FAIRLOGGER_USE_BOOST_PRETTY_FUNCTION
@ -26,6 +26,7 @@
#include <fmt/core.h>
#include <fmt/printf.h>
#include <fmt/ostream.h>
#pragma GCC diagnostic pop
@ -39,10 +40,12 @@
#include <mutex>
#include <ostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <time.h> // time_t
#include <type_traits>
#include <type_traits> // is_same
#include <unordered_map>
#include <string_view>
#include <utility> // pair
namespace fair
@ -57,52 +60,57 @@ enum class Severity : int
debug2 = 4,
debug1 = 5,
debug = 6,
info = 7,
state = 8,
warn = 9,
error = 10,
fatal = 11,
// backwards-compatibility:
NOLOG = nolog,
TRACE = trace,
DEBUG4 = debug4,
DEBUG3 = debug3,
DEBUG2 = debug2,
DEBUG1 = debug1,
DEBUG = debug,
INFO = info,
STATE = state,
WARNING = warn,
detail = 7,
info = 8,
state = 9,
warn = 10,
important = 11,
alarm = 12,
error = 13,
critical = 14,
fatal = 15,
// aliases
warning = warn,
WARN = warn,
ERROR = error,
FATAL = fatal
// 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
};
// 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,
verylow = 0,
low,
medium,
high,
veryhigh,
// backwards-compatibility:
VERYLOW = verylow,
LOW = low,
MEDIUM = medium,
HIGH = high,
VERYHIGH = veryhigh,
// extra slots for user-defined verbosities:
user1,
user2,
user3,
user4,
// backwards-compatibility:
VERYLOW = verylow,
LOW = low,
MEDIUM = medium,
HIGH = high,
VERYHIGH = veryhigh
};
struct VerbositySpec
@ -110,7 +118,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]
@ -169,19 +177,19 @@ struct LogMetaData
{
std::time_t timestamp;
std::chrono::microseconds us;
std::string process_name;
std::string file;
std::string line;
std::string func;
std::string severity_name;
std::string_view process_name;
std::string_view file;
std::string_view line;
std::string_view func;
std::string_view severity_name;
fair::Severity severity;
};
class Logger
{
public:
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 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, fVerbosity, file, line, func)
{}
virtual ~Logger() noexcept(false);
@ -238,7 +246,8 @@ 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, const std::string& s) { return fmt::format("\033[01;{}m{}\033[0m", static_cast<int>(c), s); }
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 void SetConsoleSeverity(const Severity severity);
static void SetConsoleSeverity(const std::string& severityStr);
@ -246,16 +255,23 @@ 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);
static bool Logging(const Severity severity)
{
return (severity >= fMinSeverity &&
fMinSeverity > Severity::nolog) ||
severity == Severity::fatal;
}
static bool Logging(const std::string& severityStr);
static void SetVerbosity(const Verbosity verbosity);
@ -266,13 +282,13 @@ class Logger
static void SetConsoleColor(const bool colored = 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 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 RemoveFileSink();
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 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 void OnFatal(std::function<void()> func);
@ -308,10 +324,10 @@ 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, 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;
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;
// protection for use after static destruction took place
static bool fIsDestructed;
@ -319,11 +335,7 @@ class Logger
static bool constexpr SuppressSeverity(Severity sev)
{
#ifdef FAIR_MIN_SEVERITY
return sev < Severity::FAIR_MIN_SEVERITY;
#else
return false;
#endif
}
private:
@ -358,6 +370,9 @@ 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
@ -379,16 +394,16 @@ class Logger
#undef LOGV
#define LOGV FAIR_LOGV
#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 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
@ -404,38 +419,59 @@ class Logger
#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) \
if (fair::Logger::SuppressSeverity(fair::Severity::severity)) ; else \
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)
// Log line with the given verbosity if the provided severity is below or equals the configured one
#define FAIR_LOGV(severity, verbosity) \
if (fair::Logger::SuppressSeverity(fair::Severity::severity)) ; else \
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)
// Log with fmt- or printf-like formatting
#define FAIR_LOGP(severity, ...) LOG(severity) << fmt::format(__VA_ARGS__)
#define FAIR_LOGF(severity, ...) LOG(severity) << fmt::sprintf(__VA_ARGS__)
#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__)
// Log an empty line
#define FAIR_LOGN(severity) \
if (fair::Logger::SuppressSeverity(fair::Severity::severity)) ; else \
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()
// Log with custom file, line, function
#define FAIR_LOGD(severity, file, line, f) \
if (fair::Logger::SuppressSeverity(severity)) ; else \
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 FAIR_LOG_IF(severity, condition) \
if (fair::Logger::SuppressSeverity(fair::Severity::severity)) ; else \
for (bool fairLOggerunLikelyvariable4 = false; !fair::Logger::SuppressSeverity(fair::Severity::severity) && !fairLOggerunLikelyvariable4; fairLOggerunLikelyvariable4 = true) \
for (bool fairLOggerunLikelyvariable2 = false; condition && !fairLOggerunLikelyvariable2; fairLOggerunLikelyvariable2 = true) \
LOG(severity)
FAIR_LOG(severity)
#endif // FAIR_LOGGER_H

100
test/Common.h Normal file
View File

@ -0,0 +1,100 @@
/********************************************************************************
* 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

41
test/ci/CMakeLists.txt Normal file
View File

@ -0,0 +1,41 @@
################################################################################
# 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})

8
test/ci/linux.def.in Normal file
View File

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

7
test/ci/setup-fedora.sh Executable file
View File

@ -0,0 +1,7 @@
#! /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

35
test/ci/slurm-submit.sh Executable file
View File

@ -0,0 +1,35 @@
#! /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"

81
test/cycle.cxx Normal file
View File

@ -0,0 +1,81 @@
/********************************************************************************
* 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;
}

62
test/logger.cxx Normal file
View File

@ -0,0 +1,62 @@
/********************************************************************************
* 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;
}

View File

@ -1,208 +0,0 @@
/********************************************************************************
* 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);
LOGP(info, "Hello {} {}!", "world", ":-)");
LOGF(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;
}

67
test/macros.cxx Normal file
View File

@ -0,0 +1,67 @@
/********************************************************************************
* 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;
}

64
test/nolog.cxx Normal file
View File

@ -0,0 +1,64 @@
/********************************************************************************
* 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;
}

102
test/severity.cxx Normal file
View File

@ -0,0 +1,102 @@
/********************************************************************************
* 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;
}

151
test/sinks.cxx Normal file
View File

@ -0,0 +1,151 @@
/********************************************************************************
* 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;
}

67
test/threads.cxx Normal file
View File

@ -0,0 +1,67 @@
/********************************************************************************
* 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;
}

102
test/verbosity.cxx Normal file
View File

@ -0,0 +1,102 @@
/********************************************************************************
* 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;
}