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/ProfilingFormater.h"
00019 #include "zypp/base/String.h"
00020 #include "zypp/Date.h"
00021 #include "zypp/PathInfo.h"
00022 
00023 using std::endl;
00024 
00026 namespace zypp
00027 { 
00028 
00029   namespace base
00030   { 
00031 
00033     // LineFormater
00035     std::string LogControl::LineFormater::format( const std::string & group_r,
00036                                                   logger::LogLevel    level_r,
00037                                                   const char *        file_r,
00038                                                   const char *        func_r,
00039                                                   int                 line_r,
00040                                                   const std::string & message_r )
00041     {
00042       static char hostname[1024];
00043       static char nohostname[] = "unknown";
00044       std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
00045       return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
00046                         now.c_str(), level_r,
00047                         ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
00048                         getpid(),
00049                         group_r.c_str(),
00050                         file_r, func_r, line_r,
00051                         message_r.c_str() );
00052     }
00053 
00055     namespace logger
00056     { 
00057 
00059       // LineWriter
00061       struct StdErrWriter : public LogControl::LineWriter
00062       {
00063         virtual void writeOut( const std::string & formated_r )
00064         {
00065           std::cerr << formated_r << endl;
00066         }
00067       };
00069       struct FileWriter : public LogControl::LineWriter
00070       {
00071         FileWriter( const Pathname & logfile_r, mode_t mode_r )
00072         {
00073           // set unbuffered write
00074           _outs.rdbuf()->pubsetbuf(0,0);
00075           _outs.open( logfile_r.asString().c_str(), std::ios_base::app );
00076           // not filesystem::chmod, as filesystem:: functions log,
00077           // and this FileWriter is not yet in place.
00078           ::chmod( logfile_r.asString().c_str(), mode_r );
00079         }
00080         std::ofstream _outs;
00081 
00082         virtual void writeOut( const std::string & formated_r )
00083         {
00084           _outs << formated_r << endl;
00085         }
00086       };
00088 
00089       inline void putStream( const std::string & group_r, LogLevel level_r,
00090                              const char * file_r, const char * func_r, int line_r,
00091                              const std::string & buffer_r );
00092 
00094       //
00095       //        CLASS NAME : Loglinebuf
00096       //
00097       class Loglinebuf : public std::streambuf {
00098 
00099       public:
00101         Loglinebuf( const std::string & group_r, LogLevel level_r )
00102         : _group( group_r )
00103         , _level( level_r )
00104         , _file( "" )
00105         , _func( "" )
00106         , _line( -1 )
00107         {}
00109         ~Loglinebuf()
00110         {
00111           if ( !_buffer.empty() )
00112             writeout( "\n", 1 );
00113         }
00114 
00116         void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
00117         {
00118           _file = fil_r;
00119           _func = fnc_r;
00120           _line = lne_r;
00121         }
00122 
00123       private:
00125         virtual std::streamsize xsputn( const char * s, std::streamsize n )
00126         { return writeout( s, n ); }
00128         virtual int overflow( int ch = EOF )
00129         {
00130           if ( ch != EOF )
00131             {
00132               char tmp = ch;
00133               writeout( &tmp, 1 );
00134             }
00135           return 0;
00136         }
00138         virtual int writeout( const char* s, std::streamsize n )
00139         {
00140           if ( s && n )
00141             {
00142               const char * c = s;
00143               for ( int i = 0; i < n; ++i, ++c )
00144                 {
00145                   if ( *c == '\n' ) {
00146                     _buffer += std::string( s, c-s );
00147                     logger::putStream( _group, _level, _file, _func, _line, _buffer );
00148                     _buffer = std::string();
00149                     s = c+1;
00150                   }
00151                 }
00152               if ( s < c )
00153                 {
00154                   _buffer += std::string( s, c-s );
00155                 }
00156             }
00157           return n;
00158         }
00159 
00160       private:
00161         std::string  _group;
00162         LogLevel     _level;
00163         const char * _file;
00164         const char * _func;
00165         int          _line;
00166         std::string  _buffer;
00167       };
00168 
00170 
00172       //
00173       //        CLASS NAME : Loglinestream
00174       //
00175       class Loglinestream {
00176 
00177       public:
00179         Loglinestream( const std::string & group_r, LogLevel level_r )
00180         : _mybuf( group_r, level_r )
00181         , _mystream( &_mybuf )
00182         {}
00184         ~Loglinestream()
00185         { _mystream.flush(); }
00186 
00187       public:
00189         std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
00190         {
00191           _mybuf.tagSet( fil_r, fnc_r, lne_r );
00192           return _mystream;
00193         }
00194 
00195       private:
00196         Loglinebuf   _mybuf;
00197         std::ostream _mystream;
00198       };
00200 
00202       //
00203       //        CLASS NAME : LogControlImpl
00204       //
00214       struct LogControlImpl
00215       {
00216       public:
00217         void excessive( bool onOff_r )
00218         { _excessive = onOff_r; }
00219 
00221         void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
00222         { _lineWriter = writer_r; }
00223 
00224         shared_ptr<LogControl::LineWriter> getLineWriter() const
00225         { return _lineWriter; }
00226 
00228         void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
00229         {
00230           if ( format_r )
00231             _lineFormater = format_r;
00232           else
00233             _lineFormater.reset( new LogControl::LineFormater );
00234         }
00235 
00236         void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
00237         {
00238           if ( logfile_r.empty() )
00239             setLineWriter( shared_ptr<LogControl::LineWriter>() );
00240           else if ( logfile_r == Pathname( "-" ) )
00241             setLineWriter( shared_ptr<LogControl::LineWriter>(new StdErrWriter) );
00242           else
00243             setLineWriter( shared_ptr<LogControl::LineWriter>(new FileWriter(logfile_r, mode_r)) );
00244         }
00245 
00246       private:
00247         std::ostream _no_stream;
00248         bool         _excessive;
00249 
00250         shared_ptr<LogControl::LineFormater> _lineFormater;
00251         shared_ptr<LogControl::LineWriter>   _lineWriter;
00252 
00253       public:
00255         std::ostream & getStream( const std::string & group_r,
00256                                   LogLevel            level_r,
00257                                   const char *        file_r,
00258                                   const char *        func_r,
00259                                   const int           line_r )
00260         {
00261           if ( ! _lineWriter )
00262             return _no_stream;
00263           if ( level_r == E_XXX && !_excessive )
00264             return _no_stream;
00265 
00266           if ( !_streamtable[group_r][level_r] )
00267             {
00268               _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
00269             }
00270           return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r );
00271         }
00272 
00274         void putStream( const std::string & group_r,
00275                         LogLevel            level_r,
00276                         const char *        file_r,
00277                         const char *        func_r,
00278                         int                 line_r,
00279                         const std::string & message_r )
00280         {
00281           if ( _lineWriter )
00282             _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
00283                                                           file_r, func_r, line_r,
00284                                                           message_r ) );
00285         }
00286 
00287       private:
00288         typedef shared_ptr<Loglinestream>        StreamPtr;
00289         typedef std::map<LogLevel,StreamPtr>     StreamSet;
00290         typedef std::map<std::string,StreamSet>  StreamTable;
00292         StreamTable _streamtable;
00293 
00294       private:
00298         LogControlImpl()
00299         : _no_stream( NULL )
00300         , _excessive( getenv("ZYPP_FULLLOG") )
00301         , _lineFormater( new LogControl::LineFormater )
00302         {
00303           if ( getenv("ZYPP_LOGFILE") )
00304             logfile( getenv("ZYPP_LOGFILE") );
00305 
00306           if ( getenv("ZYPP_PROFILING") )
00307           {
00308             shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater);
00309             setLineFormater(formater);
00310           }
00311         }
00312 
00313       public:
00320         static LogControlImpl instance;
00321       };
00323 
00324       // 'THE' LogControlImpl singleton
00325       LogControlImpl LogControlImpl::instance;
00326 
00328 
00330       inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
00331       {
00332         return str << "LogControlImpl";
00333       }
00334 
00336       //
00337       // Access from logger::
00338       //
00340 
00341       std::ostream & getStream( const char * group_r,
00342                                 LogLevel     level_r,
00343                                 const char * file_r,
00344                                 const char * func_r,
00345                                 const int    line_r )
00346       {
00347         return LogControlImpl::instance.getStream( group_r,
00348                                                    level_r,
00349                                                    file_r,
00350                                                    func_r,
00351                                                    line_r );
00352       }
00353 
00355       inline void putStream( const std::string & group_r, LogLevel level_r,
00356                              const char * file_r, const char * func_r, int line_r,
00357                              const std::string & buffer_r )
00358       {
00359         LogControlImpl::instance.putStream( group_r, level_r,
00360                                             file_r, func_r, line_r,
00361                                             buffer_r );
00362       }
00363 
00365     } // namespace logger
00367 
00369     //
00370     //  CLASS NAME : LogControl
00371     //  Forward to LogControlImpl singleton.
00372     //
00374 
00375     using logger::LogControlImpl;
00376 
00377     void LogControl::logfile( const Pathname & logfile_r )
00378     { LogControlImpl::instance.logfile( logfile_r ); }
00379 
00380     void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
00381     { LogControlImpl::instance.logfile( logfile_r, mode_r ); }
00382 
00383     void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
00384     { LogControlImpl::instance.setLineWriter( writer_r ); }
00385 
00386     void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r )
00387     { LogControlImpl::instance.setLineFormater( formater_r ); }
00388 
00389     void LogControl::logNothing()
00390     { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>() ); }
00391 
00392     void LogControl::logToStdErr()
00393     { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>( new logger::StdErrWriter ) ); }
00394 
00396     //
00397     // LogControl::TmpExcessive
00398     //
00400     LogControl::TmpExcessive::TmpExcessive()
00401     { LogControlImpl::instance.excessive( true ); }
00402     LogControl::TmpExcessive::~TmpExcessive()
00403     { LogControlImpl::instance.excessive( false );  }
00404 
00406     //
00407     // LogControl::TmpLineWriter
00408     //
00410     LogControl::TmpLineWriter::TmpLineWriter( const shared_ptr<LineWriter> & writer_r )
00411     : _writer( LogControlImpl::instance.getLineWriter() )
00412     { LogControlImpl::instance.setLineWriter( writer_r ); }
00413     LogControl::TmpLineWriter::~TmpLineWriter()
00414     { LogControlImpl::instance.setLineWriter( _writer ); }
00415     /******************************************************************
00416      **
00417      ** FUNCTION NAME : operator<<
00418      ** FUNCTION TYPE : std::ostream &
00419     */
00420     std::ostream & operator<<( std::ostream & str, const LogControl & obj )
00421     {
00422       return str << LogControlImpl::instance;
00423     }
00424 
00426   } // namespace base
00429 } // namespace zypp

Generated on Tue Sep 25 19:22:58 2007 for libzypp by  doxygen 1.5.3