I am trying to do a simple logging library only for my own. I know there exists several once, but I have not found any header-only, small and very "c++" like logging library which fits into my application.
Currently I have the following syntax:
logger << debug << "A debug message" << end; //debug and end is my custom manipulators
I have implemented all necessary operator<< and it works great, specially when it have backward compatibility with std::ostream. But I wonder, just for efficiency if it is a why to stop evaluate anything if some message should not be logged (after debug in the example)? Making everything after the severity manipulator "disappear"?
Just now do I have the following code in short:
template <typename Type>
Logger & Logger::operator<<(const Type & message)
{
if(this->get_message_level() <= this->get_severity())
{
BOOST_FOREACH(std::ostream* stream, this->_sinks)
{
*stream << message;
}
}
return *this;
}
Logger & Logger::operator<< (Logger & (*pf)(Logger&))
{
return pf(*this);
}
Logger & debug(Logger& logger)
{
logger.lock();
logger.set_severity(7);
//...
return logger;
}
Logger & end(Logger& logger)
{
logger << std::endl;
logger.unlock();
return logger;
}
Thanks in advance.
You could do something as simple as
extern "C" bool want_log;
#define LOG(Arg) do { if (want_log) \
cout << __FILE__ << ":" << __LINE__ ": " << Arg << endl; } while(0)
and use it as LOG("x=" << x)
It can be a bit tricky, depending on what compromizes you're willing to
accept in the syntax. If you really want to support everything that
outputting to an ostream does, then the best you can do (as far as I
know) is a wrapper class, along the lines of:
class Logger
{
std::ostream* myDest;
public:
// Appropriate constructors...
template<typename T>
Logger& operator<<( T const& obj )
{
if ( myDest != NULL )
(*myDest) << obj;
return *this;
}
};
If logging is turned off (Logger::myDest == NULL), none of the
conversion code will execute, but you'll still evaluate each of the
arguments. In my experience, this is not usually an issue, since most
of the arguments are either string literals or a simple variable, but
it's not a total 0 cost. It also has the potential disadvantage that
the propagated type is not std::ostream& (although I've never found
this to be a problem in practice).
A somewhat tricker solution would be to use a macro along the lines of:
#define logger loggerInstance != NULL && (*loggerInstance)
This will still allow most of the actual uses with the same syntax
(because the && operator has very low precedence), but could fail in
cases where someone has tried to be too clever, and embedded the logging
output in a more complicated expression. In addition to not doing the
conversions, the arguments are not even evaluated if logging is turned
off.
Finally, if you accept a different syntax, you can write something like:
#ifndef NDEBUG
#define LOG(argList) logger << argList
#else
#define LOG(argList)
#endif
This requires the user to write LOG("x = " << x), instead of log <<
"x = " << x, and requires recompiling if you want to turn logging on,
but it is the only solution I know which has absolute 0 cost if logging
is turned off.
In my experience, most applications can support the first solution; in a
very few cases, you might want to use the second; and I've never seen an
application where performance required the third.
Note that even with the first, you'll probably want to use a macro to
get the logger instance, in order to automatically insert __FILE__ and
__LINE__, and that in the second, you'll probably still want to use a
wrapper class, in order to ensure a flush in the destructor; if the
application is multithreaded, you'll want the wrapper in all cases, in
order to make the entire sequence of output atomic.
You could check for the severity in the Logger & Logger::operator<< (Logger & (*pf)(Logger&)) operator and just return an "empty" logger that doesn't print anything in that case:
class EmptyLogger : public Logger {
template <typename Type>
Logger & Logger::operator<<(const Type & message) { return *this; }
};
EmptyLogger empty; // Can be global/static, it won't cause any race conditions as it does nothing
Logger & Logger::operator<< (Logger & (*pf)(Logger&))
{
if (logger.get_severity() < 5) // Replace with a proper condition
return empty;
return pf(*this); // What does pf() do? Aren't you returning reference to a temporary object?
}
Take a look at this article in dr dobbs about logging in c++:
http://drdobbs.com/cpp/201804215?pgno=2
This page addresses your particular concern but I'd recommend reading the whole article.
I implemented a logging system based on this article and was really pleased with it.
Related
Let's say I have a project with many functions. For debugging purpopses, I want each one of them print out a diagnostic message (or a few) when called:
int f(int arg) {
cerr << "f() called with argument" << arg << endl;
int ret = 42;
cerr << "f() returned " << ret << endl;
return ret;
}
and so on. In one function, there may be as many as five to six messages printed out on cerr. I want to be able to disable them unless a debug flag (like NDEBUG) is set. One thing I could do is wrap each cerr statement with an if-statement.
#ifdef NDEBUG
const bool DEBUG_ON = true;
#else
const bool DEBUG_ON = false;
#endif
int f(int arg) {
if (DEBUG_ON) {
cerr << "f() called with argument" << arg << endl;
}
int ret = 42;
if (DEBUG_ON) {
cerr << "f() returned " << ret << endl;
}
return ret;
}
But it can get really tedious and, in the end, virtually unreadable with a couple dozens of such statements. My idea was to replace cerr with a custom object with an overloaded << operator which would send any arguments passed to it "into the void" like this:
class NullOutStream {
public:
NullOutStream operator<<(...) {
return *this;
}
};
NullOutStream debug_out;
#ifdef NDEBUG
#define debug_out cerr
#else
#define debug_out debug_out
#endif
Although it works perfectly, it doesn't seem very elegant. Is there a standard/nicer way to accomplish this?
There is no "standard" way to do this. There are many logging/assertion libraries that deal with similar issues, and there are different approaches to solve this. A few things to keep in mind:
It may or may not be desirable to keep the side effects of your log statement (as yours does). For example, if you did something like this:
debug_out << ++i;
This would increment i no matter whether you are in debug mode or not. This is probably desirable in this case. Conversely, if you do this:
debug_out << some_object.expensive_to_string_operation();
This would call expensive_to_string_operation() even when you are not in debug mode. This is probably not desirable in this case.
This would not happen if you used printf-style debug macro, e.g. something like this:
#ifdef NDEBUG
#define logf(...)
#else
#define logf(...) printf(__VA_ARGS__)
#endif
The reason being that when in non-debug mode, the arguments would be removed by the preprocessor.
You may want to do other things before or after each log statement, e.g. record a time stamp, flush a log file etc. It is possible to do this with streams by using destructor tricks, but it is more complicated to implement. It is much easier to do this using a function call, e.g. something like this:
#define log(msg) printf("%s: %s\n", timestamp(), msg)
You may want to record file name / line number with your logs. Again, this is easier to do with a function call than with a stream.
Streams may be better if you want custom formatting by object type - the printf interface doesn't lend itself to that very well.
I would recommend to have a look at some existing logging libraries to get an idea of different approaches. I suggest looking at Google's glog library because it has an interesting combination of using streams while retaining the ability to do 'per call' things (e.g. record time stamps, line numbers etc).
I'm working on a small C++11 application (an SDL2 game) and i'm having a hard time "porting" some of my object-oriented knowledge from PHP/Java to C++. For example, in order to create an elegant error logging approach, i would create a class with various adapters and centralize logging there. I already did that in C++, but i have no idea on how my classes should be using the Logger class.
In Java and PHP, i would use dependency injection, and put the Logger as a class member variable in them. But in C++, what's the proper way? I don't really think that going static would be nice.
Oh man.
To me logging is similar to date/time handling: the basic case is trivial, but anything more than trivial is extremely complicated: no middle ground.
Let me advise you to look into a general purpose logging library such as Pantheios or Boost.Log.
The reason why I advice for this approach as opposed to making "your own effort", is that I know first hand how the "logging situation" goes:
you start with a simple "write to file" or "write to screen"
then you need to also log to another device
then you want to filter out severity levels
then you want to send your logs via pipes
then you want to turn off logging
And it all becomes very, very difficult, and the logging classes start polluting your code.
So, like I said: based on my limited experience, I would encourage you to look into the suggested libraries.
Good luck.
Edit: Boost.Log examples
Just for completeness of the post (refer to page for details).
Trivial case:
#include <boost/log/trivial.hpp>
int main(int, char*[]) {
BOOST_LOG_TRIVIAL(trace) << "A trace severity message";
BOOST_LOG_TRIVIAL(debug) << "A debug severity message";
BOOST_LOG_TRIVIAL(info) << "An informational severity message";
BOOST_LOG_TRIVIAL(warning) << "A warning severity message";
BOOST_LOG_TRIVIAL(error) << "An error severity message";
BOOST_LOG_TRIVIAL(fatal) << "A fatal severity message";
return 0;
}
One approach would be to pass a reference to a logger object around function calls. However, logging is a sort of an orthogonal aspect to application logic, so that explicitly passing that logger and having it as a member quickly becomes a nuisance and only adds artificial complexity.
I prefer having one global logger in the application. Modules can create its own loggers as child loggers of the main logger forming a hierarchy (I think this is similar to Python logging module) and control its output sink and verbosity independently if necessary.
I always use something like this:
class Log
{
public:
Log()
: m_filename( "dafault.log" )
{}
// if you wanna give other names eventually...
Log( const std::string & p_filename )
: m_filename( p_filename )
{}
virtual ~Log()
{
// implement your writeToFile() with std::ofstream
writeToFile( m_filename, m_stream, true );
}
template< typename T >
Log & operator<<( const T & p_value )
{
m_stream << p_value;
return *this;
}
private:
std::string m_filename;
std::ostringstream m_stream;
};
So this way I am able to log like this:
Log() << "My message in the log with numbers " << 1 << 2 << 3 << " and so on...";
Log( "other.log" ) << "Log in another file eventually...";
My current approach is to use a kind of dependency injection, using C++ strengths instead of magic. It does not require on anything specific to C++11 (except that __thread which is an extension could be replaced by thread_local if you wished to be Standard).
class LoggerEngine {
public:
static LoggerEngine* Current() { return CurrentE; }
virtual bool isActive(Level) { return true; }
virtual void log(char const* function,
char const* file,
int line,
std::string message) = 0;
// cuz' decorators rock
LoggerEngine* previous() const { return _previous; }
protected:
LoggerEngine(): _previous(CurrentE) { CurrentE = this; }
~LoggerEngine() { CurrentE = _previous; }
private:
static __thread LoggerEngine* CurrentE;
LoggerEngine* const _previous;
}; // class LoggerEngine
// in some .cpp file:
__thread LoggerEngine* LoggerEngine::CurrentE = 0;
And then, provide macros (to capture function, file and line):
#define LOG(L_, Message_) \
do { if (LoggerEngine* e = LoggerEngine::Current() and e->isActive(L_)) { \
std::ostringstream _28974986589657165; \
_28974986589657165 << Message_; \
e->log(__func__, __FILE__, __LINE__, _28974986589657165.str()); \
}} while(0);
However it could certainly be made better by using shims instead, because even though it prevents any computation in case the level is not active it still requires formatting of the full message (and the necessary memory allocation) even if it is going to truncate the message anyway (for example because it uses fixed-size buffers) and does not easily allow customization of the formatting.
The combination of stacking engines (and popping them off automatically using RAII) with thread-local behavior is really pretty neat. Most code only ever see an interface, without having to thread it by (cool when you have 4/5 different engines), and any level of the stack can switch the engine to something more appropriate.
There is one caveat, as is, no logging occurs before a first Engine is defined. For this reason I've often thought of defaulting to writing to the console if no engine is setup but... I've mostly changed my style to avoid computation before main is called since I cannot dependency-inject during this phase (and it's awkward if an exception fires...)
Usage is like this:
void benchmark() {
LOG(INFO, "Hello, World!");
Timer t;
{
MySinkLogger const _; (void)_; // a logger with "isActive" always false
for (size_t i = 0; i != 10000; ++i) {
LOG(INFO, "Flood!");
}
}
LOG(INFO, "Elapsed: " << t.elapsed());
}
int main() {
MyFileLoggerEngine const _("somefile.log"); (void)_; // a file logger
benchmark();
}
And normally this could create a file "somefile.log" containing:
2013-10-03T18:38:04.645512 mylaptop INFO <test.cpp#42> Hello, World!
2013-10-03T18:38:04.865765 mylaptop INFO <test.cpp#47> Elapsed: 0.220213s
I am making a smallish project, total of about 3-4 people. I want to have a solid way of debugging the application, by logs for example. Are there any good resources on how to structure it and such? I've heard a lot from project managers that a good logging feature is critical to each project, but I'm not sure how to do it.
I found this Dr. Dobb's article, Logging In C++, very useful regarding this subject.
Also on Dr. Dobb's: A Highly Configurable Logging Framework In C++
If all you want is a dead simple thread safe logging class which always outputs to stderr then you could use this class I wrote:
#ifndef _LOGGER_HPP_
#define _LOGGER_HPP_
#include <iostream>
#include <sstream>
/* consider adding boost thread id since we'll want to know whose writting and
* won't want to repeat it for every single call */
/* consider adding policy class to allow users to redirect logging to specific
* files via the command line
*/
enum loglevel_e
{logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4};
class logIt
{
public:
logIt(loglevel_e _loglevel = logERROR) {
_buffer << _loglevel << " :"
<< std::string(
_loglevel > logDEBUG
? (_loglevel - logDEBUG) * 4
: 1
, ' ');
}
template <typename T>
logIt & operator<<(T const & value)
{
_buffer << value;
return *this;
}
~logIt()
{
_buffer << std::endl;
// This is atomic according to the POSIX standard
// http://www.gnu.org/s/libc/manual/html_node/Streams-and-Threads.html
std::cerr << _buffer.str();
}
private:
std::ostringstream _buffer;
};
extern loglevel_e loglevel;
#define log(level) \
if (level > loglevel) ; \
else logIt(level)
#endif
Use it like this:
// define and turn off for the rest of the test suite
loglevel_e loglevel = logERROR;
void logTest(void) {
loglevel_e loglevel_save = loglevel;
loglevel = logDEBUG4;
log(logINFO) << "foo " << "bar " << "baz";
int count = 3;
log(logDEBUG) << "A loop with " << count << " iterations";
for (int i = 0; i != count; ++i)
{
log(logDEBUG1) << "the counter i = " << i;
log(logDEBUG2) << "the counter i = " << i;
}
loglevel = loglevel_save;
}
If you are asking about logging frameworks and you work in C++, check out Apache's log4cxx. It takes a few moments to understand the architecture, but once you did, you realize that it is a good balance of flexibility, ease of use and (as they say) performance.
log4cxx has a very flexible configuration by witch you can control, without recompiling, where the output goes to (file / rotating file / console/etc.), the debugging level of subcomponents (e.g. you want to focus on a particular class / component so you set it to DEBUG level while the rest is on INFO), format of log entries etc.
If you are asking about general guidelines on how do logging, I haven't seen such (not that I actually looked for). I think this is mainly empiric - you decide what info is needed on each logging level like INFO, DEBUG etc., and you refine it according to your and your client's needs (don't forget that your client could also be a customer of the log, depending on your project).
Depends on what you mean by "logging". One form is simply to provide a method for printing the contents of some object to an output stream. For an object of type ClassName this entails writing an insertion operator for the class:
std::ostream &operator<< (std::ostream &stream, const ClassName & obj) {
// Implementation elided
}
With this at hand you can print an object of type ClassName to an output stream. This can be quite useful, so useful that some organizations require that every class implement such a method.
I am looking for a portable way to implement lazy evaluation in C++ for logging class.
Let's say that I have a simple logging function like
void syslog(int priority, const char *format, ...);
then in syslog() function we can do:
if (priority < current_priority)
return;
so we never actually call the formatting function (sprintf).
On the other hand, if we use logging stream like
log << LOG_NOTICE << "test " << 123;
all the formating is always executed, which may take a lot of time.
Is there any possibility to actually use all the goodies of ostream (like custom << operator for classes, type safety, elegant syntax...) in a way that the formating is executed AFTER the logging level is checked ?
This looks like something that could be handled with expression templates. Beware, however, that expression templates can be decidedly non-trivial to implement.
The general idea of how they work is that the operators just build up a temporary object, and you pass that temporary object to your logging object. The logging object would look at the logging level and decide whether to carry out the actions embodied in the temporary object, or just discard it.
What I've done in our apps is to return a boost::iostreams::null_stream in the case where the logging level filters that statement. That works reasonably well, but will still call all << operators.
If the log level is set at compile time, you could switch to an object with a null << operator.
Otherwise, it's expression templates as Jerry said.
The easiest and most straight-forward way is to simply move the check outside of the formatting:
MyLogger log; // Probably a global variable or similar.
if (log.notice())
log << "notified!\n" << some_function("which takes forever to compute"
" and which it is impossible to elide if the check is inside log's"
" op<< or similar");
if (log.warn()) {
log << "warned!\n";
T x;
longer_code_computing(value_for, x); // easily separate out this logic
log << x;
}
If you really wanted to shorten the common case, you could use a macro:
#define LOG_NOTICE(logger) if (logger.notice()) logger <<
LOG_NOTICE(log) << "foo\n";
// instead of:
if (log.notice()) log << "foo\n";
But the savings is marginal.
One possible MyLogger:
struct MyLogger {
int priority_threshold;
bool notice() const { return notice_priority < current_priority; }
bool warn() const { return warn_priority < current_priority; }
bool etc() const { return etc_priority < current_priority; }
template<class T>
MyLogger& operator<<(T const &x) {
do_something_with(x);
return *this;
}
};
The problem here is mixing iostream-style operator overloading with a printf-like logging function – specifically translating manipulators and formatting flags/fields from iostreams into a format string. You could write to a stringstream and then chunk that to your syslog function, or try something fancier. The above MyLogger works easiest if it also contains an ostream reference to which it can forward, but you'll need a few more op<< overloads for iomanips (e.g. endl) if you do that.
For mine I made a debug_ostream class which has templated << operators. These operators check the debug level before calling the real operator.
You will need to define non-template overrides for const char* and std::ostream& (*x)(std::ostream&) because otherwise those don't work. I'm not sure why.
With inlining and high enough optimization levels the compiler will turn the whole output line into a single check of the debug level instead of one per output item.
I should add to this that this doesn't solve the original problem. For example if part of the debug line is to call an expensive function to get a value for output, that function will still be called. My solution only skips the formatting overhead.
So I have a C++ program, that normally when it executes writes out things to a log file. This is done using an fstream. However, now I want to include functionality to turn the logging off. Essentially, my code looks like this:
bool isLogging;
fstream* logFilePtr;
throughout my code, there are a bunch of statements like:
(*logFilePtr) << " Kernel call time in seconds: " << kTime << endl;
...
Now, if the "isLogging" is true, I don't want these to print. I could just go surround them with a bunch of if statements, but I'd prefer something cleaner than that. I thought there was some way to take a C++ stream and redirect it to point to "nothing" so that when the << operator is used, nothing will print.
Does anyone know how to redirect the stream, or have any other ideas on how to handle this in an elegant way?
Thanks,
Colin
You could wrap it up in a class.
class Log {
Log (fstream &s) : stream(s), enabled(false) { }
void Enable () { enabled = true; }
void Disable () { enabled = false; }
template<class T>
Log &operator<< (T const& rhs) {
if (enabled) stream << rhs;
return *this;
}
private:
fstream &stream;
bool enabled;
};
this isn't tested .. but the basic idea should be there.
Take a look at rdbuf member function. You can create a discarding stream buffer and associate it with your stream.
struct nullbuf: std::streambuf
{
int overflow(int c) { return traits_type::not_eof(c); }
};
std::iostream doesn't allow OS-level redirection, however, you can share std::streambufs between std::iostreams:
int main() {
// redirect stdout to stderr:
std::streambuf * const oldstdout = std::cout.rdbuf();
std::cout.rdbuf( std::cerr.rdbuf() );
// test
std::cout << "Hello ";
std::cerr << "World" << std::endl;
// re-set, so streambufs are properly deleted:
std::cout.rdbuf( oldstdout );
// test
std::cout << "Hello ";
std::cerr << "World" << std::endl;
return 0;
}
This way, you can redirect logging to somewhere else (e.g. "/dev/null" :), or, if you follow avakar's answer, use nullbuf.
platform? if you are under unix you can write the file to /dev/null
I use POCO library's logging feature. It supports configuring channels - console, file, both. Configuring format of output and logging levels (trace, debug, error etc). I then surround the logging functionality with functions such as
inline void logError(const std::string & str)
{
#ifdef COMPILE_ERROR_LOGGING
g_pMyPocoLogger->error(str);
#endif
}
You can choose not to use the library but I still recommend surrounding your logging with a wrapper.
std::ostream& Debug(int level) {
std::clog.clear(levell <= shown_level ? std::ios_base::goodbit: std::ios_base::badbit);
return std::clog;
}
From comp.lang.c++.
Under "other ideas on how to handle this":
Use the state pattern to eliminate the need for the if checks around all code.
Use the policy pattern (compile time strategy pattern) with a Logging policy object.