libzypp 9.41.1
|
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 if ( mode_r ) 00050 { 00051 // not filesystem::assert_file as filesystem:: functions log, 00052 // and this FileWriter is not yet in place. 00053 int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r ); 00054 if ( fd != -1 ) 00055 ::close( fd ); 00056 } 00057 // set unbuffered write 00058 std::ofstream * fstr = 0; 00059 _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) ); 00060 fstr->rdbuf()->pubsetbuf(0,0); 00061 _str = &(*fstr); 00062 } 00063 } 00064 00066 } // namespace log 00068 00070 namespace base 00071 { 00072 00074 // LineFormater 00076 std::string LogControl::LineFormater::format( const std::string & group_r, 00077 logger::LogLevel level_r, 00078 const char * file_r, 00079 const char * func_r, 00080 int line_r, 00081 const std::string & message_r ) 00082 { 00083 static char hostname[1024]; 00084 static char nohostname[] = "unknown"; 00085 std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) ); 00086 return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s", 00087 now.c_str(), level_r, 00088 ( gethostname( hostname, 1024 ) ? nohostname : hostname ), 00089 getpid(), 00090 group_r.c_str(), 00091 file_r, func_r, line_r, 00092 message_r.c_str() ); 00093 } 00094 00096 namespace logger 00097 { 00098 00099 inline void putStream( const std::string & group_r, LogLevel level_r, 00100 const char * file_r, const char * func_r, int line_r, 00101 const std::string & buffer_r ); 00102 00104 // 00105 // CLASS NAME : Loglinebuf 00106 // 00107 class Loglinebuf : public std::streambuf { 00108 00109 public: 00111 Loglinebuf( const std::string & group_r, LogLevel level_r ) 00112 : _group( group_r ) 00113 , _level( level_r ) 00114 , _file( "" ) 00115 , _func( "" ) 00116 , _line( -1 ) 00117 {} 00119 ~Loglinebuf() 00120 { 00121 if ( !_buffer.empty() ) 00122 writeout( "\n", 1 ); 00123 } 00124 00126 void tagSet( const char * fil_r, const char * fnc_r, int lne_r ) 00127 { 00128 _file = fil_r; 00129 _func = fnc_r; 00130 _line = lne_r; 00131 } 00132 00133 private: 00135 virtual std::streamsize xsputn( const char * s, std::streamsize n ) 00136 { return writeout( s, n ); } 00138 virtual int overflow( int ch = EOF ) 00139 { 00140 if ( ch != EOF ) 00141 { 00142 char tmp = ch; 00143 writeout( &tmp, 1 ); 00144 } 00145 return 0; 00146 } 00148 virtual int writeout( const char* s, std::streamsize n ) 00149 { 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 std::ostream & ret( _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ) ); 00284 if ( !ret ) 00285 { 00286 ret.clear(); 00287 ret << "---<RESET LOGSTREAM FROM FAILED STATE]" << endl; 00288 } 00289 return ret; 00290 } 00291 00293 void putStream( const std::string & group_r, 00294 LogLevel level_r, 00295 const char * file_r, 00296 const char * func_r, 00297 int line_r, 00298 const std::string & message_r ) 00299 { 00300 if ( _lineWriter ) 00301 _lineWriter->writeOut( _lineFormater->format( group_r, level_r, 00302 file_r, func_r, line_r, 00303 message_r ) ); 00304 } 00305 00306 private: 00307 typedef shared_ptr<Loglinestream> StreamPtr; 00308 typedef std::map<LogLevel,StreamPtr> StreamSet; 00309 typedef std::map<std::string,StreamSet> StreamTable; 00311 StreamTable _streamtable; 00312 00313 private: 00317 LogControlImpl() 00318 : _no_stream( NULL ) 00319 , _excessive( getenv("ZYPP_FULLLOG") ) 00320 , _lineFormater( new LogControl::LineFormater ) 00321 { 00322 if ( getenv("ZYPP_LOGFILE") ) 00323 logfile( getenv("ZYPP_LOGFILE") ); 00324 00325 if ( getenv("ZYPP_PROFILING") ) 00326 { 00327 shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater); 00328 setLineFormater(formater); 00329 } 00330 } 00331 00332 ~LogControlImpl() 00333 { 00334 _lineWriter.reset(); 00335 } 00336 00337 public: 00344 static LogControlImpl & instance(); 00345 }; 00347 00348 // 'THE' LogControlImpl singleton 00349 inline LogControlImpl & LogControlImpl::instance() 00350 { 00351 static LogControlImpl _instance; 00352 return _instance; 00353 } 00354 00356 00358 inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj ) 00359 { 00360 return str << "LogControlImpl"; 00361 } 00362 00364 // 00365 // Access from logger:: 00366 // 00368 00369 std::ostream & getStream( const char * group_r, 00370 LogLevel level_r, 00371 const char * file_r, 00372 const char * func_r, 00373 const int line_r ) 00374 { 00375 return LogControlImpl::instance().getStream( group_r, 00376 level_r, 00377 file_r, 00378 func_r, 00379 line_r ); 00380 } 00381 00383 inline void putStream( const std::string & group_r, LogLevel level_r, 00384 const char * file_r, const char * func_r, int line_r, 00385 const std::string & buffer_r ) 00386 { 00387 LogControlImpl::instance().putStream( group_r, level_r, 00388 file_r, func_r, line_r, 00389 buffer_r ); 00390 } 00391 00392 bool isExcessive() 00393 { return LogControlImpl::instance().isExcessive(); } 00394 00396 } // namespace logger 00398 00400 // 00401 // CLASS NAME : LogControl 00402 // Forward to LogControlImpl singleton. 00403 // 00405 00406 using logger::LogControlImpl; 00407 00408 void LogControl::logfile( const Pathname & logfile_r ) 00409 { LogControlImpl::instance().logfile( logfile_r ); } 00410 00411 void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r ) 00412 { LogControlImpl::instance().logfile( logfile_r, mode_r ); } 00413 00414 shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const 00415 { return LogControlImpl::instance().getLineWriter(); } 00416 00417 void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r ) 00418 { LogControlImpl::instance().setLineWriter( writer_r ); } 00419 00420 void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r ) 00421 { LogControlImpl::instance().setLineFormater( formater_r ); } 00422 00423 void LogControl::logNothing() 00424 { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>() ); } 00425 00426 void LogControl::logToStdErr() 00427 { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) ); } 00428 00430 // 00431 // LogControl::TmpExcessive 00432 // 00434 LogControl::TmpExcessive::TmpExcessive() 00435 { LogControlImpl::instance().excessive( true ); } 00436 LogControl::TmpExcessive::~TmpExcessive() 00437 { LogControlImpl::instance().excessive( false ); } 00438 00439 /****************************************************************** 00440 ** 00441 ** FUNCTION NAME : operator<< 00442 ** FUNCTION TYPE : std::ostream & 00443 */ 00444 std::ostream & operator<<( std::ostream & str, const LogControl & obj ) 00445 { 00446 return str << LogControlImpl::instance(); 00447 } 00448 00450 } // namespace base 00453 } // namespace zypp