How to implement a logging macro with automatic newline in C++ - c++

In the C++ library glog (Google logging module) there is a nice interface where you can write
LOG(INFO) << "abc " << my_var;
and at runtime it prints something like abc 5\n at runtime (if my_var was 5) where it automatically terminated with a newline.
This is much superior to having to always terminate with std::endl as in
std::cout << "abc " << my_var << std::endl;
What is the simpliest way (code + macros) do I need to replicate this effect in my code?

I think the idea is to return a temp wrapper object:
#include <iostream>
struct Log
{
~Log(void) { ::std::cout << ::std::endl; }
};
template<typename T> Log &&
operator <<(Log && wrap, T const & whatever)
{
::std::cout << whatever;
return ::std::move(wrap);
}
int main()
{
Log() << "whatever";
Log() << "more";
return 0;
}
online compiler
Note that the macro can be used here to execute conditional branching in the beginning of logging. That is skip logging if severity level is low.
#define LOG(level) \
if(g_log_lelevel <= level) Log()

Related

Processing all passed overloads at once

I'm tired of making up on the spot debug codes and including <iostream> in every single file. So I wanted to make myself a universal, self-contained and lightweight debug class, that I would just include in the header, and forget.
I want to use something along the lines of
#include "debug.hpp"
debug DBG;
DBG << "foo and" << " bar";
//Or even better, just include it and do debug() << "foo and" << " bar";
So, I wrote this:
#include <iostream>
#include <string>
#include <chrono>
#include <ctime>
class Debug
{
public:
Debug &operator<<(std::string arg_0)
{
auto tempTime = std::chrono::system_clock::to_time_t(
std::chrono::system_clock::now() );
auto timeString(ctime(&tempTime));
timeString = timeString.substr(timeString.find(':') - 2, 8);
std::cout << timeString << " >> " << arg_0 << '\n';
return *this;
}
};
But of course, this doesn't work because, as I've learned, every overload operator causes this function (is it still called a function?) to trigger separately. Creating:
hour:minute:second >> foo and
hour:minute:second >> bar
Any way I could pass everything at once after the first overload operator appears? Maybe as a stringstream? Also, I won't be only passing strings, but anything that I need, will this require me to manually create a separate overload function for every signle type that I may pass?
P.S: Cross-plaform solution is optional, but welcome (Currently developing on Linux)
You may return an other class to do the job, something like:
class Helper
{
public:
~Helper() { std::cout << "\n"; }
template<typename T>
friend Helper&& operator << (Helper&&h, const T& t) {
std::cout << t;
return std::move(h);
}
};
class Debug
{
public:
template<typename T>
friend Helper operator<<(Debug&, const T& t)
{
auto tempTime = std::chrono::system_clock::to_time_t(
std::chrono::system_clock::now() );
auto timeString{ctime(&tempTime)};
timeString = timeString.substr(timeString.find(':') - 2, 8);
std::cout << timeString << " >> " << t;
return Helper{};
}
};
Each time you call operator<<, your code prints the time stamp and \n. And that's the problem. To avoid that, you can print the time stamp in the constructor of Debug, and print \n in the destructor.
class Debug {
public:
Debug() {
auto tempTime = std::chrono::system_clock::to_time_t(
std::chrono::system_clock::now() );
std::string timeString(ctime(&tempTime));
timeString = timeString.substr(timeString.find(':') - 2, 8);
std::cout << timeString;
}
~Debug() {
std::cout << "\n";
}
Debug &operator<<(std::string arg_0) {
std::cout << " >> " << arg_0;
return *this;
}
};
In order to debug types other than string, you make operator<< a template:
template <typename T>
Debug &operator<<(T &&arg_0) {
std::cout << " >> " << std::forward<T>(arg_0);
return *this;
}
I see 2 design problems here:
You try to create stream-like object. It means that it doesn't know, when the line ends, until you send EOL to it. Without this information, it doesn't know when to add prefix to "your" line and print it. Consider the two following situation:
DBG << "foo and" << " bar";
and
DBG << "foo and";
... (a lot of code) ...
DBG << " bar";
They look exactly the same inside your Debug class, because:
DBG << "foo and" << " bar"; == (DBG.operator<<("foo and")).operator<<(" bar");
And this is the same as:
DBG.operator<<("foo and");
DBG.operator<<("bar");
So you have to decide how to define the end of the message you want to print (and when do you want to measure the time: At the beginning or at the end of the message?).
When do you want to flush your stream? You have to send std::endl or std::flush to std::cout to flush it. Sending "\n" does not flush std::cout (this is important difference between std::endl and "\n"). If you do not flush it, it may be printed several minutes/hours later (it will wait in a buffer). On the other hand frequent buffer flushing may be a performance killer in application producing large amount of text.
Try to define how your stream should behave when you send to it "\n", std::endl and std::flush (std::endl should be converted to "\n"+std::flush).
About other questions:
I would use simple template to "transfer" parameter of operator<<() to std::cout. It would allow to use your class for any type that can be printed by std::cout. To make things simpler you can define the operator<<() outside your class, eg.:
template<typename tParam>
Debug &operator<<(Debug& stream, tParam const & myParam)
{
...
return stream;
}

Optionally print to stdout at runtime

I have output in a C++ program that I only want to see if a "verbose" option is specified at runtime. I've found lots of methods to use preprocessor #define statements to control debugging output when compiling, but I can't find any ways to do this at runtime short of wrapping every cout in if(verbose).
In pseudocode, I'd like to transform:
if(verbose)
cout << "Some text: " << variable << endl;
...
if(verbose)
cout << "Other text: " << var << endl;
Into:
if(verbose)
//block cout
cout << "Some text: " << variable << endl;
cout << "Other text: " << var << endl;
Is there some way to optionally redefine cout at runtime so those lines silently print nothing? Better yet would be a more flexible approach that allows some output while blocking others.
You can simply bind a stream object reference to different streams depending on verbose:
ostream& vout = (verbose? cout : nullstream);
Then use vout for all the output that should only appear when verbose.
Of course you need to define nullstream first; that involves defining a streambuf derived class.
I'm not sure whether you're in the process of writing a program, or whether you already have a program you want to disable output for. Generally, when you're writing software with debugging output, you'll want to create some sort of logging class to help you control when output occurs and where it goes (e.g., to a file, to stdout, to stderr, etc.). An example of a simple one would be:
#include <iostream>
class Logger {
public:
Logger(bool enabled) : enabled(enabled) { }
void setEnabled(bool enabled) { this->enabled = enabled; }
template<typename T> Logger& operator<<(T const& t)
{
if (enabled)
std::cout << t;
return *this;
}
// If you'd like manipulator support (e.g., for std::endl)
Logger& operator<<(std::ostream& (*manipulator)(std::ostream&))
{
if (enabled)
std::cout << manipulator;
return *this;
}
private:
bool enabled;
};
int main()
{
Logger log(true);
log << "Hello, " << "World!" << 123; // Prints Hello, World!123
log.setEnabled(false);
log << "Hello, " << "World!" << 123; // Prints nothing
}
Alternatively, you could redirect cout, as others have mentioned, or even just simply redirect your program's output to /dev/null on the command line:
./myProgram > /dev/null

multiple threads writing to std::cout or std::cerr

I have OpenMP threads that write to the console via cout and cerr. This of course is not safe, since output can be interleaved. I could do something like
#pragma omp critical(cerr)
{
cerr << "my variable: " << variable << endl;
}
It would be nicer if could replace cerr with a thread-safe version, similar to the approach explained in the valgrind DRD manual (http://valgrind.org/docs/manual/drd-manual.html#drd-manual.effective-use) which involves deriving a class from std::ostreambuf. Ideally in the end I would just replace cerr with my own threaded cerr, e.g. simply:
tcerr << "my variable: " << variable << endl;
Such a class could print to the console as soon as it encounters an "endl". I do not mind if lines from different threads are interleaved, but each line should come only from one thread.
I do not really understand how all this streaming in C++ works, it is too complicated. Has anybody such a class or can show me how to create such a class for that purpose?
As others pointed out, in C++11, std::cout is thread-safe.
However if you use it like
std::cout << 1 << 2 << 3;
with different threads, the output can still be interleaved, since every << is a new function call which can be preceeded by any function call on another thread.
To avoid interleaving without a #pragma omp critical - which would lock everything - you can do the following:
std::stringstream stream; // #include <sstream> for this
stream << 1 << 2 << 3;
std::cout << stream.str();
The three calls writing 123 to the stream are happening in only one thread to a local, non-shared object, therefore aren't affected by any other threads. Then, there is only one call to the shared output stream std::cout, where the order of items 123 is already fixed, therefore won't get messed up.
You can use an approach similar to a string builder. Create a non-template class that:
offers templated operator<< for insertion into this object
internally builds into a std::ostringstream
dumps the contents on destruction
Rough approach:
class AtomicWriter {
std::ostringstream st;
public:
template <typename T>
AtomicWriter& operator<<(T const& t) {
st << t;
return *this;
}
~AtomicWriter() {
std::string s = st.str();
std::cerr << s;
//fprintf(stderr,"%s", s.c_str());
// write(2,s.c_str(),s.size());
}
};
Use as:
AtomicWriter() << "my variable: " << variable << "\n";
Or in more complex scenarios:
{
AtomicWriter w;
w << "my variables:";
for (auto & v : vars) {
w << ' ' << v;
}
} // now it dumps
You will need to add more overloads if you want manipulators, you can use write better than fprintf for the atomic write in the destructor, or std::cerr, you can generalize so that the destination is passed to the constructor (std::ostream/file descriptor/FILE*),
I don't have enough reputation to post a comment, but I wanted to post my addition to the AtomicWriter class to support std::endl and allow for other streams to be used besides std::cout. Here it is:
class AtomicWriter {
std::ostringstream st;
std::ostream &stream;
public:
AtomicWriter(std::ostream &s=std::cout):stream(s) { }
template <typename T>
AtomicWriter& operator<<(T const& t) {
st << t;
return *this;
}
AtomicWriter& operator<<( std::ostream&(*f)(std::ostream&) ) {
st << f;
return *this;
}
~AtomicWriter() { stream << st.str(); }
};
Put the following code in header file atomic_stream_macro.h
#ifndef atomic_stream_macro_h
#define atomic_stream_macro_h
#include <mutex>
/************************************************************************/
/************************************************************************/
extern std::mutex print_mutex;
#define PRINT_MSG(out,msg) \
{ \
std::unique_lock<std::mutex> lock (print_mutex); \
\
out << __FILE__ << "(" << __LINE__ << ")" << ": " \
<< msg << std::endl; \
}
/************************************************************************/
/************************************************************************/
#endif
Now the macro can be used from a file as follows.
#include <atomic_stream_macro.h>
#include <iostream>
int foo (void)
{
PRINT_MSG (std::cout, "Some " << "Text " << "Here ");
}
Finally, in the main.cxx, declare the mutex.
#include <mutex>
std::mutex print_mutex;
int main (void)
{
// launch threads from here
}
You could do it by inheriting std::basic_streambuf, and override the correct functions to make it threadsafe. Then use this class for your stream objects.

Writing a macro for logging

I'm writing a logging class at the moment. The Logger works with streams and also prints the object which is logging at the moment. Here is the macro:
#define OBJLOG(DL, what) DL <= this->Logger->getDebugLevel() ? *this->Logger << DL << "[" << this->Name << "]: "<< what << std::endl : this->Logger->doNothing();
The pseudo code Variant for better overview:
#define OBJLOG(debuglevel, what) debuglevel <= logger.debuglevel ? logger.log(what) : logger.doNothing()
Is there any way to get around the doNothing function call, like doing nothing at all?
#define OBJLOG(DL, what) do { if(DL <= this->Logger->getDebugLevel()) *this->Logger << DL << "[" << this->Name << "]: "<< what << std::endl; } while(0)
See Why use apparently meaningless do-while and if-else statements in macros? for an explanation. (The do {} while(0) isn't strictly necessary here, but I would prefer not to leak an ostream.)
Also, you should always wrap macro argument uses in parentheses, like:
#define OBJLOG(DL, what) do { if((DL) <= this->Logger->getDebugLevel()) *this->Logger << (DL) << "[" << this->Name << "]: "<< (what) << std::endl; } while(0)
Finally, you should move this code into a function and call that in your macro (if you really insist on using a macro) to avoid evaluating your macro arguments more than once.
Have your logger.log() function return a boolean.
Connect your predicates with an and like this: debuglevel <= logger.debuglevel && logger.log
That should do the trick.
If you want an expression that does nothing, try (void)0.

Is there anyway to write the following as a C++ macro?

my_macro << 1 << "hello world" << blah->getValue() << std::endl;
should expand into:
std::ostringstream oss;
oss << 1 << "hello world" << blah->getValue() << std::endl;
ThreadSafeLogging(oss.str());
#define my_macro my_stream()
class my_stream: public std::ostringstream {
public:
my_stream() {}
~my_stream() {
ThreadSafeLogging(this->str());
}
};
int main() {
my_macro << 1 << "hello world" << std::endl;
}
A temporary of type my_stream is created, which is a subclass of ostringstream. All operations to that temporary work as they would on an ostringstream.
When the statement ends (ie. right after the semicolon on the whole printing operation in main()), the temporary object goes out of scope and is destroyed. The my_stream destructor calls ThreadSafeLogging with the data "collected" previously.
Tested (g++).
Thanks/credits to dingo for pointing out how to simplify the whole thing, so I don't need the overloaded operator<<. Too bad upvotes can't be shared.
Couldn't you just derive from ostream and provide your own thread safe implementation? Then you could just do
myCOutObject << 1 << "hello world" << blah->getValue() << std::endl;
And get the exact same functionality without macros and using C++ properly?
No. The problem is that without using function syntax, a macro is limited to only being replaced where it is.
But if you were willing to use function syntax, you can then replace stuff both before and after the args.
my_macro(1 << "hello world" << blah->getValue() << std::endl);
You could by defining MyMacro as:
#define my_macro(args) std::ostreamstring oss; \
oss << args; \
ThreadSafeLogging(oss.str());
Take a look at google-glog, they do this using a temporary object instanciated with a
LOG(INFO) << "log whatever" << 1;
and they also have other interesting macros such as LOG_IF et al.
Considering you have these lines included somewhere in your code, yes it is possible
#include <iostream>
#include <sstream>
__LINE__ macro is defined by all standart compilers.
So we can use it to generate a variable name wich is different each time you use the macro :)
Here is a new version that is seen as a one-statement instruction only:
(EDITED)
#define Var_(Name, Index) Name##Index
#define Var(Name, Index) Var_(Name, Index)
#define my_macro \
for (struct { int x; std::ostringstream oss; } Var(s, __LINE__) = { 0 }; \
Var(s, __LINE__).x<2; ++Var(s, __LINE__).x) \
if (Var(s, __LINE__).x==1) ThreadSafeLogging(Var(s, __LINE__).oss.str()); \
else Var(s, __LINE__).oss
// So you can use it like this
int main()
{
if (4 != 2)
my_macro << 4 << " hello " << std::endl;
my_macro << 2 << " world !" << std::endl;
}
Developper probably won't need to use this macro twice on same line becasue of simplicity of operator <<. But in case you need this, you can switch the use of __LINE__ by __COUNTER__ (which is non standard!). Thanks to Quuxplusone for this tip
Here's another nasty trick I saw somewhere else. It has a significant disadvantage compared to my other answer: you can't use it twice in the same scope because it declares a variable. However, it may still be interesting for other cases where you want to have somemacro foo run something after foo.
#define my_macro \
std::ostringstream oss; \
for (int x=0; x<2; ++x) \
if (x==1) ThreadSafeLogging(oss.str()); \
else oss
int main() {
my_macro << 1 << "hello world" << std::endl;
}
The logging setup I have is quite similar:
bool ShouldLog(const char* file, size_t line, Priority prio);
class LoggerOutput : public std::stringstream {
public:
LoggerOutput(const char* file, size_t line, Priority prio)
: prio(prio)
{
Prefix(file, line, prio);
}
void Prefix(const char* file, size_t line, Priority prio);
~LoggerOutput() {
Flush();
}
void Flush();
private:
Priority prio;
};
#define LOG(Prio) if (!Logging::ShouldLog(__FILE__, __LINE__, Prio)) {} else Logging::LoggerOutput(__FILE__, __LINE__, Prio)
If your logging is disabled, the ostream is never created and little overhead exists. You can configure logging on file name & line number(s) or priority levels. The ShouldLog function can change between invocations, so you could throttle or limit output. The log output uses two functions to modify itself, Prefix that adds a "file:line: (PRIO) " prefix to the line, and Flush() which both flushes it to the log output as a single command and adds a newline to it. In my implementation it always does, but you can make that conditional if one is not already there.