libzypp
10.5.0
|
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 00030 namespace log 00031 { 00032 00033 StdoutLineWriter::StdoutLineWriter() 00034 : StreamLineWriter( std::cout ) 00035 {} 00036 00037 StderrLineWriter::StderrLineWriter() 00038 : StreamLineWriter( std::cerr ) 00039 {} 00040 00041 FileLineWriter::FileLineWriter( const Pathname & file_r, mode_t mode_r ) 00042 { 00043 if ( file_r == Pathname("-") ) 00044 { 00045 _str = &std::cerr; 00046 } 00047 else 00048 { 00049 // set unbuffered write 00050 std::ofstream * fstr = 0; 00051 _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) ); 00052 fstr->rdbuf()->pubsetbuf(0,0); 00053 _str = &(*fstr); 00054 if ( mode_r ) 00055 { 00056 // not filesystem::chmod, as filesystem:: functions log, 00057 // and this FileWriter is not yet in place. 00058 ::chmod( file_r.asString().c_str(), mode_r ); 00059 } 00060 } 00061 } 00062 00064 } // namespace log 00066 00068 namespace base 00069 { 00070 00072 // LineFormater 00074 std::string LogControl::LineFormater::format( const std::string & group_r, 00075 logger::LogLevel level_r, 00076 const char * file_r, 00077 const char * func_r, 00078 int line_r, 00079 const std::string & message_r ) 00080 { 00081 static char hostname[1024]; 00082 static char nohostname[] = "unknown"; 00083 std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) ); 00084 return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s", 00085 now.c_str(), level_r, 00086 ( gethostname( hostname, 1024 ) ? nohostname : hostname ), 00087 getpid(), 00088 group_r.c_str(), 00089 file_r, func_r, line_r, 00090 message_r.c_str() ); 00091 } 00092 00094 namespace logger 00095 { 00096 00097 inline void putStream( const std::string & group_r, LogLevel level_r, 00098 const char * file_r, const char * func_r, int line_r, 00099 const std::string & buffer_r ); 00100 00102 // 00103 // CLASS NAME : Loglinebuf 00104 // 00105 class Loglinebuf : public std::streambuf { 00106 00107 public: 00109 Loglinebuf( const std::string & group_r, LogLevel level_r ) 00110 : _group( group_r ) 00111 , _level( level_r ) 00112 , _file( "" ) 00113 , _func( "" ) 00114 , _line( -1 ) 00115 {} 00117 ~Loglinebuf() 00118 { 00119 if ( !_buffer.empty() ) 00120 writeout( "\n", 1 ); 00121 } 00122 00124 void tagSet( const char * fil_r, const char * fnc_r, int lne_r ) 00125 { 00126 _file = fil_r; 00127 _func = fnc_r; 00128 _line = lne_r; 00129 } 00130 00131 private: 00133 virtual std::streamsize xsputn( const char * s, std::streamsize n ) 00134 { return writeout( s, n ); } 00136 virtual int overflow( int ch = EOF ) 00137 { 00138 if ( ch != EOF ) 00139 { 00140 char tmp = ch; 00141 writeout( &tmp, 1 ); 00142 } 00143 return 0; 00144 } 00146 virtual int writeout( const char* s, std::streamsize n ) 00147 { 00148 //logger::putStream( _group, _level, _file, _func, _line, _buffer ); 00149 //return n; 00150 if ( s && n ) 00151 { 00152 const char * c = s; 00153 for ( int i = 0; i < n; ++i, ++c ) 00154 { 00155 if ( *c == '\n' ) { 00156 _buffer += std::string( s, c-s ); 00157 logger::putStream( _group, _level, _file, _func, _line, _buffer ); 00158 _buffer = std::string(); 00159 s = c+1; 00160 } 00161 } 00162 if ( s < c ) 00163 { 00164 _buffer += std::string( s, c-s ); 00165 } 00166 } 00167 return n; 00168 } 00169 00170 private: 00171 std::string _group; 00172 LogLevel _level; 00173 const char * _file; 00174 const char * _func; 00175 int _line; 00176 std::string _buffer; 00177 }; 00178 00180 00182 // 00183 // CLASS NAME : Loglinestream 00184 // 00185 class Loglinestream { 00186 00187 public: 00189 Loglinestream( const std::string & group_r, LogLevel level_r ) 00190 : _mybuf( group_r, level_r ) 00191 , _mystream( &_mybuf ) 00192 {} 00194 ~Loglinestream() 00195 { _mystream.flush(); } 00196 00197 public: 00199 std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r ) 00200 { 00201 _mybuf.tagSet( fil_r, fnc_r, lne_r ); 00202 return _mystream; 00203 } 00204 00205 private: 00206 Loglinebuf _mybuf; 00207 std::ostream _mystream; 00208 }; 00210 00212 // 00213 // CLASS NAME : LogControlImpl 00214 // 00224 struct LogControlImpl 00225 { 00226 public: 00227 bool isExcessive() 00228 { return _excessive; } 00229 00230 void excessive( bool onOff_r ) 00231 { _excessive = onOff_r; } 00232 00234 void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r ) 00235 { _lineWriter = writer_r; } 00236 00237 shared_ptr<LogControl::LineWriter> getLineWriter() const 00238 { return _lineWriter; } 00239 00241 void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r ) 00242 { 00243 if ( format_r ) 00244 _lineFormater = format_r; 00245 else 00246 _lineFormater.reset( new LogControl::LineFormater ); 00247 } 00248 00249 void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 ) 00250 { 00251 if ( logfile_r.empty() ) 00252 setLineWriter( shared_ptr<LogControl::LineWriter>() ); 00253 else if ( logfile_r == Pathname( "-" ) ) 00254 setLineWriter( shared_ptr<LogControl::LineWriter>(new log::StderrLineWriter) ); 00255 else 00256 setLineWriter( shared_ptr<LogControl::LineWriter>(new log::FileLineWriter(logfile_r, mode_r)) ); 00257 } 00258 00259 private: 00260 std::ostream _no_stream; 00261 bool _excessive; 00262 00263 shared_ptr<LogControl::LineFormater> _lineFormater; 00264 shared_ptr<LogControl::LineWriter> _lineWriter; 00265 00266 public: 00268 std::ostream & getStream( const std::string & group_r, 00269 LogLevel level_r, 00270 const char * file_r, 00271 const char * func_r, 00272 const int line_r ) 00273 { 00274 if ( ! _lineWriter ) 00275 return _no_stream; 00276 if ( level_r == E_XXX && !_excessive ) 00277 return _no_stream; 00278 00279 if ( !_streamtable[group_r][level_r] ) 00280 { 00281 _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) ); 00282 } 00283 return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ); 00284 } 00285 00287 void putStream( const std::string & group_r, 00288 LogLevel level_r, 00289 const char * file_r, 00290 const char * func_r, 00291 int line_r, 00292 const std::string & message_r ) 00293 { 00294 if ( _lineWriter ) 00295 _lineWriter->writeOut( _lineFormater->format( group_r, level_r, 00296 file_r, func_r, line_r, 00297 message_r ) ); 00298 } 00299 00300 private: 00301 typedef shared_ptr<Loglinestream> StreamPtr; 00302 typedef std::map<LogLevel,StreamPtr> StreamSet; 00303 typedef std::map<std::string,StreamSet> StreamTable; 00305 StreamTable _streamtable; 00306 00307 private: 00311 LogControlImpl() 00312 : _no_stream( NULL ) 00313 , _excessive( getenv("ZYPP_FULLLOG") ) 00314 , _lineFormater( new LogControl::LineFormater ) 00315 { 00316 if ( getenv("ZYPP_LOGFILE") ) 00317 logfile( getenv("ZYPP_LOGFILE") ); 00318 00319 if ( getenv("ZYPP_PROFILING") ) 00320 { 00321 shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater); 00322 setLineFormater(formater); 00323 } 00324 } 00325 00326 ~LogControlImpl() 00327 { 00328 _lineWriter.reset(); 00329 } 00330 00331 public: 00338 static LogControlImpl & instance(); 00339 }; 00341 00342 // 'THE' LogControlImpl singleton 00343 inline LogControlImpl & LogControlImpl::instance() 00344 { 00345 static LogControlImpl _instance; 00346 return _instance; 00347 } 00348 00350 00352 inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj ) 00353 { 00354 return str << "LogControlImpl"; 00355 } 00356 00358 // 00359 // Access from logger:: 00360 // 00362 00363 std::ostream & getStream( const char * group_r, 00364 LogLevel level_r, 00365 const char * file_r, 00366 const char * func_r, 00367 const int line_r ) 00368 { 00369 return LogControlImpl::instance().getStream( group_r, 00370 level_r, 00371 file_r, 00372 func_r, 00373 line_r ); 00374 } 00375 00377 inline void putStream( const std::string & group_r, LogLevel level_r, 00378 const char * file_r, const char * func_r, int line_r, 00379 const std::string & buffer_r ) 00380 { 00381 LogControlImpl::instance().putStream( group_r, level_r, 00382 file_r, func_r, line_r, 00383 buffer_r ); 00384 } 00385 00386 bool isExcessive() 00387 { return LogControlImpl::instance().isExcessive(); } 00388 00390 } // namespace logger 00392 00394 // 00395 // CLASS NAME : LogControl 00396 // Forward to LogControlImpl singleton. 00397 // 00399 00400 using logger::LogControlImpl; 00401 00402 void LogControl::logfile( const Pathname & logfile_r ) 00403 { LogControlImpl::instance().logfile( logfile_r ); } 00404 00405 void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r ) 00406 { LogControlImpl::instance().logfile( logfile_r, mode_r ); } 00407 00408 shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const 00409 { return LogControlImpl::instance().getLineWriter(); } 00410 00411 void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r ) 00412 { LogControlImpl::instance().setLineWriter( writer_r ); } 00413 00414 void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r ) 00415 { LogControlImpl::instance().setLineFormater( formater_r ); } 00416 00417 void LogControl::logNothing() 00418 { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>() ); } 00419 00420 void LogControl::logToStdErr() 00421 { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) ); } 00422 00424 // 00425 // LogControl::TmpExcessive 00426 // 00428 LogControl::TmpExcessive::TmpExcessive() 00429 { LogControlImpl::instance().excessive( true ); } 00430 LogControl::TmpExcessive::~TmpExcessive() 00431 { LogControlImpl::instance().excessive( false ); } 00432 00433 /****************************************************************** 00434 ** 00435 ** FUNCTION NAME : operator<< 00436 ** FUNCTION TYPE : std::ostream & 00437 */ 00438 std::ostream & operator<<( std::ostream & str, const LogControl & obj ) 00439 { 00440 return str << LogControlImpl::instance(); 00441 } 00442 00444 } // namespace base 00447 } // namespace zypp