Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/corelibs/vos/log.hh

Go to the documentation of this file.
00001 /*
00002     This file is part of the Virtual Object System of
00003     the Interreality project (http://interreality.org).
00004 
00005     Copyright (C) 2001, 2002 Peter Amstutz
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00020 
00021     Peter Amstutz <tetron@interreality.org>
00022 */
00023 #ifndef _LOG_HH_
00024 #define _LOG_HH_
00025 
00026 /** @file
00027     Defines Log.
00028     @see LOG
00029 */
00030 
00031 #include <vos/corelibs/vos/vosdefs.hh>
00032 
00033 #include <string>
00034 #include <map>
00035 
00036 /** @def LOG(c, l, m) log.hh vos/corelibs/vos/log.hh
00037 
00038     @param c (string) the logging channel, which will be created if it does not exist
00039     @param l (int) the logging level (0 is the highest priority, 5
00040     being the lowest priority.
00041     @param m The actual log message.  This is actually used as an
00042     output into a stream, so the whole C++ stream output API is available
00043     In other words, can use expressions like:
00044     @code
00045         LOG("foo", 3, "x = " << x << "\n");
00046     @endcode
00047 
00048     You can control log levels using the setLevel(), setDefaultLevel(), setMasterLevel(), and
00049     also by setting an environment variables named <code>VOS_LOG</code> and <code>VOS_MASTER_LOGLEVEL</code>.
00050     The LOG macro first checks the master loglevel. If (l) is greater than the master level, no logging message will be printed.
00051     Next, LOG checks the level for the channel. if (l) is less than or equal to the channel's level, the message is printed.
00052 
00053     The format of the <code>VOS_LOG</code> environment variable is <code>channel1=level1,channel2=level2,...</code>.
00054     Don't use any spaces.
00055     <code>VOS_MASTER_LOGLEVEL</code> should contain a single (positive) integer.
00056     Both environment variables are entirely optional.
00057 
00058     LOG must be a macro because of the way output streams are used (believe
00059     me, I tried other ways...)  Note that also, because it is a macro,
00060     you pay no penalty related to creating output the if string if it isn't going
00061     be printed; the log level is checked beforehand.
00062 */
00063 
00064 #define LOG_MAXLINELENGTH 1024
00065 
00066 #ifdef USE_STRSTREAM
00067 #include <strstream>
00068 #define LOG(c, l, m) {                 \
00069     if(l <= Log::masterLogLevel) {      \
00070         Log* _lg = Log::getLog(c);         \
00071         if(! _lg) { _lg=new Log(c); Log::addChannel(_lg); }  \
00072         if(_lg->getLevel() >= l) {          \
00073           char _y[LOG_MAXLINELENGTH];                   \
00074           memset(_y, 0, sizeof(_y));       \
00075           ostrstream _x(_y, sizeof(_y)-1); \
00076           _x << m;                        \
00077           _lg->log(l, _x.str());           \
00078         } \
00079     }                                  \
00080 }
00081 #else
00082 #include <sstream>
00083 #define LOG(c, l, m) {         \
00084     if(l <= Log::masterLogLevel) { \
00085         Log* _lg = Log::getLog(c); \
00086         if(! _lg) { _lg=new Log(c); Log::addChannel(_lg); }  \
00087         if(_lg->getLevel() >= l) {  \
00088           ostringstream _x;        \
00089           _x << m;                 \
00090           _lg->log(l, _x.str());    \
00091         }                          \
00092     } \
00093 }
00094 #endif
00095 
00096 namespace VOS
00097 {
00098 /** @class Log log.hh vos/corelibs/vos/log.hh
00099  *
00100  * The logging class.  The main user interface to this class is the macro LOG(),
00101  * but you can set some global options using the static methods in this class,
00102  * and you can set properties of individual channels using this class.
00103  */
00104 class VOS_API Log
00105 {
00106 private:
00107     string channelname;
00108     std::ostream* output;
00109     int loglevel;
00110 
00111     class StrCmp {
00112     public:
00113         inline bool operator()(const char* p, const char* q) const {
00114             return (strcmp(p, q) < 0);
00115         };
00116     };
00117 
00118     static map<const char*, Log*, StrCmp> channels;
00119     static std::ostream* defaultostream;
00120     static int defaultloglevel;
00121     static bool didReadEnv;
00122 public:
00123 
00124     /** A level that applies to all channels. (default is 10) */
00125     static int masterLogLevel;
00126 
00127     static boost::mutex log_io_mutex;
00128 
00129     /** Construct a new logging channel.  Usually you
00130         don't need to call this, as it will be created automatically
00131         when a new channel is refered to.
00132         @param channel the channel name that will select this log object
00133         @param outputstream the output stream this log will write to
00134         @internal
00135     */
00136     Log(const string& channel, std::ostream* outputstream);
00137 
00138     /** Construct a new logging channel.  Usually you
00139         don't need to call this, as it will be created automatically
00140         when a new channel is refered to.
00141         @param channel the channel name that will select this log object
00142         @internal
00143     */
00144     Log(const string& channel);
00145 
00146     /** Write a line to the logfile.  You probably want to be
00147         using LOG(), however.
00148         @param level the level to log at.  If the logging channel
00149         level is lower than this level, the log message will be suppressed
00150         @param message the message string to print
00151         @internal
00152     */
00153     void log(int level, const string& message);
00154 
00155     /** Set the log level for this channel. Log levels for channels can also be set with an environment variable VOS_LOG, which takes the format channel:level,channel:level, etc. -- channel is the name of a log channel, and level is the integer level for that channel.
00156         @param loglevel the level, messages with a level higher than this will be suppressed.
00157      */
00158     void setLevel(int loglevel);
00159 
00160     /** Get the log level for this channel
00161         @returns loglevel the level, messages with a level higher than this will be suppressed.
00162      */
00163     int getLevel();
00164 
00165     /** Log to a particular channel, which will be created if it does
00166         not exist.  You probably want to be using LOG(), however.
00167         @param channel the channel to log in
00168         @param level the level to log at.  If the logging channel
00169         level is lower than this level, the log message will be suppressed
00170         @param message the message string to print
00171         @internal
00172      */
00173     static void log(const char* channel, int level, const string& message);
00174     static void log(const string& channel, int level, const string& message);
00175 
00176     /** Obtain the log object for a particular channel
00177         @param channel the channel desired.
00178         @returns the log object desired, or 0 if it does not exist
00179     */
00180     static Log* getLog(const string& channel);
00181 
00182     /** Obtain the log object for a particular channel
00183         @param channel the channel desired.
00184         @returns the log object desired, or 0 if it does not exist
00185     */
00186     static Log* getLog(const char* channel);
00187 
00188     /** Add a new channel to the channel table.
00189         @param l the log channel
00190      */
00191     static void addChannel(Log* l);
00192 
00193     /** Sets the default output stream for new log objects.  The
00194         starting default output stream is "clog" (which is generally
00195         an alias for stderr.)
00196         @param o the output stream
00197     */
00198     static void setDefaultOutputStream(std::ostream* o);
00199 
00200     /** Sets the default log level for new log channels.
00201         @param loglevel the level, messages with a level higher than this will be suppressed.
00202     */
00203     static void setDefaultLevel(int loglevel);
00204 
00205     /** Returns the default log level for new log channels. */
00206     static int getDefaultLevel();
00207 
00208     /** Sets the master log level for all log objects. The master log level applies to all
00209         logging statements, regardless of channel name.
00210         @param loglevel the new level. Messages with a level higher than this will be suppressed.
00211     */
00212     static void setMasterLevel(int loglevel);
00213 
00214     /** Returns the master log level. */
00215     static int getMasterLevel();
00216 
00217     /** Read the environment variable VOS_LOG and set/create the
00218         appropriate log channels to the specified levels.
00219         @note This is called exactly once automatically by getLog() so
00220         you probably don't ever have to call this.
00221     */
00222 
00223     static void readEnvironment();
00224 
00225     /** Close all channels. */
00226     static void closeAllChannels();
00227 };
00228 }
00229 
00230 #endif

Generated on Tue Aug 12 03:55:40 2003 for Interreality Project - VOS by doxygen 1.3.2