libzypp 8.13.6
|
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 if ( s && n ) 00149 { 00150 const char * c = s; 00151 for ( int i = 0; i < n; ++i, ++c ) 00152 { 00153 if ( *c == '\n' ) { 00154 _buffer += std::string( s, c-s ); 00155 logger::putStream( _group, _level, _file, _func, _line, _buffer ); 00156 _buffer = std::string(); 00157 s = c+1; 00158 } 00159 } 00160 if ( s < c ) 00161 { 00162 _buffer += std::string( s, c-s ); 00163 } 00164 } 00165 return n; 00166 } 00167 00168 private: 00169 std::string _group; 00170 LogLevel _level; 00171 const char * _file; 00172 const char * _func; 00173 int _line; 00174 std::string _buffer; 00175 }; 00176 00178 00180 // 00181 // CLASS NAME : Loglinestream 00182 // 00183 class Loglinestream { 00184 00185 public: 00187 Loglinestream( const std::string & group_r, LogLevel level_r ) 00188 : _mybuf( group_r, level_r ) 00189 , _mystream( &_mybuf ) 00190 {} 00192 ~Loglinestream() 00193 { _mystream.flush(); } 00194 00195 public: 00197 std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r ) 00198 { 00199 _mybuf.tagSet( fil_r, fnc_r, lne_r ); 00200 return _mystream; 00201 } 00202 00203 private: 00204 Loglinebuf _mybuf; 00205 std::ostream _mystream; 00206 }; 00208 00210 // 00211 // CLASS NAME : LogControlImpl 00212 // 00222 struct LogControlImpl 00223 { 00224 public: 00225 bool isExcessive() 00226 { return _excessive; } 00227 00228 void excessive( bool onOff_r ) 00229 { _excessive = onOff_r; } 00230 00232 void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r ) 00233 { _lineWriter = writer_r; } 00234 00235 shared_ptr<LogControl::LineWriter> getLineWriter() const 00236 { return _lineWriter; } 00237 00239 void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r ) 00240 { 00241 if ( format_r ) 00242 _lineFormater = format_r; 00243 else 00244 _lineFormater.reset( new LogControl::LineFormater ); 00245 } 00246 00247 void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 ) 00248 { 00249 if ( logfile_r.empty() ) 00250 setLineWriter( shared_ptr<LogControl::LineWriter>() ); 00251 else if ( logfile_r == Pathname( "-" ) ) 00252 setLineWriter( shared_ptr<LogControl::LineWriter>(new log::StderrLineWriter) ); 00253 else 00254 setLineWriter( shared_ptr<LogControl::LineWriter>(new log::FileLineWriter(logfile_r, mode_r)) ); 00255 } 00256 00257 private: 00258 std::ostream _no_stream; 00259 bool _excessive; 00260 00261 shared_ptr<LogControl::LineFormater> _lineFormater; 00262 shared_ptr<LogControl::LineWriter> _lineWriter; 00263 00264 public: 00266 std::ostream & getStream( const std::string & group_r, 00267 LogLevel level_r, 00268 const char * file_r, 00269 const char * func_r, 00270 const int line_r ) 00271 { 00272 if ( ! _lineWriter ) 00273 return _no_stream; 00274 if ( level_r == E_XXX && !_excessive ) 00275 return _no_stream; 00276 00277 if ( !_streamtable[group_r][level_r] ) 00278 { 00279 _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) ); 00280 } 00281 return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ); 00282 } 00283 00285 void putStream( const std::string & group_r, 00286 LogLevel level_r, 00287 const char * file_r, 00288 const char * func_r, 00289 int line_r, 00290 const std::string & message_r ) 00291 { 00292 if ( _lineWriter ) 00293 _lineWriter->writeOut( _lineFormater->format( group_r, level_r, 00294 file_r, func_r, line_r, 00295 message_r ) ); 00296 } 00297 00298 private: 00299 typedef shared_ptr<Loglinestream> StreamPtr; 00300 typedef std::map<LogLevel,StreamPtr> StreamSet; 00301 typedef std::map<std::string,StreamSet> StreamTable; 00303 StreamTable _streamtable; 00304 00305 private: 00309 LogControlImpl() 00310 : _no_stream( NULL ) 00311 , _excessive( getenv("ZYPP_FULLLOG") ) 00312 , _lineFormater( new LogControl::LineFormater ) 00313 { 00314 if ( getenv("ZYPP_LOGFILE") ) 00315 logfile( getenv("ZYPP_LOGFILE") ); 00316 00317 if ( getenv("ZYPP_PROFILING") ) 00318 { 00319 shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater); 00320 setLineFormater(formater); 00321 } 00322 } 00323 00324 ~LogControlImpl() 00325 { 00326 _lineWriter.reset(); 00327 } 00328 00329 public: 00336 static LogControlImpl & instance(); 00337 }; 00339 00340 // 'THE' LogControlImpl singleton 00341 inline LogControlImpl & LogControlImpl::instance() 00342 { 00343 static LogControlImpl _instance; 00344 return _instance; 00345 } 00346 00348 00350 inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj ) 00351 { 00352 return str << "LogControlImpl"; 00353 } 00354 00356 // 00357 // Access from logger:: 00358 // 00360 00361 std::ostream & getStream( const char * group_r, 00362 LogLevel level_r, 00363 const char * file_r, 00364 const char * func_r, 00365 const int line_r ) 00366 { 00367 return LogControlImpl::instance().getStream( group_r, 00368 level_r, 00369 file_r, 00370 func_r, 00371 line_r ); 00372 } 00373 00375 inline void putStream( const std::string & group_r, LogLevel level_r, 00376 const char * file_r, const char * func_r, int line_r, 00377 const std::string & buffer_r ) 00378 { 00379 LogControlImpl::instance().putStream( group_r, level_r, 00380 file_r, func_r, line_r, 00381 buffer_r ); 00382 } 00383 00384 bool isExcessive() 00385 { return LogControlImpl::instance().isExcessive(); } 00386 00388 } // namespace logger 00390 00392 // 00393 // CLASS NAME : LogControl 00394 // Forward to LogControlImpl singleton. 00395 // 00397 00398 using logger::LogControlImpl; 00399 00400 void LogControl::logfile( const Pathname & logfile_r ) 00401 { LogControlImpl::instance().logfile( logfile_r ); } 00402 00403 void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r ) 00404 { LogControlImpl::instance().logfile( logfile_r, mode_r ); } 00405 00406 shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const 00407 { return LogControlImpl::instance().getLineWriter(); } 00408 00409 void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r ) 00410 { LogControlImpl::instance().setLineWriter( writer_r ); } 00411 00412 void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r ) 00413 { LogControlImpl::instance().setLineFormater( formater_r ); } 00414 00415 void LogControl::logNothing() 00416 { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>() ); } 00417 00418 void LogControl::logToStdErr() 00419 { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) ); } 00420 00422 // 00423 // LogControl::TmpExcessive 00424 // 00426 LogControl::TmpExcessive::TmpExcessive() 00427 { LogControlImpl::instance().excessive( true ); } 00428 LogControl::TmpExcessive::~TmpExcessive() 00429 { LogControlImpl::instance().excessive( false ); } 00430 00431 /****************************************************************** 00432 ** 00433 ** FUNCTION NAME : operator<< 00434 ** FUNCTION TYPE : std::ostream & 00435 */ 00436 std::ostream & operator<<( std::ostream & str, const LogControl & obj ) 00437 { 00438 return str << LogControlImpl::instance(); 00439 } 00440 00442 } // namespace base 00445 } // namespace zypp