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/String.h"
00019 #include "zypp/Date.h"
00020
00021 using std::endl;
00022
00024 namespace zypp
00025 {
00026
00027 namespace base
00028 {
00029
00031
00033 std::string LogControl::LineFormater::format( const std::string & group_r,
00034 logger::LogLevel level_r,
00035 const char * file_r,
00036 const char * func_r,
00037 int line_r,
00038 const std::string & message_r )
00039 {
00040 static char hostname[1024];
00041 static char nohostname[] = "unknown";
00042 std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
00043 return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
00044 now.c_str(), level_r,
00045 ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
00046 getpid(),
00047 group_r.c_str(),
00048 file_r, func_r, line_r,
00049 message_r.c_str() );
00050 }
00051
00053 namespace logger
00054 {
00055
00057
00059 struct StdErrWriter : public LogControl::LineWriter
00060 {
00061 virtual void writeOut( const std::string & formated_r )
00062 {
00063 std::cerr << formated_r << endl;
00064 }
00065 };
00067 struct FileWriter : public LogControl::LineWriter
00068 {
00069 FileWriter( const Pathname & logfile_r )
00070 : _logfile( logfile_r )
00071 {}
00072 Pathname _logfile;
00073
00074 virtual void writeOut( const std::string & formated_r )
00075 {
00076 std::ofstream outs( _logfile.asString().c_str(), std::ios_base::app );
00077 outs << formated_r << endl;
00078 }
00079 };
00081
00082 inline void putStream( const std::string & group_r, LogLevel level_r,
00083 const char * file_r, const char * func_r, int line_r,
00084 const std::string & buffer_r );
00085
00087
00088
00089
00090 class Loglinebuf : public std::streambuf {
00091
00092 public:
00094 Loglinebuf( const std::string & group_r, LogLevel level_r )
00095 : _group( group_r )
00096 , _level( level_r )
00097 , _file( "" )
00098 , _func( "" )
00099 , _line( -1 )
00100 {}
00102 ~Loglinebuf()
00103 {
00104 if ( !_buffer.empty() )
00105 writeout( "\n", 1 );
00106 }
00107
00109 void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
00110 {
00111 _file = fil_r;
00112 _func = fnc_r;
00113 _line = lne_r;
00114 }
00115
00116 private:
00118 virtual std::streamsize xsputn( const char * s, std::streamsize n )
00119 { return writeout( s, n ); }
00121 virtual int overflow( int ch = EOF )
00122 {
00123 if ( ch != EOF )
00124 {
00125 char tmp = ch;
00126 writeout( &tmp, 1 );
00127 }
00128 return 0;
00129 }
00131 virtual int writeout( const char* s, std::streamsize n )
00132 {
00133 if ( s && n )
00134 {
00135 const char * c = s;
00136 for ( int i = 0; i < n; ++i, ++c )
00137 {
00138 if ( *c == '\n' ) {
00139 _buffer += std::string( s, c-s );
00140 logger::putStream( _group, _level, _file, _func, _line, _buffer );
00141 _buffer = std::string();
00142 s = c+1;
00143 }
00144 }
00145 if ( s < c )
00146 {
00147 _buffer += std::string( s, c-s );
00148 }
00149 }
00150 return n;
00151 }
00152
00153 private:
00154 std::string _group;
00155 LogLevel _level;
00156 const char * _file;
00157 const char * _func;
00158 int _line;
00159 std::string _buffer;
00160 };
00161
00163
00165
00166
00167
00168 class Loglinestream {
00169
00170 public:
00172 Loglinestream( const std::string & group_r, LogLevel level_r )
00173 : _mybuf( group_r, level_r )
00174 , _mystream( &_mybuf )
00175 {}
00177 ~Loglinestream()
00178 { _mystream.flush(); }
00179
00180 public:
00182 std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
00183 {
00184 _mybuf.tagSet( fil_r, fnc_r, lne_r );
00185 return _mystream;
00186 }
00187
00188 private:
00189 Loglinebuf _mybuf;
00190 std::ostream _mystream;
00191 };
00193
00195
00196
00197
00207 struct LogControlImpl
00208 {
00209 public:
00210 void excessive( bool onOff_r )
00211 { _excessive = onOff_r; }
00212
00214 void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
00215 { _lineWriter = writer_r; }
00216
00217 shared_ptr<LogControl::LineWriter> getLineWriter() const
00218 { return _lineWriter; }
00219
00221 void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
00222 {
00223 if ( format_r )
00224 _lineFormater = format_r;
00225 else
00226 _lineFormater.reset( new LogControl::LineFormater );
00227 }
00228
00229 void logfile( const Pathname & logfile_r )
00230 {
00231 if ( logfile_r.empty() )
00232 setLineWriter( shared_ptr<LogControl::LineWriter>() );
00233 else if ( logfile_r == Pathname( "-" ) )
00234 setLineWriter( shared_ptr<LogControl::LineWriter>(new StdErrWriter) );
00235 else
00236 setLineWriter( shared_ptr<LogControl::LineWriter>(new FileWriter(logfile_r)) );
00237 }
00238
00239 private:
00240 std::ostream _no_stream;
00241 bool _excessive;
00242
00243 shared_ptr<LogControl::LineFormater> _lineFormater;
00244 shared_ptr<LogControl::LineWriter> _lineWriter;
00245
00246 public:
00248 std::ostream & getStream( const std::string & group_r,
00249 LogLevel level_r,
00250 const char * file_r,
00251 const char * func_r,
00252 const int line_r )
00253 {
00254 if ( ! _lineWriter )
00255 return _no_stream;
00256 if ( level_r == E_XXX && !_excessive )
00257 return _no_stream;
00258
00259 if ( !_streamtable[group_r][level_r] )
00260 {
00261 _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
00262 }
00263 return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r );
00264 }
00265
00267 void putStream( const std::string & group_r,
00268 LogLevel level_r,
00269 const char * file_r,
00270 const char * func_r,
00271 int line_r,
00272 const std::string & message_r )
00273 {
00274 if ( _lineWriter )
00275 _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
00276 file_r, func_r, line_r,
00277 message_r ) );
00278 }
00279
00280 private:
00281 typedef shared_ptr<Loglinestream> StreamPtr;
00282 typedef std::map<LogLevel,StreamPtr> StreamSet;
00283 typedef std::map<std::string,StreamSet> StreamTable;
00285 StreamTable _streamtable;
00286
00287 private:
00291 LogControlImpl()
00292 : _no_stream( NULL )
00293 , _excessive( getenv("ZYPP_FULLLOG") )
00294 , _lineFormater( new LogControl::LineFormater )
00295 {
00296 if ( getenv("ZYPP_LOGFILE") )
00297 logfile( getenv("ZYPP_LOGFILE") );
00298 }
00299
00300 public:
00307 static LogControlImpl instance;
00308 };
00310
00311
00312 LogControlImpl LogControlImpl::instance;
00313
00315
00317 inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
00318 {
00319 return str << "LogControlImpl";
00320 }
00321
00323
00324
00325
00327
00329 std::ostream & getStream( const char * group_r,
00330 LogLevel level_r,
00331 const char * file_r,
00332 const char * func_r,
00333 const int line_r )
00334 {
00335 return LogControlImpl::instance.getStream( group_r,
00336 level_r,
00337 file_r,
00338 func_r,
00339 line_r );
00340 }
00341
00343 inline void putStream( const std::string & group_r, LogLevel level_r,
00344 const char * file_r, const char * func_r, int line_r,
00345 const std::string & buffer_r )
00346 {
00347 LogControlImpl::instance.putStream( group_r, level_r,
00348 file_r, func_r, line_r,
00349 buffer_r );
00350 }
00351
00353 }
00355
00357
00358
00359
00360
00362
00363 using logger::LogControlImpl;
00364
00365 void LogControl::logfile( const Pathname & logfile_r )
00366 { LogControlImpl::instance.logfile( logfile_r ); }
00367
00368 void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
00369 { LogControlImpl::instance.setLineWriter( writer_r ); }
00370
00371 void LogControl::logNothing()
00372 { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>() ); }
00373
00374 void LogControl::logToStdErr()
00375 { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>( new logger::StdErrWriter ) ); }
00376
00378
00379
00380
00382 LogControl::TmpExcessive::TmpExcessive()
00383 { LogControlImpl::instance.excessive( true ); }
00384 LogControl::TmpExcessive::~TmpExcessive()
00385 { LogControlImpl::instance.excessive( false ); }
00386
00388
00389
00390
00392 LogControl::TmpLineWriter::TmpLineWriter( const shared_ptr<LineWriter> & writer_r )
00393 : _writer( LogControlImpl::instance.getLineWriter() )
00394 { LogControlImpl::instance.setLineWriter( writer_r ); }
00395 LogControl::TmpLineWriter::~TmpLineWriter()
00396 { LogControlImpl::instance.setLineWriter( _writer ); }
00397
00398
00399
00400
00401
00402 std::ostream & operator<<( std::ostream & str, const LogControl & obj )
00403 {
00404 return str << LogControlImpl::instance;
00405 }
00406
00408 }
00411 }