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
00029 namespace base
00030 {
00031
00033
00035 std::string LogControl::LineFormater::format( const std::string & group_r,
00036 logger::LogLevel level_r,
00037 const char * file_r,
00038 const char * func_r,
00039 int line_r,
00040 const std::string & message_r )
00041 {
00042 static char hostname[1024];
00043 static char nohostname[] = "unknown";
00044 std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
00045 return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
00046 now.c_str(), level_r,
00047 ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
00048 getpid(),
00049 group_r.c_str(),
00050 file_r, func_r, line_r,
00051 message_r.c_str() );
00052 }
00053
00055 namespace logger
00056 {
00057
00059
00061 struct StdErrWriter : public LogControl::LineWriter
00062 {
00063 virtual void writeOut( const std::string & formated_r )
00064 {
00065 std::cerr << formated_r << endl;
00066 }
00067 };
00069 struct FileWriter : public LogControl::LineWriter
00070 {
00071 FileWriter( const Pathname & logfile_r, mode_t mode_r )
00072 {
00073
00074 _outs.rdbuf()->pubsetbuf(0,0);
00075 _outs.open( logfile_r.asString().c_str(), std::ios_base::app );
00076
00077
00078 ::chmod( logfile_r.asString().c_str(), mode_r );
00079 }
00080 std::ofstream _outs;
00081
00082 virtual void writeOut( const std::string & formated_r )
00083 {
00084 _outs << formated_r << endl;
00085 }
00086 };
00088
00089 inline void putStream( const std::string & group_r, LogLevel level_r,
00090 const char * file_r, const char * func_r, int line_r,
00091 const std::string & buffer_r );
00092
00094
00095
00096
00097 class Loglinebuf : public std::streambuf {
00098
00099 public:
00101 Loglinebuf( const std::string & group_r, LogLevel level_r )
00102 : _group( group_r )
00103 , _level( level_r )
00104 , _file( "" )
00105 , _func( "" )
00106 , _line( -1 )
00107 {}
00109 ~Loglinebuf()
00110 {
00111 if ( !_buffer.empty() )
00112 writeout( "\n", 1 );
00113 }
00114
00116 void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
00117 {
00118 _file = fil_r;
00119 _func = fnc_r;
00120 _line = lne_r;
00121 }
00122
00123 private:
00125 virtual std::streamsize xsputn( const char * s, std::streamsize n )
00126 { return writeout( s, n ); }
00128 virtual int overflow( int ch = EOF )
00129 {
00130 if ( ch != EOF )
00131 {
00132 char tmp = ch;
00133 writeout( &tmp, 1 );
00134 }
00135 return 0;
00136 }
00138 virtual int writeout( const char* s, std::streamsize n )
00139 {
00140 if ( s && n )
00141 {
00142 const char * c = s;
00143 for ( int i = 0; i < n; ++i, ++c )
00144 {
00145 if ( *c == '\n' ) {
00146 _buffer += std::string( s, c-s );
00147 logger::putStream( _group, _level, _file, _func, _line, _buffer );
00148 _buffer = std::string();
00149 s = c+1;
00150 }
00151 }
00152 if ( s < c )
00153 {
00154 _buffer += std::string( s, c-s );
00155 }
00156 }
00157 return n;
00158 }
00159
00160 private:
00161 std::string _group;
00162 LogLevel _level;
00163 const char * _file;
00164 const char * _func;
00165 int _line;
00166 std::string _buffer;
00167 };
00168
00170
00172
00173
00174
00175 class Loglinestream {
00176
00177 public:
00179 Loglinestream( const std::string & group_r, LogLevel level_r )
00180 : _mybuf( group_r, level_r )
00181 , _mystream( &_mybuf )
00182 {}
00184 ~Loglinestream()
00185 { _mystream.flush(); }
00186
00187 public:
00189 std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
00190 {
00191 _mybuf.tagSet( fil_r, fnc_r, lne_r );
00192 return _mystream;
00193 }
00194
00195 private:
00196 Loglinebuf _mybuf;
00197 std::ostream _mystream;
00198 };
00200
00202
00203
00204
00214 struct LogControlImpl
00215 {
00216 public:
00217 void excessive( bool onOff_r )
00218 { _excessive = onOff_r; }
00219
00221 void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
00222 { _lineWriter = writer_r; }
00223
00224 shared_ptr<LogControl::LineWriter> getLineWriter() const
00225 { return _lineWriter; }
00226
00228 void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
00229 {
00230 if ( format_r )
00231 _lineFormater = format_r;
00232 else
00233 _lineFormater.reset( new LogControl::LineFormater );
00234 }
00235
00236 void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
00237 {
00238 if ( logfile_r.empty() )
00239 setLineWriter( shared_ptr<LogControl::LineWriter>() );
00240 else if ( logfile_r == Pathname( "-" ) )
00241 setLineWriter( shared_ptr<LogControl::LineWriter>(new StdErrWriter) );
00242 else
00243 setLineWriter( shared_ptr<LogControl::LineWriter>(new FileWriter(logfile_r, mode_r)) );
00244 }
00245
00246 private:
00247 std::ostream _no_stream;
00248 bool _excessive;
00249
00250 shared_ptr<LogControl::LineFormater> _lineFormater;
00251 shared_ptr<LogControl::LineWriter> _lineWriter;
00252
00253 public:
00255 std::ostream & getStream( const std::string & group_r,
00256 LogLevel level_r,
00257 const char * file_r,
00258 const char * func_r,
00259 const int line_r )
00260 {
00261 if ( ! _lineWriter )
00262 return _no_stream;
00263 if ( level_r == E_XXX && !_excessive )
00264 return _no_stream;
00265
00266 if ( !_streamtable[group_r][level_r] )
00267 {
00268 _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
00269 }
00270 return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r );
00271 }
00272
00274 void putStream( const std::string & group_r,
00275 LogLevel level_r,
00276 const char * file_r,
00277 const char * func_r,
00278 int line_r,
00279 const std::string & message_r )
00280 {
00281 if ( _lineWriter )
00282 _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
00283 file_r, func_r, line_r,
00284 message_r ) );
00285 }
00286
00287 private:
00288 typedef shared_ptr<Loglinestream> StreamPtr;
00289 typedef std::map<LogLevel,StreamPtr> StreamSet;
00290 typedef std::map<std::string,StreamSet> StreamTable;
00292 StreamTable _streamtable;
00293
00294 private:
00298 LogControlImpl()
00299 : _no_stream( NULL )
00300 , _excessive( getenv("ZYPP_FULLLOG") )
00301 , _lineFormater( new LogControl::LineFormater )
00302 {
00303 if ( getenv("ZYPP_LOGFILE") )
00304 logfile( getenv("ZYPP_LOGFILE") );
00305
00306 if ( getenv("ZYPP_PROFILING") )
00307 {
00308 shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater);
00309 setLineFormater(formater);
00310 }
00311 }
00312
00313 public:
00320 static LogControlImpl instance;
00321 };
00323
00324
00325 LogControlImpl LogControlImpl::instance;
00326
00328
00330 inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
00331 {
00332 return str << "LogControlImpl";
00333 }
00334
00336
00337
00338
00340
00341 std::ostream & getStream( const char * group_r,
00342 LogLevel level_r,
00343 const char * file_r,
00344 const char * func_r,
00345 const int line_r )
00346 {
00347 return LogControlImpl::instance.getStream( group_r,
00348 level_r,
00349 file_r,
00350 func_r,
00351 line_r );
00352 }
00353
00355 inline void putStream( const std::string & group_r, LogLevel level_r,
00356 const char * file_r, const char * func_r, int line_r,
00357 const std::string & buffer_r )
00358 {
00359 LogControlImpl::instance.putStream( group_r, level_r,
00360 file_r, func_r, line_r,
00361 buffer_r );
00362 }
00363
00365 }
00367
00369
00370
00371
00372
00374
00375 using logger::LogControlImpl;
00376
00377 void LogControl::logfile( const Pathname & logfile_r )
00378 { LogControlImpl::instance.logfile( logfile_r ); }
00379
00380 void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
00381 { LogControlImpl::instance.logfile( logfile_r, mode_r ); }
00382
00383 void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
00384 { LogControlImpl::instance.setLineWriter( writer_r ); }
00385
00386 void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r )
00387 { LogControlImpl::instance.setLineFormater( formater_r ); }
00388
00389 void LogControl::logNothing()
00390 { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>() ); }
00391
00392 void LogControl::logToStdErr()
00393 { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>( new logger::StdErrWriter ) ); }
00394
00396
00397
00398
00400 LogControl::TmpExcessive::TmpExcessive()
00401 { LogControlImpl::instance.excessive( true ); }
00402 LogControl::TmpExcessive::~TmpExcessive()
00403 { LogControlImpl::instance.excessive( false ); }
00404
00406
00407
00408
00410 LogControl::TmpLineWriter::TmpLineWriter( const shared_ptr<LineWriter> & writer_r )
00411 : _writer( LogControlImpl::instance.getLineWriter() )
00412 { LogControlImpl::instance.setLineWriter( writer_r ); }
00413 LogControl::TmpLineWriter::~TmpLineWriter()
00414 { LogControlImpl::instance.setLineWriter( _writer ); }
00415
00416
00417
00418
00419
00420 std::ostream & operator<<( std::ostream & str, const LogControl & obj )
00421 {
00422 return str << LogControlImpl::instance;
00423 }
00424
00426 }
00429 }