//# LogIO.h: ostream-like interface to creating log messages. //# Copyright (C) 1997,1999,2000,2001,2003 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# //# $Id$ #ifndef CASA_LOGIO_H #define CASA_LOGIO_H //# Includes #include #include #include #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN //# Forward Declarations class LogSink; class LogOrigin; // // ostream-like interface to creating log messages. // // // // // //
  • LogSink class //
  • LogMessage class //
  • LogOrigin class // // // // Log message, Input/Output. // // // // LogIO is intended to be used in a way similar to the ostream class. // However, rather than sending it's output to a file or stdout, it bundles // its output up into LogMessage objects // and posts them to a LogSink. // // When you use the "<<" operator on a LogIO, you are building up a log message // inside the LogIO object. The message is posted when: //
      //
    1. LogIO::POST() is called //
    2. You send the LogIO::POST or LogIO::EXCEPTION // commands to the LogIO with the shift ( << ) command. //
    3. The LogIO object is destructed. //
    // Note that log messages may span multiple lines, so sending the LogIO a // newline (via "\n" or endl) does not force the message to be emitted. //
    // // // A LogIO may be created in the following ways: // // LogIO os; // // Here, os is attached to the global log sink, and no origin // information is set. // // // TableLogSink tab(...); // LogIO os(tab); // // Here, os is attached to tab (and also to the global // log sink since every sink's post also calls the global sink's // post). // // // // LogIO os(LogOrigin("class", "func(args)", WHERE)); // // Here, os is attached to the global sink and the origin // information is set to class::func(args) and the line number and // source file information is set (with WHERE). // // // TableLogSink tab(...); // LogIO os(LogOrigin("class", "func(args)", WHERE), tab); // // Here all the above information is set. // // Once you have a LogIO, using it is pretty simple: // // os << "Every good boy deserves" << 5 << " pieces of fudge!"; // // // This accumulates the message but does not send it. If you want to force it // to be sent you can do so with either of the following methods: // // os << LogIO::POST; // From the Commands enum // os.post(); // Member function // // Note that after a post the priority is reset to NORMAL. // // If you want to change the level of the message you can also do so with the // shift operator: // // os << LogIO::DEBUGGING << "Boring message" << // LogIO::SEVERE << "Error!" << LogIO::POST; // // Note that changing the priority changes the priority of the entire // message. The message does not get posted until the POST is done. // So in the above example the DEBUGGING priority does not do anything // because the priority is overwritten by the SEVERE one. // // You can also change the origin information with the << operator: // // os << LogOrigin("class", "func(args)"); // os << WHERE; // // // A class which has an operator<< to std::ostream but not LogIO can be handled // as follows: // // os << LogIO::SEVERE << " at "; // os.output() << MEpoch::Convert(time_p, MEpoch::Ref(MEpoch::UTC))(); // os << LogIO::POST; // // // // // The earlier method of creating log messages solely through LogSink and // LogMessage required the programmer to type in more lines of code than // this solution. Also, this interface makes it easy to drop log messages // into existing code that uses ostreams. // // // //
  • Add << operators for all classes that have ostream<< defined. // (We could probably do it with a template, but might result // in ambiguity). //
  • Have a function for changing the LogSink only? (You can get // much the same effect with operator=). // them? // class LogIO { public: // Special commands to the LogIO object enum Command { // Post the accumulated message. Equivalent to calling LogIO::post(). POST, // Post the accumulated message then throw an exception. // Always posts the message at SEVERE priority. Equivalent to calling // LogIO::postThenThrow(). EXCEPTION, // Change the message priority to SEVERE. SEVERE, // Change the message priority to WARN. WARN, // Change the message priority to NORMAL. NORMAL, NORMAL1, NORMAL2, NORMAL3, NORMAL4, NORMAL5, // Change the message priority to DEBUGGING. DEBUG1, DEBUG2, DEBUGGING}; // Attach this LogIO object to the global sink with no origin information. LogIO(); // Attach this LogIO object to the supplied sink. A referencing copy of // the sink is made inside the LogIO object, so you do not need to worry // about memory management. LogIO(LogSink &sink); // Attach this LogIO object to the supplied origin and global sink. LogIO(const LogOrigin &OR); // Attach this LogIO object to the supplied origin and sink. LogIO(const LogOrigin &OR, LogSink &sink); // Copying uses reference semantics, i.e. the same sink will be shared // by both copies. // LogIO(const LogIO &other); LogIO &operator=(const LogIO &other); // // The destructor will post any accumulated message that has not already // been posted. ~LogIO(); // Post the accumulated message. If you wish, you can post the messages // only locally to the sink. // After the post the priority is reset to NORMAL. void post(); void post(LogMessage &amess); // Post the accumulated message locally. // After the post the priority is reset to NORMAL. void postLocally(); // Post the accumulated message at SEVERE priority and then throw an // exception. // After the post the priority is reset to NORMAL. template void postThenThrow (const EXC& exc) { preparePostThenThrow(exc); sink_p.postThenThrow (msg_p, exc); } // Change the priority of the message. It does NOT post the accumulated // message at the old priority first. void priority(LogMessage::Priority which); LogMessage::Priority priority(); // Change the location in the origin. Almost always this is called with the // macro WHERE as its argument. void sourceLocation(const SourceLocation *where); // Change the origin of the accumulated message. void origin(const LogOrigin &origin); // Acumulate output in this ostream. ostream& output(); // Occasionally it is useful to interrogate the local log sink. LogSinkInterface &localSink(); const LogSinkInterface &localSink() const; private: // Prepare message stream for postThenThrow function. void preparePostThenThrow (const AipsError& x); LogSink sink_p; LogMessage msg_p; ostringstream *text_p; }; // // Functions to send commands to a LogIO object. // // The following commands don't change the accumulated message, rather they // send commands to the LogIO object, either to: //
      //
    1. post the current message: os << "message" << LogIO::POST; //
    2. post the current message and then throw an exception: // os << "error" << LogIO::EXCEPTION; //
    3. Change the priority of the current message: // os << LogIO::DEBUGGING; //
    4. Change the origin of the message: // // os << LogOrigin(...); // os << WHERE; // Changes only source file/line number // //
    // LogIO &operator<<(LogIO &os, LogIO::Command item); LogIO &operator<<(LogIO &os, const SourceLocation *item); LogIO &operator<<(LogIO &os, const LogOrigin &OR); // // // Functions to accumulate text in the output message. // // Accumulate text in the output message. The last entry is for things like // endl. // LogIO &operator<<(LogIO &os, const String &item); LogIO &operator<<(LogIO &os, const char *item); LogIO &operator<<(LogIO &os, Double item); LogIO &operator<<(LogIO &os, Complex item); LogIO &operator<<(LogIO &os, DComplex item); LogIO &operator<<(LogIO &os, Int item); LogIO &operator<<(LogIO &os, uInt item); LogIO &operator<<(LogIO &os, Int64 item); LogIO &operator<<(LogIO &os, uInt64 item); LogIO &operator<<(LogIO &os, uLong item); LogIO &operator<<(LogIO &os, Long item); LogIO &operator<<(LogIO &os, Bool item); LogIO &operator<<(LogIO &os, ostream &(*item)(ostream &)); // inline LogSinkInterface &LogIO::localSink() { return sink_p.localSink(); } inline const LogSinkInterface &LogIO::localSink() const { return sink_p.localSink(); } } //# NAMESPACE CASACORE - END #endif