C / C ++ supporting conditional function calls depending on log level

Some research on existing C / C ++ solutions turned out that Pantheios might be the best in my case, it is the lowest overhead if logging is disabled.

All loggers seem to support some sort of print log message. However, in my case, I have a function call that should be avoided if logging is disabled (as it is quite expensive).

I am currently using a very simple registration setup like

#ifdef DEBUG_L1    
cout << "msg 1" << endl // log level 1
#ifdef DEBUG_L2
printBuffer()           // log level 2
#endif
#endif

      

It serves my needs (for now) as I pay zero overhead if logging is disabled. However, the code quickly looks ugly and not very flexible.

This should be implemented with a C ++ logger. As said, the function body is printBuffer()

quite expensive. It would be nice if it could be avoided if logging is disabled.

Is it possible to declare an entire function call only to execute above a certain log level? Or do I need a preprocessor in this case?

Edit:

Thanks @BobTFish. I was actually thinking about using the setting you describe. I am wondering how flexible it is to implement this. I usually write a set of strings and values ​​( int

, float

and pointers). In style

cout << "name1=" << int << " name2=" << (void*)(ptr) << endl;

      

Now, I really don't like switching to syntax printf

per se. How does the macro approach handle this (since it masked it with only one class parameter)?

+3


source to share


3 answers


What I mean is C ++ specific logging patterns like easylogging or spdlog. In spdlog , for example, you can create your own target log files by implementing the receiver interface. Another option (probably a better one) is to use the log-level function.

Here's an example (copied from the spdlog manual):



    //
    // Runtime log levels
    //
    spd::set_level(spd::level::info); //Set global log level to info
    console->debug("This message shold not be displayed!");
    console->set_level(spd::level::debug); // Set specific logger log level
    console->debug("Now it should..");

      

By implementing the <operator for your own custom class, you can control what data is flushed to the log. With, logger->should_log()

you can check if the specified log level is enabled.

+2


source


I think you can use google logging library from here

Typical use of glog with condition



#include <glog/logging.h>

{
  // Initialize logging. There are multiple options, so read the documentation
  google::InitGoogleLogging();

  void* p;
  LOG_IF(INFO, p == nullptr) << "We have nullptr. Bomb detected!";

  // Don't forget to shut that down
  google::ShutdownGoogleLogging();
}

      

+1


source


If you are interested in performance and runtime take a look at the zf_log library. What you might like:

  • It evaluates the logging arguments and calls the actual logging function only when needed (when the log level allows it).
  • It has a runtime log level and a compilation log level. The statements LOG()

    below the compilation log level are compiled and have no runtime overhead.
  • The runtime level at runtime can be changed, but when the message log level is below the execution log level, the arguments will not be evaluated and the actual log function will not be called. The only thing that will be appreciated is this if (msg_log_level >= runtime_log_level)

    .
  • It has an extremely small calling site (the amount of code generated per line LOG()

    ), 3x -20x less than other libraries.
  • It does not slow down compilation of your sources that include its headers (unlike some header-only libraries).
0


source







All Articles