I am in progress of refactoring a C++ application of mine. Before I used a macro like
LOG("something interesting") // 1
LOG("something ended") // 2
LOG("foo: " << bar) // 3
My idea now was to write a Log class like so:
Log(std::string _init_message):
init_message(_init_message)
{ PrintLogLine(init_message + " ...");}
~Log()
{ PrintLogLine(init_message + " done.");}
to get "automatic" logging of specific actions (i.e. when they start, stop + additionally timings etc.) when I use it like
void ActionXYZ() {
Log log("xyz");
// do stuff
}
Where I am struggling is in defining a way to make it work for case 3). In Java I could use a method which takes one String argument since the compiler takes care of automatically string building. What possibilities do I have in C++?
Can I make it work so that I can use it like either one option?
// in "do stuff"
log("foo:" + bar); // OR
log << "foo:" << bar;
As I've mentioned in the comments, you could use Boost.Format. It also helps with the problem of int-to-string conversions, etc. It might get a bit verbose, though — to avoid calling .str() to call std::string constructor, you could make one that accepts boost::format directly.
Log log(boost::format("foo %1% bar") % 42); // with Log(boost::format)
Log log((boost::format("foo %1% bar") % 42).str()); // with only Log(std::string)
Refer to Boost.Format documentation for details.
Two immediate possibilities come to mind. The first is to take advantage of std::string appending:
Log log(std::string("foo:") + bar);
The second is to make more log constructors that take additional parameters:
Log log("foo:", bar);
You really should consider using Boost.Log for your logging. Logging can be a complex thing; it's useful to get a fully formed implementation.
You can create a logging class that inherits from std::strstream.
class Mstream : public std::strstream
{
public:
Mstream() : std::strstream(Buffer = new char[BUFLEN], BUFLEN, ios::out);
ostream& endf(ostream& s);
void Write();
private:
char* Buffer;
};
Now you can log output as,
Mstream m;
m <<"Foo"<<s<<endf;
In endf(ostream& s) you can cast ostream to Mstream and call the Write(). In Write(), you format the output and print it to console or to a file.
Related
I've created an fstream object to write info to files.
I write strings to the new file like
fStreamObject << "New message.\n";
because I want each << to print a string to the next line.
I want to be able to set a property and make a call like
fstreamObject << "New message.";
which will write the string to the next line.
Are there flags/settings for fstream objects that allows this to be done?
I've seen the different file modes (i.e. ofstream::in, ofstream::out, etc.), but I couldn't find one that auto writes to a new line. Also, I'm not looking to write my own solution. I want to be able to use a built in feature.
No, there are no readily configurable capabilities of that sort within the standard streams.
You may have to subclass the stream type and fiddle with operator<< to get this to work the way you want, or do it with a helper function of some description:
fstreamObject << nl("New message.");
(but that's hardly easier than just having the \n in there (for a string, anyway).
It depends on what you mean by "setting the stream". If we consider this to be fairly broad then the answer happens to be "yes"!
Here is how:
Create a stream buffer which inserts a newline every time it is flushed, i.e., when sync() is called. Otherwise it just forwards characters.
Change the file stream's stream buffer to use this stream buffer filtering to the file stream's stream buffer.
Set the flag std::ios_base::unitbuf which causes a flush after every [properly written] output operation.
Here are is the example code to do just that:
#include <iostream>
class newlinebuf
: public std::streambuf {
std::ostream* stream;
std::streambuf* sbuf;
int overflow(int c) { return this->sbuf->sputc(c); }
int sync() {
return (this->sbuf->sputc('\n') == std::char_traits::eof()
|| this->sbuf->pubsync() == -1)? -1: 0;
}
public:
newlinebuf(std::ostream& stream)
: stream(&stream)
, sbuf(stream.rdbuf(this)) {
stream << std::unitbuf;
}
~newlinebuf() { this->stream->rdbuf(this->sbuf); }
};
int main() {
newlinebuf sbuf(std::cout);
std::cout << "hello" << "world";
}
Although this approach work, I would recommend against using it! On problem is that all composite output operators, i.e., those using multiple output operators to do their work, will cause multiple newlines. I'm not aware of anything which can be done to prevent this behavior. There isn't anything in the standard library which enables just configuring the stream to do this: you'll need to insert the newline somehow.
No, the C++ streams do not allow that.
There is no way to decide where one insertion stops and the next starts.
For example for custom types, their stream-inserters are often implemented as calls to other stream-inserters and member-functions.
The only things you can do, is write your own class, which delegates to a stream of your choosing, and does that.
That's of strictly limited utiliy though.
struct alwaysenter {
std::ostream& o;
template<class X> alwaysenter& operator<<(X&& x) {
o<<std::forward<X>(x);
return *this;
}
};
I need an interface to write short messages to a log file, the messages often contains multiple parts such as an identifier together with a value.
In order to do this I've created a class that handles a lot of minor stuff such as creating filenames with timestamps and so on, although I don't want to use a variable argument list (int nargs, ...), so I thought my best option was to pass a std::stringstream to the write function instead.
I want to be able to write these calls as one-liners and not having to create a std::stringstream every time I need to do this, therefore I created a static member function to return a stringstream object I could use with my write function, although for some reason it doesn't work.
MyClass.h
class MyClass {
public:
static std::stringstream& stream();
void write(std::ostream& datastream);
private:
static std::stringstream* _stringstream;
};
MyClass.cpp
std::stringstream* MyClass::_stringstream = new std::stringstream();
std::stringstream& MyClass::stream() {
MyClass::_stringstream->str(std::string());
return *MyClass::_stringstream;
}
void MyClass::write(std::string data) {
this->_fhandle << data << std::endl;
}
void MyClass::write(std::ostream& datastream) {
std::string data = dynamic_cast<std::ostringstream&>(datastream).str();
this->write(data);
}
main.cpp
MyClass* info = new MyClass();
info->write("Hello, world");
info->write(MyClass::stream() << "Lorem" << ", " << "ipsum");
info->write(MyClass::stream() << "dolor sit" << " amet");
The code compiles, but when executing the application I get a std::bad_cast exception...
That's because you are creating an std::stringstream, which
doesn't derive from an std::ostringstream. Just create an
std::ostringstream, and the bad_cast should disappear.
Having said that, reusing the std::ostringstream many times
like this is generally not a good idea; the iostream classes are
full of state, which will not be reset between each use. It's
better to create new instance each time. (The classical
solution for this sort of thing is to create a copiable wrapper
class, which forwards to an std::ostream. An instance of this
is returned by info->write(), so you can write info->write() << "Hello, world" ....)
I found this question answered for Python, Java, Linux script, but not C++:
I'd like to write all outputs of my C++ program to both the terminal and an output file. Using something like this:
int main ()
{
freopen ("myfile.txt","w",stdout);
cout<< "Let's try this";
fclose (stdout);
return 0;
}
outputs it to only the output file named "myfile.txt", and prevents it from showing on the terminal. How can I make it output to both simultaneously? I use visual studio 2010 express (if that would make any difference).
Thanks in advance!
Possible solution: use a static stream cout-like object to write both to cout and a file.
Rough example:
struct LogStream
{
template<typename T> LogStream& operator<<(const T& mValue)
{
std::cout << mValue;
someLogStream << mValue;
}
};
inline LogStream& lo() { static LogStream l; return l; }
int main()
{
lo() << "hello!";
return 0;
}
You will probably need to explicitly handle stream manipulators, though.
Here is my library implementation.
There is no built in way to do this in one step. You have to write the data to a file and then write the data out on screen in two steps.
You can write a function that takes in the data and the filename and does this for you, to save you time, some sort of logging function.
I have a method to do this, and it is based on a subscriber model.
In this model all your logging goes to a "logging" manager and you then have "subscribers" that decide what to do with the messages. Messages have topics (for me a number) and loggers subscribe to one or more topic.
For your purpose, you create 2 subscribers, one that outputs to the file and one that outputs to the console.
In the logic of your code you simply output the message, and at this level not need to know what is going to be done with it. In my model though you can check first if there are any "listeners" as this is considered cheaper than constructing and outputting messages that will only end up in /dev/null (well you know what I mean).
One way to do this would be to write a small wrapper to do this, for example:
class DoubleOutput
{
public:
// Open the file in the constructor or any other method
DoubleOutput(const std::string &filename);
// ...
// Write to both the file and the stream here
template <typename T>
friend DoubleOutput & operator<<(const T& file);
// ...
private:
FILE *file;
}
To have a class instead of a function makes you use the RAII idiom (https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization)
To use it:
DoubleOutput mystream("myfile");
mystream << "Hello World";
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.
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.