LogControl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <fstream>
00014 #include <string>
00015 
00016 #include "zypp/base/Logger.h"
00017 #include "zypp/base/LogControl.h"
00018 #include "zypp/base/String.h"
00019 #include "zypp/Date.h"
00020 #include "zypp/PathInfo.h"
00021 
00022 using std::endl;
00023 
00025 namespace zypp
00026 { 
00027 
00028   namespace base
00029   { 
00030 
00032     // LineFormater
00034     std::string LogControl::LineFormater::format( const std::string & group_r,
00035                                                   logger::LogLevel    level_r,
00036                                                   const char *        file_r,
00037                                                   const char *        func_r,
00038                                                   int                 line_r,
00039                                                   const std::string & message_r )
00040     {
00041       static char hostname[1024];
00042       static char nohostname[] = "unknown";
00043       std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
00044       return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
00045                         now.c_str(), level_r,
00046                         ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
00047                         getpid(),
00048                         group_r.c_str(),
00049                         file_r, func_r, line_r,
00050                         message_r.c_str() );
00051     }
00052 
00054     namespace logger
00055     { 
00056 
00058       // LineWriter
00060       struct StdErrWriter : public LogControl::LineWriter
00061       {
00062         virtual void writeOut( const std::string & formated_r )
00063         {
00064           std::cerr << formated_r << endl;
00065         }
00066       };
00068       struct FileWriter : public LogControl::LineWriter
00069       {
00070         FileWriter( const Pathname & logfile_r, mode_t mode_r )
00071         {
00072           // set unbuffered write
00073           _outs.rdbuf()->pubsetbuf(0,0);
00074           _outs.open( logfile_r.asString().c_str(), std::ios_base::app );
00075           // not filesystem::chmod, as filesystem:: functions log,
00076           // and this FileWriter is not yet in place.
00077           ::chmod( logfile_r.asString().c_str(), mode_r );
00078         }
00079         std::ofstream _outs;
00080 
00081         virtual void writeOut( const std::string & formated_r )
00082         {
00083           _outs << formated_r << endl;
00084         }
00085       };
00087 
00088       inline void putStream( const std::string & group_r, LogLevel level_r,
00089                              const char * file_r, const char * func_r, int line_r,
00090                              const std::string & buffer_r );
00091 
00093       //
00094       //        CLASS NAME : Loglinebuf
00095       //
00096       class Loglinebuf : public std::streambuf {
00097 
00098       public:
00100         Loglinebuf( const std::string & group_r, LogLevel level_r )
00101         : _group( group_r )
00102         , _level( level_r )
00103         , _file( "" )
00104         , _func( "" )
00105         , _line( -1 )
00106         {}
00108         ~Loglinebuf()
00109         {
00110           if ( !_buffer.empty() )
00111             writeout( "\n", 1 );
00112         }
00113 
00115         void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
00116         {
00117           _file = fil_r;
00118           _func = fnc_r;
00119           _line = lne_r;
00120         }
00121 
00122       private:
00124         virtual std::streamsize xsputn( const char * s, std::streamsize n )
00125         { return writeout( s, n ); }
00127         virtual int overflow( int ch = EOF )
00128         {
00129           if ( ch != EOF )
00130             {
00131               char tmp = ch;
00132               writeout( &tmp, 1 );
00133             }
00134           return 0;
00135         }
00137         virtual int writeout( const char* s, std::streamsize n )
00138         {
00139           if ( s && n )
00140             {
00141               const char * c = s;
00142               for ( int i = 0; i < n; ++i, ++c )
00143                 {
00144                   if ( *c == '\n' ) {
00145                     _buffer += std::string( s, c-s );
00146                     logger::putStream( _group, _level, _file, _func, _line, _buffer );
00147                     _buffer = std::string();
00148                     s = c+1;
00149                   }
00150                 }
00151               if ( s < c )
00152                 {
00153                   _buffer += std::string( s, c-s );
00154                 }
00155             }
00156           return n;
00157         }
00158 
00159       private:
00160         std::string  _group;
00161         LogLevel     _level;
00162         const char * _file;
00163         const char * _func;
00164         int          _line;
00165         std::string  _buffer;
00166       };
00167 
00169 
00171       //
00172       //        CLASS NAME : Loglinestream
00173       //
00174       class Loglinestream {
00175 
00176       public:
00178         Loglinestream( const std::string & group_r, LogLevel level_r )
00179         : _mybuf( group_r, level_r )
00180         , _mystream( &_mybuf )
00181         {}
00183         ~Loglinestream()
00184         { _mystream.flush(); }
00185 
00186       public:
00188         std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
00189         {
00190           _mybuf.tagSet( fil_r, fnc_r, lne_r );
00191           return _mystream;
00192         }
00193 
00194       private:
00195         Loglinebuf   _mybuf;
00196         std::ostream _mystream;
00197       };
00199 
00201       //
00202       //        CLASS NAME : LogControlImpl
00203       //
00213       struct LogControlImpl
00214       {
00215       public:
00216         void excessive( bool onOff_r )
00217         { _excessive = onOff_r; }
00218 
00220         void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
00221         { _lineWriter = writer_r; }
00222 
00223         shared_ptr<LogControl::LineWriter> getLineWriter() const
00224         { return _lineWriter; }
00225 
00227         void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
00228         {
00229           if ( format_r )
00230             _lineFormater = format_r;
00231           else
00232             _lineFormater.reset( new LogControl::LineFormater );
00233         }
00234 
00235         void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
00236         {
00237           if ( logfile_r.empty() )
00238             setLineWriter( shared_ptr<LogControl::LineWriter>() );
00239           else if ( logfile_r == Pathname( "-" ) )
00240             setLineWriter( shared_ptr<LogControl::LineWriter>(new StdErrWriter) );
00241           else
00242             setLineWriter( shared_ptr<LogControl::LineWriter>(new FileWriter(logfile_r, mode_r)) );
00243         }
00244 
00245       private:
00246         std::ostream _no_stream;
00247         bool         _excessive;
00248 
00249         shared_ptr<LogControl::LineFormater> _lineFormater;
00250         shared_ptr<LogControl::LineWriter>   _lineWriter;
00251 
00252       public:
00254         std::ostream & getStream( const std::string & group_r,
00255                                   LogLevel            level_r,
00256                                   const char *        file_r,
00257                                   const char *        func_r,
00258                                   const int           line_r )
00259         {
00260           if ( ! _lineWriter )
00261             return _no_stream;
00262           if ( level_r == E_XXX && !_excessive )
00263             return _no_stream;
00264 
00265           if ( !_streamtable[group_r][level_r] )
00266             {
00267               _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
00268             }
00269           return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r );
00270         }
00271 
00273         void putStream( const std::string & group_r,
00274                         LogLevel            level_r,
00275                         const char *        file_r,
00276                         const char *        func_r,
00277                         int                 line_r,
00278                         const std::string & message_r )
00279         {
00280           if ( _lineWriter )
00281             _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
00282                                                           file_r, func_r, line_r,
00283                                                           message_r ) );
00284         }
00285 
00286       private:
00287         typedef shared_ptr<Loglinestream>        StreamPtr;
00288         typedef std::map<LogLevel,StreamPtr>     StreamSet;
00289         typedef std::map<std::string,StreamSet>  StreamTable;
00291         StreamTable _streamtable;
00292 
00293       private:
00297         LogControlImpl()
00298         : _no_stream( NULL )
00299         , _excessive( getenv("ZYPP_FULLLOG") )
00300         , _lineFormater( new LogControl::LineFormater )
00301         {
00302           if ( getenv("ZYPP_LOGFILE") )
00303             logfile( getenv("ZYPP_LOGFILE") );
00304         }
00305 
00306       public:
00313         static LogControlImpl instance;
00314       };
00316 
00317       // 'THE' LogControlImpl singleton
00318       LogControlImpl LogControlImpl::instance;
00319 
00321 
00323       inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
00324       {
00325         return str << "LogControlImpl";
00326       }
00327 
00329       //
00330       // Access from logger::
00331       //
00333 
00335       std::ostream & getStream( const char * group_r,
00336                                 LogLevel     level_r,
00337                                 const char * file_r,
00338                                 const char * func_r,
00339                                 const int    line_r )
00340       {
00341         return LogControlImpl::instance.getStream( group_r,
00342                                                    level_r,
00343                                                    file_r,
00344                                                    func_r,
00345                                                    line_r );
00346       }
00347 
00349       inline void putStream( const std::string & group_r, LogLevel level_r,
00350                              const char * file_r, const char * func_r, int line_r,
00351                              const std::string & buffer_r )
00352       {
00353         LogControlImpl::instance.putStream( group_r, level_r,
00354                                             file_r, func_r, line_r,
00355                                             buffer_r );
00356       }
00357 
00359     } // namespace logger
00361 
00363     //
00364     //  CLASS NAME : LogControl
00365     //  Forward to LogControlImpl singleton.
00366     //
00368 
00369     using logger::LogControlImpl;
00370 
00371     void LogControl::logfile( const Pathname & logfile_r )
00372     { LogControlImpl::instance.logfile( logfile_r ); }
00373 
00374     void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
00375     { LogControlImpl::instance.logfile( logfile_r, mode_r ); }
00376 
00377     void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
00378     { LogControlImpl::instance.setLineWriter( writer_r ); }
00379 
00380     void LogControl::logNothing()
00381     { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>() ); }
00382 
00383     void LogControl::logToStdErr()
00384     { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>( new logger::StdErrWriter ) ); }
00385 
00387     //
00388     // LogControl::TmpExcessive
00389     //
00391     LogControl::TmpExcessive::TmpExcessive()
00392     { LogControlImpl::instance.excessive( true ); }
00393     LogControl::TmpExcessive::~TmpExcessive()
00394     { LogControlImpl::instance.excessive( false );  }
00395 
00397     //
00398     // LogControl::TmpLineWriter
00399     //
00401     LogControl::TmpLineWriter::TmpLineWriter( const shared_ptr<LineWriter> & writer_r )
00402     : _writer( LogControlImpl::instance.getLineWriter() )
00403     { LogControlImpl::instance.setLineWriter( writer_r ); }
00404     LogControl::TmpLineWriter::~TmpLineWriter()
00405     { LogControlImpl::instance.setLineWriter( _writer ); }
00406     /******************************************************************
00407      **
00408      ** FUNCTION NAME : operator<<
00409      ** FUNCTION TYPE : std::ostream &
00410     */
00411     std::ostream & operator<<( std::ostream & str, const LogControl & obj )
00412     {
00413       return str << LogControlImpl::instance;
00414     }
00415 
00417   } // namespace base
00420 } // namespace zypp

Generated on Thu Jul 6 00:07:20 2006 for zypp by  doxygen 1.4.6