Giter Club home page Giter Club logo

fairlogger's Introduction

FairLogger

Lightweight and fast C++ Logging Library

example output

Branch Build Status
master build status master branch
dev build status dev branch

Installation

git clone https://github.com/FairRootGroup/FairLogger
mkdir FairLogger_build && cd FairLogger_build
cmake -DCMAKE_INSTALL_PREFIX=./FairLogger_install ../FairLogger
cmake --build . --target install

FairLogger bundles a version of the fmt library. You can override this with your own fmt installation via the -DUSE_EXTERNAL_FMT=ON and -DFMT_ROOT=/fmt/location CMake switches.

Usage

In your CMakeLists.txt:

find_package(FairLogger)

If FairLogger is not installed in system directories, you can hint the installation location:

set(CMAKE_PREFIX_PATH /path/to/FairLogger/installation ${CMAKE_PREFIX_PATH})
find_package(FairLogger)

find_package(FairLogger) will define an imported target FairLogger::FairLogger.

If FairLogger is built with -DUSE_BOOST_PRETTY_FUNCTION=ON and/or -DUSE_EXTERNAL_FMT=ON, your project needs to find the external dependencies, too, e.g.

find_package(FairLogger)
foreach(dep IN LISTS FairLogger_PACKAGE_DEPENDENCIES)
  find_package(${dep} ${FairLogger_${dep}_VERSION})
endforeach()

CMake options

On command line:

  • -DDISABLE_COLOR=ON disables coloured console output.
  • -DBUILD_TESTING=OFF disables building of unit tests.
  • -DUSE_BOOST_PRETTY_FUNCTION=ON enables usage of BOOST_PRETTY_FUNCTION macro.
  • -DUSE_EXTERNAL_FMT=ON uses external fmt instead of the bundled one.

Documentation

1. General

All log calls go through the provided LOG(severity) macro. Output through this macro is thread-safe. Logging is done to cout, file output and/or custom sinks.

2. Additional macros

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 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 and the result is logged, e.g. LOGP(info, "Hello {}!", "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).

3. Severity

The log severity is controlled via:

fair::Logger::SetConsoleSeverity("<severity level>");
// and/or
fair::Logger::SetFileSeverity("<severity level>");
// and/or
fair::Logger::SetCustomSeverity("<customSinkName>", "<severity level>");

where severity level is one of the following:

"nolog",
"trace",
"debug4",
"debug3",
"debug2",
"debug1",
"debug",
"detail",
"info",
"state",
"warn",
"important",
"alarm",
"error",
"fatal",

Logger will log the chosen severity and all above it (except "nolog", which deactivates logging for that sink completely). Fatal severity is always logged.

3.1 Compile-time severity switch

The minimum severity level can be configured at compile time via definition of FAIR_MIN_SEVERITY:

cmake -DFAIR_MIN_SEVERITY=warn ..

The above would only log severities equal to or above warn.

When FAIR_MIN_SEVERITY is not provided all severities are enabled.

4. Verbosity

The log verbosity is controlled via:

fair::Logger::SetVerbosity("<verbosity level>");

it is same for all sinks, and is one of the following values: verylow, low, medium, high, veryhigh, user1, user2, user3, user4, which translates to following output:

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
user1:    [severity] message
user2:    [severity] message
user3:    [severity] message
user4:    [severity] message

When running a FairMQ device, the log severity can be simply provided via --verbosity <level> cmd option.

The user may customize the existing verbosities or any of user1, user2, user3, user4 verbosities via:

void fair::Logger::DefineVerbosity(fair::Verbosity, fair::VerbositySpec);
void fair::Logger::DefineVerbosity("<verbosity level>", fair::VerbositySpec);

The fair::Logger::VerbositySpec object can e.g. be created like this:

auto spec = fair::VerbositySpec::Make(VerbositySpec::Info::timestamp_s,
                                      VerbositySpec::Info::process_name);
// results in [HH:MM:SS][process_name] message
Argument Result
fair::VerbositySpec::Info::process_name [process_name]
fair::VerbositySpec::Info::timestamp_s [HH:MM:SS]
fair::VerbositySpec::Info::timestamp_us [HH:MM:SS:µS]
fair::VerbositySpec::Info::severity [severity]
fair::VerbositySpec::Info::file [file]
fair::VerbositySpec::Info::file_line [file:line]
fair::VerbositySpec::Info::file_line_function [file:line:function]

4.1 BOOST_PRETTY_FUNCTION support

By default, the veryhigh verbosity prints the function name from which the LOG macro was invoked. If you desire a more verbose function signature including the full namespace, return value and function arguments, you can enable support for BOOST_PRETTY_FUNCTION

  • globally by compiling FairLogger with the CMake option -DUSE_BOOST_PRETTY_FUNCTION=ON, or
  • per translation unit by defining FAIRLOGGER_USE_BOOST_PRETTY_FUNCTION before including the FairLogger header, e.g.
#define FAIRLOGGER_USE_BOOST_PRETTY_FUNCTION
#include <Logger.h>

In the latter case, the user needs to take care of adding the boost include path to the compiler search path manually (e.g. -I/path/to/boost/include).

5. Color

Colored output on console can be activated with:

Logger::SetConsoleColor(true);

When running a FairMQ device, the log color (console) can be simply provided via --color <true/false> cmd option (default is true).

6. File output

Output to file can be enabled via:

Logger::InitFileSink("<severity level>", "test_log", true);

which will add output to "test_log" filename (if third parameter is true it will add timestamp to the file name) with <severity level> severity.

When running a FairMQ device, the log file can be simply provided via --log-to-file <filename_prefix> cmd option (this will also turn off console output).

7. Custom sinks

Custom sinks can be added via Logger::AddCustomSink("sink name", "<severity>", callback) method.

Here is an example adding a custom sink for all severities ("trace" and above). It has access to the log content and meta data. Custom log calls are also thread-safe.

    Logger::AddCustomSink("MyCustomSink", "trace", [](const string& content, const LogMetaData& metadata)
    {
        cout << "content: " << content << endl;

        cout << "available metadata: " << endl;
        cout << "std::time_t timestamp: " << metadata.timestamp << endl;
        cout << "std::chrono::microseconds us: " << metadata.us.count() << endl;
        cout << "std::string process_name: " << metadata.process_name << endl;
        cout << "std::string file: " << metadata.file << endl;
        cout << "std::string line: " << metadata.line << endl;
        cout << "std::string func: " << metadata.func << endl;
        cout << "std::string severity_name: " << metadata.severity_name << endl;
        cout << "fair::Severity severity: " << static_cast<int>(metadata.severity) << endl;
    });

If only output from custom sinks is desirable, console/file sinks must be deactivated by setting their severity to "nolog".

Naming conflicts?

By default, <fairlogger/Logger.h> defines unprefixed macros: LOG, LOGV, LOGF, LOGP, LOGN, LOGD, LOG_IF.

Define an option FAIR_NO_LOG* to prevent the above unprefixed macros to be defined, e.g.

#define FAIR_NO_LOG
#define FAIR_NO_LOGF
#include <fairlogger/Logger.h>

License

GNU Lesser General Public Licence (LGPL) version 3, see LICENSE.

Copyright (C) 2017-2021 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH

fairlogger's People

Contributors

christiantackegsi avatar davidrohr avatar dennisklein avatar ktf avatar rbx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fairlogger's Issues

a semicolon was inserted in the linker flags

list(APPEND CMAKE_EXE_LINKER_FLAGS "-Wl,--enable-new-dtags")
list(APPEND CMAKE_SHARED_LINKER_FLAGS "-Wl,--enable-new-dtags")

I found that in the above code, cmake inserts a semicolon in the linker flags, resulting in an error.
I suggest the following modification:

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

Handle Print() with FairLogger

Dear developers,

how do I handle the following code with the FairLogger?

    TParticle *p = (TParticle *)tr->GetParticle();
    std::cout << "Stage " << p->GetStatusCode() << " : ";
    p->Print();

The output looks like this:
Stage 4 : TParticle: pi- p: 0.290435 0.529053 1.184810 Vertex: 0.000000e+00 0.000000e+00 0.000000e+00 -1 -1

I have two problems:

  • LOG(debug) always adds a new line at the end
  • How to deal with p->Print()

Be able to customize verbosity information

At the moment it is possible to have fixed formats for verbosity levels
// verylow: message
// low: [severity] message
// medium: [HH:MM:SS][severity] message
// high: [process name][HH:MM:SS:µS][severity] message
// veryhigh: [process name][HH:MM:SS:µS][severity][file:line:function] message

As a user, I would like to be able to configure these formats, or to provide a custom verbosity level.
Say I need something without process name, without time but more information on the function (for instance including the full namespace).

Missing v1.2.0 tag

When building dev branch, the version v.1.1.0 is installed. If I type "git log", the tag v1.2.0 is not shown. @dennisklein could you please check?

Ability to only use the custom syncs?

In order to reduce the number of open file descriptors, I would like to disable FairLogger for everything but a custom sink. Is that actually possible? How do I prevent echoing to stdout?

-Wdangling-else

OS: macOS 10.14.6
Compiler: Apple LLVM version 10.0.1 (clang-1001.0.46.4)

In file included from /Users/alfaci/dklein/FairMQ/test/helper/runTestDevice.cxx:9:
/Users/alfaci/dklein/FairMQ/test/helper/devices/TestPairLeft.h:45:27: warning: add explicit braces to avoid dangling else [-Wdangling-else]
        if (counter == 4) LOG(info) << "Simple empty message ping pong successfull";
                          ^
/Users/alfaci/dklein/include/fairlogger/Logger.h:375:13: note: expanded from macro 'LOG'
#define LOG FAIR_LOG
            ^
/Users/alfaci/dklein/include/fairlogger/Logger.h:410:69: note: expanded from macro 'FAIR_LOG'
    if (fair::Logger::SuppressSeverity(fair::Severity::severity)) ; else \
                                                                    ^

Possibility to have a variable/expression as log level

I am trying to do something like:

LOG(foo == bar ? warning : error) << "this can be a warning or an error";

Is this possible with fairlogger (without an if/else and 2 LOG statements?
Or would it make sense to extend the API to support such a case?

Add option to change name of the LOG macro

Suggestion: In Logger.h rename the LOG macro to FAIRMQ_LOG (or whatever prefix you use consistently for macros) and use it instead of LOG throughout all headers. Add the following to Logger.h:

#ifdef FAIRMQ_DEFINE_LOG
#undef LOG
#define LOG FAIRMQ_LOG
#endif

Now in source files where you want to use the LOG macro, define FAIRMQ_DEFINE_LOG before including Logger.h:

#define FAIRMQ_DEFINE_LOG
#include <fairlogger/Logger.h>

Alternatively, turn the logic around and #define LOG FAIRMQ_LOG by default, unless FAIRMQ_NO_LOG is defined.

Originally posted by @mattkretz in FairRootGroup/FairMQ#244 (comment)

Provide ostream based API

I would like to use FairLogger with some external component, which has the possibility to pipe log messages on a provided std::ostream. Is there any way we could have a wrapper around Logger which is std::ostream derived, while still using FairLogger as backend?

FairLogger uses internal fmt version when asked to install, regardless of `-DUSE_EXTERNAL_FMT=ON`

I have the strange behaviour where:

 29 cmake $SOURCEDIR                                                 \
 30       ${CXX_COMPILER:+-DCMAKE_CXX_COMPILER=$CXX_COMPILER}        \
 31       ${CMAKE_BUILD_TYPE:+-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE}  \
 32       ${CXXSTD:+-DCMAKE_CXX_STANDARD=$CXXSTD}                    \
 33       -DPROJECT_GIT_VERSION=$(echo $PKGVERSION | sed -e 's/v//') \
 34       -DBUILD_TESTING=OFF                                        \
 35       -DCMAKE_INSTALL_PREFIX=$INSTALLROOT                        \
 36       -DDISABLE_COLOR=ON                                         \
 37       -DUSE_EXTERNAL_FMT=ON                                      \
 38       -DCMAKE_INSTALL_LIBDIR=lib
 39
 40 cmake --build . ${JOBS:+-- -j$JOBS}
 41 ctest ${JOBS:+-j$JOBS}
 42 cmake --build . --target install ${JOBS:+-- -j$JOBS}

works, while:

cmake --build . --target install ${JOBS:+-- -j$JOBS}

does not and fails with:

In file included from /Users/ktf/src/sw/SOURCES/FairLogger/master/0/logger/Logger.cxx:8:
In file included from /Users/ktf/src/sw/SOURCES/FairLogger/master/0/logger/Logger.h:27:
/Users/ktf/src/sw/SOURCES/FairLogger/master/0/logger/bundled/fmt/core.h:202:20: error: no template named 'result_of' in namespace 'std'; did you mean '::fmt::internal::result_of'?
  typedef typename std::result_of<
                   ^~~~~~~~~~~~~~
                   ::fmt::internal::result_of
/Users/ktf/src/sw/SOURCES/FairLogger/master/0/logger/bundled/fmt/core.h:197:8: note: '::fmt::internal::result_of' declared here
struct result_of;

notice the bundled version of fmt being used.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.