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 
00021 using std::endl;
00022 
00024 namespace zypp
00025 { 
00026 
00027   namespace base
00028   { 
00029 
00031     // LineFormater
00033     std::string LogControl::LineFormater::format( const std::string & group_r,
00034                                                   logger::LogLevel    level_r,
00035                                                   const char *        file_r,
00036                                                   const char *        func_r,
00037                                                   int                 line_r,
00038                                                   const std::string & message_r )
00039     {
00040       static char hostname[1024];
00041       static char nohostname[] = "unknown";
00042       std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
00043       return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
00044                         now.c_str(), level_r,
00045                         ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
00046                         getpid(),
00047                         group_r.c_str(),
00048                         file_r, func_r, line_r,
00049                         message_r.c_str() );
00050     }
00051 
00053     namespace logger
00054     { 
00055 
00057       // LineWriter
00059       struct StdErrWriter : public LogControl::LineWriter
00060       {
00061         virtual void writeOut( const std::string & formated_r )
00062         {
00063           std::cerr << formated_r << endl;
00064         }
00065       };
00067       struct FileWriter : public LogControl::LineWriter
00068       {
00069         FileWriter( const Pathname & logfile_r )
00070         : _logfile( logfile_r )
00071         {}
00072         Pathname _logfile;
00073 
00074         virtual void writeOut( const std::string & formated_r )
00075         {
00076           std::ofstream outs( _logfile.asString().c_str(), std::ios_base::app );
00077           outs << formated_r << endl;
00078         }
00079       };
00081 
00082       inline void putStream( const std::string & group_r, LogLevel level_r,
00083                              const char * file_r, const char * func_r, int line_r,
00084                              const std::string & buffer_r );
00085 
00087       //
00088       //        CLASS NAME : Loglinebuf
00089       //
00090       class Loglinebuf : public std::streambuf {
00091 
00092       public:
00094         Loglinebuf( const std::string & group_r, LogLevel level_r )
00095         : _group( group_r )
00096         , _level( level_r )
00097         , _file( "" )
00098         , _func( "" )
00099         , _line( -1 )
00100         {}
00102         ~Loglinebuf()
00103         {
00104           if ( !_buffer.empty() )
00105             writeout( "\n", 1 );
00106         }
00107 
00109         void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
00110         {
00111           _file = fil_r;
00112           _func = fnc_r;
00113           _line = lne_r;
00114         }
00115 
00116       private:
00118         virtual std::streamsize xsputn( const char * s, std::streamsize n )
00119         { return writeout( s, n ); }
00121         virtual int overflow( int ch = EOF )
00122         {
00123           if ( ch != EOF )
00124             {
00125               char tmp = ch;
00126               writeout( &tmp, 1 );
00127             }
00128           return 0;
00129         }
00131         virtual int writeout( const char* s, std::streamsize n )
00132         {
00133           if ( s && n )
00134             {
00135               const char * c = s;
00136               for ( int i = 0; i < n; ++i, ++c )
00137                 {
00138                   if ( *c == '\n' ) {
00139                     _buffer += std::string( s, c-s );
00140                     logger::putStream( _group, _level, _file, _func, _line, _buffer );
00141                     _buffer = std::string();
00142                     s = c+1;
00143                   }
00144                 }
00145               if ( s < c )
00146                 {
00147                   _buffer += std::string( s, c-s );
00148                 }
00149             }
00150           return n;
00151         }
00152 
00153       private:
00154         std::string  _group;
00155         LogLevel     _level;
00156         const char * _file;
00157         const char * _func;
00158         int          _line;
00159         std::string  _buffer;
00160       };
00161 
00163 
00165       //
00166       //        CLASS NAME : Loglinestream
00167       //
00168       class Loglinestream {
00169 
00170       public:
00172         Loglinestream( const std::string & group_r, LogLevel level_r )
00173         : _mybuf( group_r, level_r )
00174         , _mystream( &_mybuf )
00175         {}
00177         ~Loglinestream()
00178         { _mystream.flush(); }
00179 
00180       public:
00182         std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
00183         {
00184           _mybuf.tagSet( fil_r, fnc_r, lne_r );
00185           return _mystream;
00186         }
00187 
00188       private:
00189         Loglinebuf   _mybuf;
00190         std::ostream _mystream;
00191       };
00193 
00195       //
00196       //        CLASS NAME : LogControlImpl
00197       //
00207       struct LogControlImpl
00208       {
00209       public:
00210         void excessive( bool onOff_r )
00211         { _excessive = onOff_r; }
00212 
00214         void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
00215         { _lineWriter = writer_r; }
00216 
00217         shared_ptr<LogControl::LineWriter> getLineWriter() const
00218         { return _lineWriter; }
00219 
00221         void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
00222         {
00223           if ( format_r )
00224             _lineFormater = format_r;
00225           else
00226             _lineFormater.reset( new LogControl::LineFormater );
00227         }
00228 
00229         void logfile( const Pathname & logfile_r )
00230         {
00231           if ( logfile_r.empty() )
00232             setLineWriter( shared_ptr<LogControl::LineWriter>() );
00233           else if ( logfile_r == Pathname( "-" ) )
00234             setLineWriter( shared_ptr<LogControl::LineWriter>(new StdErrWriter) );
00235           else
00236             setLineWriter( shared_ptr<LogControl::LineWriter>(new FileWriter(logfile_r)) );
00237         }
00238 
00239       private:
00240         std::ostream _no_stream;
00241         bool         _excessive;
00242 
00243         shared_ptr<LogControl::LineFormater> _lineFormater;
00244         shared_ptr<LogControl::LineWriter>   _lineWriter;
00245 
00246       public:
00248         std::ostream & getStream( const std::string & group_r,
00249                                   LogLevel            level_r,
00250                                   const char *        file_r,
00251                                   const char *        func_r,
00252                                   const int           line_r )
00253         {
00254           if ( ! _lineWriter )
00255             return _no_stream;
00256           if ( level_r == E_XXX && !_excessive )
00257             return _no_stream;
00258 
00259           if ( !_streamtable[group_r][level_r] )
00260             {
00261               _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
00262             }
00263           return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r );
00264         }
00265 
00267         void putStream( const std::string & group_r,
00268                         LogLevel            level_r,
00269                         const char *        file_r,
00270                         const char *        func_r,
00271                         int                 line_r,
00272                         const std::string & message_r )
00273         {
00274           if ( _lineWriter )
00275             _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
00276                                                           file_r, func_r, line_r,
00277                                                           message_r ) );
00278         }
00279 
00280       private:
00281         typedef shared_ptr<Loglinestream>        StreamPtr;
00282         typedef std::map<LogLevel,StreamPtr>     StreamSet;
00283         typedef std::map<std::string,StreamSet>  StreamTable;
00285         StreamTable _streamtable;
00286 
00287       private:
00291         LogControlImpl()
00292         : _no_stream( NULL )
00293         , _excessive( getenv("ZYPP_FULLLOG") )
00294         , _lineFormater( new LogControl::LineFormater )
00295         {
00296           if ( getenv("ZYPP_LOGFILE") )
00297             logfile( getenv("ZYPP_LOGFILE") );
00298         }
00299 
00300       public:
00307         static LogControlImpl instance;
00308       };
00310 
00311       // 'THE' LogControlImpl singleton
00312       LogControlImpl LogControlImpl::instance;
00313 
00315 
00317       inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
00318       {
00319         return str << "LogControlImpl";
00320       }
00321 
00323       //
00324       // Access from logger::
00325       //
00327 
00329       std::ostream & getStream( const char * group_r,
00330                                 LogLevel     level_r,
00331                                 const char * file_r,
00332                                 const char * func_r,
00333                                 const int    line_r )
00334       {
00335         return LogControlImpl::instance.getStream( group_r,
00336                                                    level_r,
00337                                                    file_r,
00338                                                    func_r,
00339                                                    line_r );
00340       }
00341 
00343       inline void putStream( const std::string & group_r, LogLevel level_r,
00344                              const char * file_r, const char * func_r, int line_r,
00345                              const std::string & buffer_r )
00346       {
00347         LogControlImpl::instance.putStream( group_r, level_r,
00348                                             file_r, func_r, line_r,
00349                                             buffer_r );
00350       }
00351 
00353     } // namespace logger
00355 
00357     //
00358     //  CLASS NAME : LogControl
00359     //  Forward to LogControlImpl singleton.
00360     //
00362 
00363     using logger::LogControlImpl;
00364 
00365     void LogControl::logfile( const Pathname & logfile_r )
00366     { LogControlImpl::instance.logfile( logfile_r ); }
00367 
00368     void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
00369     { LogControlImpl::instance.setLineWriter( writer_r ); }
00370 
00371     void LogControl::logNothing()
00372     { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>() ); }
00373 
00374     void LogControl::logToStdErr()
00375     { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>( new logger::StdErrWriter ) ); }
00376 
00378     //
00379     // LogControl::TmpExcessive
00380     //
00382     LogControl::TmpExcessive::TmpExcessive()
00383     { LogControlImpl::instance.excessive( true ); }
00384     LogControl::TmpExcessive::~TmpExcessive()
00385     { LogControlImpl::instance.excessive( false );  }
00386 
00388     //
00389     // LogControl::TmpLineWriter
00390     //
00392     LogControl::TmpLineWriter::TmpLineWriter( const shared_ptr<LineWriter> & writer_r )
00393     : _writer( LogControlImpl::instance.getLineWriter() )
00394     { LogControlImpl::instance.setLineWriter( writer_r ); }
00395     LogControl::TmpLineWriter::~TmpLineWriter()
00396     { LogControlImpl::instance.setLineWriter( _writer ); }
00397     /******************************************************************
00398      **
00399      ** FUNCTION NAME : operator<<
00400      ** FUNCTION TYPE : std::ostream &
00401     */
00402     std::ostream & operator<<( std::ostream & str, const LogControl & obj )
00403     {
00404       return str << LogControlImpl::instance;
00405     }
00406 
00408   } // namespace base
00411 } // namespace zypp

Generated on Mon Jun 5 19:10:31 2006 for zypp by  doxygen 1.4.6