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
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
00057
00058 ::chmod( file_r.asString().c_str(), mode_r );
00059 }
00060 }
00061 }
00062
00064 }
00066
00068 namespace base
00069 {
00070
00072
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
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
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
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
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
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 }
00390
00392
00393
00394
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
00424
00426 LogControl::TmpExcessive::TmpExcessive()
00427 { LogControlImpl::instance().excessive( true ); }
00428 LogControl::TmpExcessive::~TmpExcessive()
00429 { LogControlImpl::instance().excessive( false ); }
00430
00431
00432
00433
00434
00435
00436 std::ostream & operator<<( std::ostream & str, const LogControl & obj )
00437 {
00438 return str << LogControlImpl::instance();
00439 }
00440
00442 }
00445 }