00001
00002
00003
00004
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
00052
00053 int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r );
00054 if ( fd != -1 )
00055 ::close( fd );
00056 }
00057
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 }
00068
00070 namespace base
00071 {
00072
00074
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
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
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
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
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
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 }
00392
00394
00395
00396
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
00426
00428 LogControl::TmpExcessive::TmpExcessive()
00429 { LogControlImpl::instance().excessive( true ); }
00430 LogControl::TmpExcessive::~TmpExcessive()
00431 { LogControlImpl::instance().excessive( false ); }
00432
00433
00434
00435
00436
00437
00438 std::ostream & operator<<( std::ostream & str, const LogControl & obj )
00439 {
00440 return str << LogControlImpl::instance();
00441 }
00442
00444 }
00447 }