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 #include "zypp/PathInfo.h"
00021
00022 using std::endl;
00023
00025 namespace zypp
00026 {
00027
00028 namespace base
00029 {
00030
00032
00034 std::string LogControl::LineFormater::format( const std::string & group_r,
00035 logger::LogLevel level_r,
00036 const char * file_r,
00037 const char * func_r,
00038 int line_r,
00039 const std::string & message_r )
00040 {
00041 static char hostname[1024];
00042 static char nohostname[] = "unknown";
00043 std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
00044 return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
00045 now.c_str(), level_r,
00046 ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
00047 getpid(),
00048 group_r.c_str(),
00049 file_r, func_r, line_r,
00050 message_r.c_str() );
00051 }
00052
00054 namespace logger
00055 {
00056
00058
00060 struct StdErrWriter : public LogControl::LineWriter
00061 {
00062 virtual void writeOut( const std::string & formated_r )
00063 {
00064 std::cerr << formated_r << endl;
00065 }
00066 };
00068 struct FileWriter : public LogControl::LineWriter
00069 {
00070 FileWriter( const Pathname & logfile_r, mode_t mode_r )
00071 {
00072
00073 _outs.rdbuf()->pubsetbuf(0,0);
00074 _outs.open( logfile_r.asString().c_str(), std::ios_base::app );
00075
00076
00077 ::chmod( logfile_r.asString().c_str(), mode_r );
00078 }
00079 std::ofstream _outs;
00080
00081 virtual void writeOut( const std::string & formated_r )
00082 {
00083 _outs << formated_r << endl;
00084 }
00085 };
00087
00088 inline void putStream( const std::string & group_r, LogLevel level_r,
00089 const char * file_r, const char * func_r, int line_r,
00090 const std::string & buffer_r );
00091
00093
00094
00095
00096 class Loglinebuf : public std::streambuf {
00097
00098 public:
00100 Loglinebuf( const std::string & group_r, LogLevel level_r )
00101 : _group( group_r )
00102 , _level( level_r )
00103 , _file( "" )
00104 , _func( "" )
00105 , _line( -1 )
00106 {}
00108 ~Loglinebuf()
00109 {
00110 if ( !_buffer.empty() )
00111 writeout( "\n", 1 );
00112 }
00113
00115 void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
00116 {
00117 _file = fil_r;
00118 _func = fnc_r;
00119 _line = lne_r;
00120 }
00121
00122 private:
00124 virtual std::streamsize xsputn( const char * s, std::streamsize n )
00125 { return writeout( s, n ); }
00127 virtual int overflow( int ch = EOF )
00128 {
00129 if ( ch != EOF )
00130 {
00131 char tmp = ch;
00132 writeout( &tmp, 1 );
00133 }
00134 return 0;
00135 }
00137 virtual int writeout( const char* s, std::streamsize n )
00138 {
00139 if ( s && n )
00140 {
00141 const char * c = s;
00142 for ( int i = 0; i < n; ++i, ++c )
00143 {
00144 if ( *c == '\n' ) {
00145 _buffer += std::string( s, c-s );
00146 logger::putStream( _group, _level, _file, _func, _line, _buffer );
00147 _buffer = std::string();
00148 s = c+1;
00149 }
00150 }
00151 if ( s < c )
00152 {
00153 _buffer += std::string( s, c-s );
00154 }
00155 }
00156 return n;
00157 }
00158
00159 private:
00160 std::string _group;
00161 LogLevel _level;
00162 const char * _file;
00163 const char * _func;
00164 int _line;
00165 std::string _buffer;
00166 };
00167
00169
00171
00172
00173
00174 class Loglinestream {
00175
00176 public:
00178 Loglinestream( const std::string & group_r, LogLevel level_r )
00179 : _mybuf( group_r, level_r )
00180 , _mystream( &_mybuf )
00181 {}
00183 ~Loglinestream()
00184 { _mystream.flush(); }
00185
00186 public:
00188 std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
00189 {
00190 _mybuf.tagSet( fil_r, fnc_r, lne_r );
00191 return _mystream;
00192 }
00193
00194 private:
00195 Loglinebuf _mybuf;
00196 std::ostream _mystream;
00197 };
00199
00201
00202
00203
00213 struct LogControlImpl
00214 {
00215 public:
00216 void excessive( bool onOff_r )
00217 { _excessive = onOff_r; }
00218
00220 void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
00221 { _lineWriter = writer_r; }
00222
00223 shared_ptr<LogControl::LineWriter> getLineWriter() const
00224 { return _lineWriter; }
00225
00227 void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
00228 {
00229 if ( format_r )
00230 _lineFormater = format_r;
00231 else
00232 _lineFormater.reset( new LogControl::LineFormater );
00233 }
00234
00235 void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
00236 {
00237 if ( logfile_r.empty() )
00238 setLineWriter( shared_ptr<LogControl::LineWriter>() );
00239 else if ( logfile_r == Pathname( "-" ) )
00240 setLineWriter( shared_ptr<LogControl::LineWriter>(new StdErrWriter) );
00241 else
00242 setLineWriter( shared_ptr<LogControl::LineWriter>(new FileWriter(logfile_r, mode_r)) );
00243 }
00244
00245 private:
00246 std::ostream _no_stream;
00247 bool _excessive;
00248
00249 shared_ptr<LogControl::LineFormater> _lineFormater;
00250 shared_ptr<LogControl::LineWriter> _lineWriter;
00251
00252 public:
00254 std::ostream & getStream( const std::string & group_r,
00255 LogLevel level_r,
00256 const char * file_r,
00257 const char * func_r,
00258 const int line_r )
00259 {
00260 if ( ! _lineWriter )
00261 return _no_stream;
00262 if ( level_r == E_XXX && !_excessive )
00263 return _no_stream;
00264
00265 if ( !_streamtable[group_r][level_r] )
00266 {
00267 _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
00268 }
00269 return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r );
00270 }
00271
00273 void putStream( const std::string & group_r,
00274 LogLevel level_r,
00275 const char * file_r,
00276 const char * func_r,
00277 int line_r,
00278 const std::string & message_r )
00279 {
00280 if ( _lineWriter )
00281 _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
00282 file_r, func_r, line_r,
00283 message_r ) );
00284 }
00285
00286 private:
00287 typedef shared_ptr<Loglinestream> StreamPtr;
00288 typedef std::map<LogLevel,StreamPtr> StreamSet;
00289 typedef std::map<std::string,StreamSet> StreamTable;
00291 StreamTable _streamtable;
00292
00293 private:
00297 LogControlImpl()
00298 : _no_stream( NULL )
00299 , _excessive( getenv("ZYPP_FULLLOG") )
00300 , _lineFormater( new LogControl::LineFormater )
00301 {
00302 if ( getenv("ZYPP_LOGFILE") )
00303 logfile( getenv("ZYPP_LOGFILE") );
00304 }
00305
00306 public:
00313 static LogControlImpl instance;
00314 };
00316
00317
00318 LogControlImpl LogControlImpl::instance;
00319
00321
00323 inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
00324 {
00325 return str << "LogControlImpl";
00326 }
00327
00329
00330
00331
00333
00335 std::ostream & getStream( const char * group_r,
00336 LogLevel level_r,
00337 const char * file_r,
00338 const char * func_r,
00339 const int line_r )
00340 {
00341 return LogControlImpl::instance.getStream( group_r,
00342 level_r,
00343 file_r,
00344 func_r,
00345 line_r );
00346 }
00347
00349 inline void putStream( const std::string & group_r, LogLevel level_r,
00350 const char * file_r, const char * func_r, int line_r,
00351 const std::string & buffer_r )
00352 {
00353 LogControlImpl::instance.putStream( group_r, level_r,
00354 file_r, func_r, line_r,
00355 buffer_r );
00356 }
00357
00359 }
00361
00363
00364
00365
00366
00368
00369 using logger::LogControlImpl;
00370
00371 void LogControl::logfile( const Pathname & logfile_r )
00372 { LogControlImpl::instance.logfile( logfile_r ); }
00373
00374 void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
00375 { LogControlImpl::instance.logfile( logfile_r, mode_r ); }
00376
00377 void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
00378 { LogControlImpl::instance.setLineWriter( writer_r ); }
00379
00380 void LogControl::logNothing()
00381 { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>() ); }
00382
00383 void LogControl::logToStdErr()
00384 { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>( new logger::StdErrWriter ) ); }
00385
00387
00388
00389
00391 LogControl::TmpExcessive::TmpExcessive()
00392 { LogControlImpl::instance.excessive( true ); }
00393 LogControl::TmpExcessive::~TmpExcessive()
00394 { LogControlImpl::instance.excessive( false ); }
00395
00397
00398
00399
00401 LogControl::TmpLineWriter::TmpLineWriter( const shared_ptr<LineWriter> & writer_r )
00402 : _writer( LogControlImpl::instance.getLineWriter() )
00403 { LogControlImpl::instance.setLineWriter( writer_r ); }
00404 LogControl::TmpLineWriter::~TmpLineWriter()
00405 { LogControlImpl::instance.setLineWriter( _writer ); }
00406
00407
00408
00409
00410
00411 std::ostream & operator<<( std::ostream & str, const LogControl & obj )
00412 {
00413 return str << LogControlImpl::instance;
00414 }
00415
00417 }
00420 }