I have the following code which is redirecting my std::cout output to a log file.
std::ofstream out("out.txt");
std::streambuf *coutbuf = std::cout.rdbuf(); //save old buf
std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt!
Now what I want is that whenever a newline is occurring, then the current time stamp will be written to the file.
I know I can achive this with:
std::cout << getTime() << "printing data" << std::endl;
But what I want is that of std::cout taking care of it automatically somehow. Is that possible?
I assume, that You want print the TimeStamp, if the first character of the next line appears in the output.
Take a new class and inherit it from std::streambuf and connect it in the same way You do with the filebuf. If a newline-charater appears store this event in the object. Appears another character add the timestamp to the stream.
I wrote an example which use the RAII idiom for connecting the streambuf.
class AddTimeStamp : public std::streambuf
{
public:
AddTimeStamp( std::basic_ios< char >& out )
: out_( out )
, sink_()
, newline_( true )
{
sink_ = out_.rdbuf( this );
assert( sink_ );
}
~AddTimeStamp()
{
out_.rdbuf( sink_ );
}
protected:
int_type overflow( int_type m = traits_type::eof() )
{
if( traits_type::eq_int_type( m, traits_type::eof() ) )
return sink_->pubsync() == -1 ? m: traits_type::not_eof(m);
if( newline_ )
{ // -- add timestamp here
std::ostream str( sink_ );
if( !(str << getTime()) ) // add perhaps a seperator " "
return traits_type::eof(); // Error
}
newline_ = traits_type::to_char_type( m ) == '\n';
return sink_->sputc( m );
}
private:
AddTimeStamp( const AddTimeStamp& );
AddTimeStamp& operator=( const AddTimeStamp& ); // not copyable
// -- Members
std::basic_ios< char >& out_;
std::streambuf* sink_;
bool newline_;
};
call an object of this class in following way:
// some initialisation ..
{
AddTimeStamp ats( cout ); // timestamp is active
// every output to 'cout' will start with a 'getTime()' now
// ...
} // restore the old streambuf in the destructor of AddTimeStamp
That's a hack from a different point.
When you run the program, pipe the output into awk, and add there the time stamp. The command:
<program> | awk '{print strftime()" "$0}' > logfile
If you are using windows, you can download gawk from this website.
You can format the time printed by strftime. More data on that can be found in the manual
You want something like:
ostream & addTime() {
std::cout << getTime();
return std::cout;
and use it like this:
addTime() << "printing data" << std::endl;
try something like the following (it's just an abstract, I didn't test it):
class logger : ostream
{
bool line = true;
public:
template<typename T> ostream& operator<< (T somedata)
{
if (line)
ostream << getTime();
ostream << somedata;
line = somedata == std::endl;
}
}
Related
Suppose that I want to create a stream that would perform an action at the end of the statement, so that
myStream << "Hello, " << "World!";
would print "Hello, World!\n" in one shot. Not "Hello, \nWorld!\n" and not "Hello, World!", but "Hello, World\n", as if ; would trigger appending \n and flushing the buffers.
The rationale for that is a stream class that writes to both stdout and a logfile, with the logfile entries having certain prefixes and suffixes.
For example, if my target was HTML I would want this code:
myStream << "Hello, " << "World!";
myStream << "Good bye, " << "cruel World!";
to print like this:
<p>Hello, World!</p>
<p>Good bye, cruel World!</p>
and not like this:
<p>Hello, </p><p>World!</p>
<p>Good bye, </p><p>cruel World!</p>
Now, if I implement LogStream sort of like this:
LogStream & LogStream::operator<<( const std::string & text );
I won't be able to distinguish between << in the middle of the statements from the ones in the beginning/ending of the statements.
If I implement LogStream sort of like this:
LogStream LogStream::operator<<( const std::string & text );
and try to massage the input in the destructor I would get multiple destructors at once at the end of the block.
Finally, I can implement this my requiring endl at the end of each statement, but I'd rather not bother the caller with the necessity to do so.
Thus the question: how one implements such a stream in a caller-transparent fashion?
I implemented something like this once for a custom logging system. I created a class that buffered input and then its destructor flushed the buffer to my log file.
For example:
#include <iostream>
#include <sstream>
#include <string>
class LogStream
{
private:
std::stringstream m_ss;
void flush()
{
const std::string &s = m_ss.str();
if (s.length() > 0)
{
std::cout << s << std::endl;
logfile << "<p>" << s << "</p>" << std::endl;
}
}
public:
LogStream() {}
~LogStream()
{
flush();
}
template <typename T>
LogStream& operator<<(const T &t)
{
m_ss << t;
return *this;
}
template <typename T>
LogStream& operator<<( std::ostream& (*fp)(std::ostream&) )
{
// TODO: if fp is std::endl, write to log and reset m_ss
fp(m_ss);
return *this;
}
void WriteToLogAndReset()
{
flush();
m_ss.str(std::string());
m_ss.clear();
}
};
For single statements that flush on the final ;, each message would use a new instance of the class:
LogStream() << "Hello, " << "World!";
LogStream() << "Good bye, " << "cruel World!";
To allow multiple statements to write to a single message, create the object and do not let it go out of scope until the last statement is done:
{
LogStream myStream;
myStream << "Hello, ";
myStream << "World!";
}
{
LogStream myStream;
myStream << "Good bye, ";
myStream << "cruel World!";
}
To reuse an existing instance for multiple messages, tell it to flush and reset in between each message:
{
LogStream myStream;
myStream << "Hello, " << "World!";
myStream.WriteToLogAndReset();
myStream << "Good bye, " << "cruel World!";
}
I like this approach because it gives the caller more flexibility in deciding when each message is ready to be written to the log file. For instance, I use this to send multiple values to a single log message where those values are obtained from decision-making code branches. This way, I can stream some values, make some decisions, stream some more values, etc and then send the completed message to the log.
The line:
myStream << "Hello, " << "World!";
Is actually multiple statements. It's equivalent to:
ostream& result = myStream << "Hello, ";
result << "World!";
There are some tricks to do what you want by returning an unnamed temporary object (which are destroyed at the end of the full-expression). Here is some example code.
I have a little code that I haven't gotten round to doing anything constructive with that I think is doing what you're asking.
It works by using a proxy class (log_buffer) to build up the string in a std::stringstream object. At the end of the expression the log_buffer proxy object calls the main log_writer
object to process the whole line contained in the std::stringstream.
class log_writer
{
// ultimate destination
std::ostream* sink = nullptr;
// proxy class to do the << << << chaining
struct log_buffer
{
log_writer* lw;
std::stringstream ss;
void swap(log_buffer& lb)
{
if(&lb !=this)
{
std::swap(lw, lb.lw);
std::swap(ss, lb.ss);
}
}
log_buffer(log_writer& lw): lw(&lw) {}
log_buffer(log_buffer&& lb): lw(lb.lw), ss(std::move(lb.ss)) { lb.lw = nullptr; }
log_buffer(log_buffer const&) = delete;
log_buffer& operator=(log_buffer&& lb)
{
swap(lb);
return *this;
}
log_buffer& operator=(log_buffer const&) = delete;
// update the log_writer after the last call to << << <<
~log_buffer() { if(lw) lw->add_line(ss); }
template<typename DataType>
log_buffer operator<<(DataType const& t)
{
ss << t;
return std::move(*this);
}
};
void swap(log_writer& lw)
{
if(&lw != this)
{
std::swap(sink, lw.sink);
}
}
public:
log_writer(std::ostream& sink): sink(&sink) {}
log_writer(log_writer&& lw): sink(lw.sink) { lw.sink = nullptr; }
log_writer(log_writer const&) = delete;
log_writer& operator=(log_writer&& lw)
{
swap(lw);
return *this;
}
log_writer& operator=(log_writer const&) = delete;
// output the final line
void add_line(std::stringstream& ss)
{
// Do any special line formatting here
if(sink) (*sink) << ss.str() << std::endl;
}
template<typename DataType>
struct log_buffer operator<<(DataType const& data)
{
return std::move(log_buffer(*this) << data);
}
};
int main()
{
std::ofstream ofs("test.log");
log_writer lw1(ofs);
log_writer lw2(std::cout);
lw1 << "lw1 " << 2.93 << " A";
lw2 << "lw2 " << 3.14 << " B";
std::swap(lw1, lw2);
lw1 << "lw1 " << 2.93 << " C";
lw2 << "lw2 " << 3.14 << " D";
}
I call the function write in a loop. I need to append several lines.
I pass
std::fstream file(filename);
to
write(info, &file);
The following code doesn't append new line character, or at least Notepad++ does not display it.(i get just a whitespace) :
void IO::write(const std::string& name, std::iostream* stream)
{
(*stream) << "usr" << name << " === " << "\n";
}
What is wrong? How to append the new line to the text file?
To elaborate on my rather harsh comment, there is nothing wrong with your newline, but...
...use the correct types...
#include <iostream>
#include <fstream>
// ...
std::ofstream file( filename );
// ...
...and if you want to print info to the stream, just do it instead of going through some function...
// ...
file << "usr" << info << " === " << "\n";
// ...
...if you really want to make it a function, at least use references and the proper types...
void IO::write( std::ostream & stream, const std::string & name )
{
stream << "usr" << name << " === \n";
}
// ...
IO::write( file, info );
// ...
...but the "traditional" way of doing output in C++ is to overload the operator<< for the class in question, and have the implementation for printing an instance sit right alongside the class member implementations instead of going through C-style functions...
class MyClass
{
// ...
friend std::ostream & operator<<( std::ostream & stream, const MyClass & obj );
// ...
};
std::ostream & operator<<( std::ostream & stream, const MyClass & obj )
{
stream << "usr" << obj.name << " ===\n";
return stream;
}
// ...
MyClass mine;
file << "Hello\n" << mine << 42 << "\n";
I would also recommend that you use std::endl rather than "\n". std::endl flushs the file, "\n" does not.
After file is flushed (std::endl used or file closed). Try different editors to be sure, but end of line should be visible.
Jean
I created my own std::cout-like object that writes both to std::cout and to a log file.
I'm currently defining it like this in a header file, but I'm getting unused variable warnings.
Header file <MyLib/Log.h>
static LOut { };
static LOut lo;
template<typename T> inline LOut& operator<<(LOut& mLOut, const T& mValue)
{
std::string str{toStr(mValue)};
std::cout << str;
getLogStream() << str;
return mLOut;
}
Usage:
#include <MyLib/Log.h>
...
lo << "hello!" << std::endl;
Should lo be static? Should lo be extern?
Kudos for explaining the correct way of declaring a cout-like object and showing how the main standard library implementations do it.
Edit: by cout-like object, I mean a global variable that is always available after including the corresponding header.
std::cout is simply declared as follows:
namespace std {
extern ostream cout;
}
It is a regular global variable; you can do the same thing yourself. Put an extern declaration of your variable in a header; then define the same variable in a source file and link it to your application:
// mylog.h
extern MyLog mylog;
// mylog.cpp
MyLog mylog(someparams);
First, I'm not too sure what you mean be a cout-like object?
Perhaps an std::ostream.
Anyway, the usual way of doing this is to use a filtering
streambuf. Just write a streambuf which forwards to a log file,
in addition to the usual place, and insert it where ever you
want:
class LoggingOutputStreambuf : public std::streambuf
{
std::streambuf* myDest;
std::ofstreambuf myLogFile;
std::ostream* myOwner;
protected:
int overflow( int ch )
{
myLogFile.sputc( ch ); // ignores errors...
return myDest->sputc( ch );
}
public:
LoggingOutputStreambuf(
std::streambuf* dest,
std::string const& logfileName )
: myDest( dest )
, myLogFile( logfileName.c_str(), std::ios_base::out )
, myOwner( nullptr )
{
if ( !myLogFile.is_open() ) {
// Some error handling...
}
}
LoggingOutputStreambuf(
std::ostream& dest,
std::string const& logfileName )
: LoggingOutputStreambuf( dest.rdbuf(), logfileName )
{
dest.rdbuf( this );
myOwner = &dest;
}
~LoggingOutputStreambuf()
{
if ( myOwner != nullptr ) {
myOwner->rdbuf( myDest );
}
}
};
(This is C++11, but it shouldn't be hard to modify it for
C++03.)
To use, you could use something like:
LoggingOutputStreambuf logger( std::cout );
// ...
All output to std::cout will be logged until logger goes out
of scope.
In practice, you'll likely use something more complicated than a
filebuf for logging, since you may want to insert time stamps
at the start of each line, or systematically flush at the end of
each line. (Filtering streambufs can take care of those issues
as well.)
std::cout-like object that writes both to std::cout and to a log file
Maybe boost.iostreams would be sufficient?
#include <iostream>
#include <fstream>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/tee.hpp>
namespace io = boost::iostreams;
int main()
{
typedef io::tee_device<std::ostream, std::ofstream> teedev;
typedef io::stream<teedev> LOut;
std::ofstream outfile("test.txt");
teedev logtee(std::cout, outfile);
LOut mLOut(logtee);
mLOut << "hello!" << std::endl;
}
Simply sending the input value right out to cout didn't work for me, because I wanted to add headers and info to the log output.
Also, I had my static Debug class in which to wrap the Log stream.
This is the way I managed to do this, I hope it's useful. I'm somehow a newbye to c++, so feel free to tell me if something is wrong :)
#include <iostream>
#include <sstream>
#include <ostream>
enum class DebugLevel {
INFO,
WARNING,
ERROR
};
class Debug {
public:
/* other Debug class methods/properties
...
*/
// out stream object
static struct OutStream {
std::ostringstream stream;
DebugLevel level = DebugLevel::INFO;
public:
// here you can add parameters to the object, every line log
OutStream& operator()(DebugLevel l) {
level = l;
return *this;
}
// this overload receive the single values to append via <<
template<typename T>
OutStream& operator<<(T&& value) {
stream << value;
return *this;
}
// this overload intercept std::endl, to flush the stream and send all to std::cout
OutStream& operator<<(std::ostream& (*os)(std::ostream&)) {
// here you can build the real console log line, add colors and infos, or even write out to a log file
std::cout << __TIME__ << " [" << (int)level << "] " << stream.str() << os;
stream.str(""); // reset the string stream
level = DebugLevel::INFO; // reset the level to info
return *this;
}
} Log;
};
Debug::OutStream Debug::Log; // need to be instantiaded only because I use a static Debug class
int main() {
Debug::Log(DebugLevel::ERROR) << "Hello Log! " << 2 << " " << __FUNCTION__ << std::endl;
Debug::Log << "Hello Log! " << 0xFA << std::endl; // NB: this way the debugLevel is default
return 0;
}
In one of my projects, I wrote wrapper for std::cout.
It looks something like this:
struct out_t {
template<typename T>
out_t&
operator << (T&& x) {
std::cout << x;
// log << x;
return *this;
};
};
out_t out;
out << 1;
For complete code look for struct out in io.h
In our project we use the c++ stream operator (<<) in our object model to print out an easy readible format of the data. A simplified example is this:
std::ostream& operator<<(std::ostream & oStream, const OwnClass& iOwnClass) {
oStream << "[SomeMember1: " << iOwnClass._ownMember1 << "]\n";
oStream << "[SomeMember2: " << iOwnClass._ownMember2 << "]\n";
}
Resulting in this in the logging:
[SomeMember1: foo]
[SomeMember2: bar]
What we want now is to be able to indent the result of that operator. Some calling class might not want the result like this, but want to add 2 spaces indention before each line. We could add a member to our class specifying the indention, but that does not seem to be an elegant solution.
Of course this is not a very big issue, but our logging would be so much nicer if this would work.
Thanks
The simplest solution is to slip a filtering streambuf between the
ostream and the actual streambuf. Something like:
class IndentingOStreambuf : public std::streambuf
{
std::streambuf* myDest;
bool myIsAtStartOfLine;
std::string myIndent;
std::ostream* myOwner;
protected:
virtual int overflow( int ch )
{
if ( myIsAtStartOfLine && ch != '\n' ) {
myDest->sputn( myIndent.data(), myIndent.size() );
}
myIsAtStartOfLine = ch == '\n';
return myDest->sputc( ch );
}
public:
explicit IndentingOStreambuf(
std::streambuf* dest, int indent = 4 )
: myDest( dest )
, myIsAtStartOfLine( true )
, myIndent( indent, ' ' )
, myOwner( NULL )
{
}
explicit IndentingOStreambuf(
std::ostream& dest, int indent = 4 )
: myDest( dest.rdbuf() )
, myIsAtStartOfLine( true )
, myIndent( indent, ' ' )
, myOwner( &dest )
{
myOwner->rdbuf( this );
}
virtual ~IndentingOStreambuf()
{
if ( myOwner != NULL ) {
myOwner->rdbuf( myDest );
}
}
};
To insert, just create an instance of the streambuf:
IndentingOStreambuf indent( std::cout );
// Indented output...
When indent goes out of scope, everything returns to normal.
(For logging, I have one that is a bit more complex: the
LoggingOStreambuf takes __FILE__ and __LINE__ as arguments, sets
myIndent to a formatted string with these arguments, plus a time
stamp, resets it to an indentation string after each output, collects
all of the output in an std::ostringstream, and outputs it atomically
to myDest in the destructor.)
This can be done using a custom stream-manipulator that stores the desired indentation-level in a word of the internal extensible array of the stream. You can request such a word using the function ios_base::xalloc. This function will give you the index of your word. You can access it using ios_base::iword. One way to implement that would be this:
struct indent {
indent(int level) : level(level) {}
private:
friend std::ostream& operator<<(std::ostream& stream, const indent& val);
int level;
};
std::ostream& operator<<(std::ostream& stream, const indent& val) {
for(int i = 0; i < val.level; i++) {
stream << " ";
}
return stream;
}
std::ostream& operator<<(std::ostream & oStream, const OwnClass& iOwnClass) {
oStream << indent(oStream.iword(index)) << "[SomeMember1: " <<
iOwnClass._ownMember1 << "]\n";
oStream << indent(oStream.iword(index)) << "[SomeMember2: " <<
iOwnClass._ownMember2 << "]\n";
}
You'd have to figure out where to store the index. This effectively allows you to add custom state to the stream (note that this would not be thread-safe out-of-the-box). Every function that wants indentation should add the requested indentation to the stream, and subtract it again when it is done. You could make sure this always happen by using a guard to add/subtract the desired indent (IMHO this is more elegant than using a manipulator):
class indent_guard {
public:
indent_guard(int level, std::ostream& stream, int index)
: level(level),
stream(stream),
index(index)
{
stream.iword(index) += level;
}
~indent_guard() {
stream.iword(index) -= level;
}
private:
int level;
std::ostream& stream;
int index;
};
You could use it like this:
void some_func() {
indent_guard(2, std::cout, index);
// all output inside this function will be indented by 2 spaces
some_func(); // recursive call - output will be indented by 4 spaces
// here it will be 2 spaces again
}
Not so good way to do this is to add a global variable, which tells the indentation. Something like this :
std::string OwnClassIndentation;
std::ostream& operator<<(std::ostream & oStream, const OwnClass& iOwnClass) {
oStream << "[SomeMember1:" << OwnClassIndentation << iOwnClass._ownMember1 << "]\n";
oStream << "[SomeMember2:" << OwnClassIndentation << iOwnClass._ownMember2 << "]\n";
}
And then set it as appropriate.
You can make your own stream class that has an indentation variable and override the endl for that class, inserting the indentation.
I'm adding functions to my (simple) log class to make it usable like a stream.
Currently, after some modifications, I got this (in my cpp):
// blah blah blah...
// note: here String is a defined as: typedef std::string String;
void Log::logMessage( const String& message )
{
logText(); // to be sure we flush the current text if any (when "composing" a message)
addText( message );
logText(); // really log the message and make the current text empty
}
// blah blah blah...
Log& operator<<( Log& log, const std::stringstream& message )
{
log.logMessage( message.str() );
return log;
}
Log& operator<<( Log& log, const String& message )
{
log.addText( message );
return log;
}
Now in my "client" app I'm using this code to check the result (m_log is a valid pointer as you have already guessed):
gcore::Log& log = *m_log;
log << getName() << " : application created.";
log << "This is a test for " << getName();
Now the problem I got is that logText() (and logMessage) is never called because this test code will only call the << operator with String.
What I need is a way to call logText() when the given steam of string is finished :
log << getName() << " : application created.";
would be equivalent to
log.addText( getName() );
log.addText( " : application create." );
log.logText();
I'm not sure how to do this or even if it's possible. My first guess is that it would be possible to use std::endl at the end of the stream like this :
log << getName() << " : application created." << std::endl;
Or something equivalent, but if it's possible to do it without adding objects to the stream, that would be nice.
Any idea?
You can create a temp object and use his destructor to catch the end of the statement:
following code should give you the basic idea
class Log
{
public:
class Sublog
{
public:
Sublog(const std::string& message)
{
std::cout << message;
}
void addText(const std::string& message)
{
std::cout << message;
}
~Sublog()
{
std::cout << std::endl;
}
Sublog& operator<<(const std::string& message )
{
this->addText(message);
return *this;
}
};
};
Log::Sublog operator<<( Log& log, const std::string& message )
{
return Log::Sublog(message);
}
which would be used like this
int main()
{
Log log;
log << "Foo" << "bar";
log << "baz" << "plop";
}
after each semicolon, the destructor of Sublog is called
Klaim: the (working and effective) implementation of this solution in my case :
in the Log header :
/** To allow streaming semantic on logs (used in << operator) .
*/
class LogStreamer
{
public:
LogStreamer( Log& log, const String& text )
: m_log( log )
{
m_log.addText( text );
}
~LogStreamer()
{
m_log.logText();
}
LogStreamer& operator<<( const String& text )
{
m_log.addText( text );
return *this;
}
private:
Log& m_log;
};
GCORE_API LogStreamer operator<<( Log& log, const String& message );
and in the cpp file:
LogStreamer operator<<( Log& log, const String& message )
{
return LogStreamer( log, message );
}