libzypp  17.14.0
LogControl.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <fstream>
14 #include <string>
15 
16 #include "zypp/base/Logger.h"
17 #include "zypp/base/LogControl.h"
19 #include "zypp/base/String.h"
20 #include "zypp/Date.h"
21 #include "zypp/PathInfo.h"
22 
23 using std::endl;
24 
26 namespace zypp
27 {
28 
29 #ifndef ZYPP_NDEBUG
30  namespace debug
31  {
32  void osdlog( const std::string & msg_r, unsigned level_r )
33  {
34  // Fg::Black: 30 Bg: 40 Attr::Normal: 22;27
35  // Fg::Red: 31 ... Attr::Bright: 1
36  // Fg::Green: 32 Attr::Reverse: 7
37  // Fg::Yellow: 33
38  // Fg::Blue: 34
39  // Fg::Magenta: 35
40  // Fg::Cyan: 36
41  // Fg::White: 37
42  // Fg::Default: 39
43  static const char * ansi[] = {
44  "\033[37;40m", // 0 w
45  "\033[36;40m", // 1 c
46  "\033[33;1;40m", // 2 y
47  "\033[32;40m", // 3 g
48  "\033[31;1;40m", // 4 r
49  "\033[35;40m", // 5 m
50  };
51  static const unsigned n = sizeof(ansi)/sizeof(const char *);
52  switch ( level_r )
53  {
54  case 'w': level_r = 0; break;
55  case 'c': level_r = 1; break;
56  case 'y': level_r = 2; break;
57  case 'g': level_r = 3; break;
58  case 'r': level_r = 4; break;
59  case 'm': level_r = 5; break;
60  }
61  std::cerr << ansi[level_r%n] << "OSD[" << msg_r << "]\033[0m" << std::endl;
62  }
63 
64 
65  unsigned TraceLeave::_depth = 0;
66 
67  TraceLeave::TraceLeave( const char * file_r, const char * fnc_r, int line_r )
68  : _file( std::move(file_r) )
69  , _fnc( std::move(fnc_r) )
70  , _line( line_r )
71  {
72  //std::string::size_type p( _file.find_last_of( '/' ) );
73  //if ( p != std::string::npos )
74  //_file.erase( 0, p+1 );
75  USR << ">>> " << std::string(_depth++,'>') << " " << _file << "(" << _fnc << "):" << _line << endl;
76  }
77 
79  { USR << "<<< " << std::string(--_depth,'<') << " " << _file << "(" << _fnc << "):" << _line << endl; }
80 }
81 #endif // ZYPP_NDEBUG
82 
84  namespace log
85  {
86 
88  : StreamLineWriter( std::cout )
89  {}
90 
92  : StreamLineWriter( std::cerr )
93  {}
94 
95  FileLineWriter::FileLineWriter( const Pathname & file_r, mode_t mode_r )
96  {
97  if ( file_r == Pathname("-") )
98  {
99  _str = &std::cerr;
100  }
101  else
102  {
103  if ( mode_r )
104  {
105  // not filesystem::assert_file as filesystem:: functions log,
106  // and this FileWriter is not yet in place.
107  int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r );
108  if ( fd != -1 )
109  ::close( fd );
110  }
111  // set unbuffered write
112  std::ofstream * fstr = 0;
113  _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) );
114  fstr->rdbuf()->pubsetbuf(0,0);
115  _str = &(*fstr);
116  }
117  }
118 
120  } // namespace log
122 
124  namespace base
125  {
126 
128  // LineFormater
130  std::string LogControl::LineFormater::format( const std::string & group_r,
131  logger::LogLevel level_r,
132  const char * file_r,
133  const char * func_r,
134  int line_r,
135  const std::string & message_r )
136  {
137  static char hostname[1024];
138  static char nohostname[] = "unknown";
139  std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
140  return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
141  now.c_str(), level_r,
142  ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
143  getpid(),
144  group_r.c_str(),
145  file_r, func_r, line_r,
146  message_r.c_str() );
147  }
148 
150  namespace logger
151  {
152 
153  inline void putStream( const std::string & group_r, LogLevel level_r,
154  const char * file_r, const char * func_r, int line_r,
155  const std::string & buffer_r );
156 
158  //
159  // CLASS NAME : Loglinebuf
160  //
161  class Loglinebuf : public std::streambuf {
162 
163  public:
165  Loglinebuf( const std::string & group_r, LogLevel level_r )
166  : _group( group_r )
167  , _level( level_r )
168  , _file( "" )
169  , _func( "" )
170  , _line( -1 )
171  {}
174  {
175  if ( !_buffer.empty() )
176  writeout( "\n", 1 );
177  }
178 
180  void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
181  {
182  _file = fil_r;
183  _func = fnc_r;
184  _line = lne_r;
185  }
186 
187  private:
189  virtual std::streamsize xsputn( const char * s, std::streamsize n )
190  { return writeout( s, n ); }
192  virtual int overflow( int ch = EOF )
193  {
194  if ( ch != EOF )
195  {
196  char tmp = ch;
197  writeout( &tmp, 1 );
198  }
199  return 0;
200  }
202  virtual int writeout( const char* s, std::streamsize n )
203  {
204  //logger::putStream( _group, _level, _file, _func, _line, _buffer );
205  //return n;
206  if ( s && n )
207  {
208  const char * c = s;
209  for ( int i = 0; i < n; ++i, ++c )
210  {
211  if ( *c == '\n' ) {
212  _buffer += std::string( s, c-s );
213  logger::putStream( _group, _level, _file, _func, _line, _buffer );
214  _buffer = std::string();
215  s = c+1;
216  }
217  }
218  if ( s < c )
219  {
220  _buffer += std::string( s, c-s );
221  }
222  }
223  return n;
224  }
225 
226  private:
227  std::string _group;
229  const char * _file;
230  const char * _func;
231  int _line;
232  std::string _buffer;
233  };
234 
236 
238  //
239  // CLASS NAME : Loglinestream
240  //
242 
243  public:
245  Loglinestream( const std::string & group_r, LogLevel level_r )
246  : _mybuf( group_r, level_r )
247  , _mystream( &_mybuf )
248  {}
251  { _mystream.flush(); }
252 
253  public:
255  std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
256  {
257  _mybuf.tagSet( fil_r, fnc_r, lne_r );
258  return _mystream;
259  }
260 
261  private:
263  std::ostream _mystream;
264  };
266 
268  //
269  // CLASS NAME : LogControlImpl
270  //
281  {
282  public:
283  bool isExcessive()
284  { return _excessive; }
285 
286  void excessive( bool onOff_r )
287  { _excessive = onOff_r; }
288 
290  void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
291  { _lineWriter = writer_r; }
292 
293  shared_ptr<LogControl::LineWriter> getLineWriter() const
294  { return _lineWriter; }
295 
297  void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
298  {
299  if ( format_r )
300  _lineFormater = format_r;
301  else
302  _lineFormater.reset( new LogControl::LineFormater );
303  }
304 
305  void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
306  {
307  if ( logfile_r.empty() )
308  setLineWriter( shared_ptr<LogControl::LineWriter>() );
309  else if ( logfile_r == Pathname( "-" ) )
310  setLineWriter( shared_ptr<LogControl::LineWriter>(new log::StderrLineWriter) );
311  else
312  setLineWriter( shared_ptr<LogControl::LineWriter>(new log::FileLineWriter(logfile_r, mode_r)) );
313  }
314 
315  private:
316  std::ostream _no_stream;
318 
319  shared_ptr<LogControl::LineFormater> _lineFormater;
320  shared_ptr<LogControl::LineWriter> _lineWriter;
321 
322  public:
324  std::ostream & getStream( const std::string & group_r,
325  LogLevel level_r,
326  const char * file_r,
327  const char * func_r,
328  const int line_r )
329  {
330  if ( ! _lineWriter )
331  return _no_stream;
332  if ( level_r == E_XXX && !_excessive )
333  return _no_stream;
334 
335  if ( !_streamtable[group_r][level_r] )
336  {
337  _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
338  }
339  std::ostream & ret( _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ) );
340  if ( !ret )
341  {
342  ret.clear();
343  ret << "---<RESET LOGSTREAM FROM FAILED STATE]" << endl;
344  }
345  return ret;
346  }
347 
349  void putStream( const std::string & group_r,
350  LogLevel level_r,
351  const char * file_r,
352  const char * func_r,
353  int line_r,
354  const std::string & message_r )
355  {
356  if ( _lineWriter )
357  _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
358  file_r, func_r, line_r,
359  message_r ) );
360  }
361 
362  private:
363  typedef shared_ptr<Loglinestream> StreamPtr;
364  typedef std::map<LogLevel,StreamPtr> StreamSet;
365  typedef std::map<std::string,StreamSet> StreamTable;
368 
369  private:
374  : _no_stream( NULL )
375  , _excessive( getenv("ZYPP_FULLLOG") )
376  , _lineFormater( new LogControl::LineFormater )
377  {
378  if ( getenv("ZYPP_LOGFILE") )
379  logfile( getenv("ZYPP_LOGFILE") );
380 
381  if ( getenv("ZYPP_PROFILING") )
382  {
383  shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater);
384  setLineFormater(formater);
385  }
386  }
387 
389  {
390  _lineWriter.reset();
391  }
392 
393  public:
400  static LogControlImpl & instance();
401  };
403 
404  // 'THE' LogControlImpl singleton
406  {
407  static LogControlImpl _instance;
408  return _instance;
409  }
410 
412 
414  inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
415  {
416  return str << "LogControlImpl";
417  }
418 
420  //
421  // Access from logger::
422  //
424 
425  std::ostream & getStream( const char * group_r,
426  LogLevel level_r,
427  const char * file_r,
428  const char * func_r,
429  const int line_r )
430  {
431  return LogControlImpl::instance().getStream( group_r,
432  level_r,
433  file_r,
434  func_r,
435  line_r );
436  }
437 
439  inline void putStream( const std::string & group_r, LogLevel level_r,
440  const char * file_r, const char * func_r, int line_r,
441  const std::string & buffer_r )
442  {
443  LogControlImpl::instance().putStream( group_r, level_r,
444  file_r, func_r, line_r,
445  buffer_r );
446  }
447 
448  bool isExcessive()
449  { return LogControlImpl::instance().isExcessive(); }
450 
452  } // namespace logger
454 
456  //
457  // CLASS NAME : LogControl
458  // Forward to LogControlImpl singleton.
459  //
461 
462  using logger::LogControlImpl;
463 
464  void LogControl::logfile( const Pathname & logfile_r )
465  { LogControlImpl::instance().logfile( logfile_r ); }
466 
467  void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
468  { LogControlImpl::instance().logfile( logfile_r, mode_r ); }
469 
470  shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const
472 
473  void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
474  { LogControlImpl::instance().setLineWriter( writer_r ); }
475 
476  void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r )
477  { LogControlImpl::instance().setLineFormater( formater_r ); }
478 
480  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>() ); }
481 
483  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) ); }
484 
486  //
487  // LogControl::TmpExcessive
488  //
491  { LogControlImpl::instance().excessive( true ); }
493  { LogControlImpl::instance().excessive( false ); }
494 
495  /******************************************************************
496  **
497  ** FUNCTION NAME : operator<<
498  ** FUNCTION TYPE : std::ostream &
499  */
500  std::ostream & operator<<( std::ostream & str, const LogControl & obj )
501  {
502  return str << LogControlImpl::instance();
503  }
504 
506  } // namespace base
509 } // namespace zypp
std::map< LogLevel, StreamPtr > StreamSet
Definition: LogControl.cc:364
LogLevel
Definition of log levels.
Definition: Logger.h:118
std::ostream & getStream(const std::string &group_r, LogLevel level_r, const char *file_r, const char *func_r, const int line_r)
Provide the log stream to write (logger interface)
Definition: LogControl.cc:324
Base class for ostream based LineWriter.
Definition: LogControl.h:43
void tagSet(const char *fil_r, const char *fnc_r, int lne_r)
Definition: LogControl.cc:180
Loglinestream(const std::string &group_r, LogLevel level_r)
Definition: LogControl.cc:245
const char * c_str() const
String representation.
Definition: Pathname.h:109
String related utilities and Regular expression matching.
Definition: Arch.h:344
LineWriter to file.
Definition: LogControl.h:71
If you want to format loglines by yourself, derive from this, and overload format.
Definition: LogControl.h:113
LineWriter to stderr.
Definition: LogControl.h:62
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
void setLineWriter(const shared_ptr< LogControl::LineWriter > &writer_r)
NULL _lineWriter indicates no loggin.
Definition: LogControl.cc:290
void logfile(const Pathname &logfile_r, mode_t mode_r=0640)
Definition: LogControl.cc:305
void logfile(const Pathname &logfile_r)
Set path for the logfile.
Definition: LogControl.cc:464
void osdlog(const std::string &msg_r, unsigned level_r)
Definition: LogControl.cc:32
static LogControl instance()
Singleton access.
Definition: LogControl.h:101
std::ostream & operator<<(std::ostream &str, const LogControlImpl &obj)
Definition: LogControl.cc:414
void setLineWriter(const shared_ptr< LineWriter > &writer_r)
Assign a LineWriter.
Definition: LogControl.cc:473
void logToStdErr()
Log to std::err.
Definition: LogControl.cc:482
bool empty() const
Test for an empty path.
Definition: Pathname.h:113
const char * _fnc
Definition: Logger.h:39
TraceLeave(const TraceLeave &)=delete
const std::string & _buffer
Definition: PluginScript.cc:62
shared_ptr< LogControl::LineWriter > getLineWriter() const
Definition: LogControl.cc:293
const std::string & asString() const
String representation.
Definition: Pathname.h:90
friend std::ostream & operator<<(std::ostream &str, const LogControl &obj)
Definition: LogControl.cc:500
#define USR
Definition: Logger.h:84
virtual int overflow(int ch=EOF)
Definition: LogControl.cc:192
void setLineFormater(const shared_ptr< LogControl::LineFormater > &format_r)
Assert _lineFormater is not NULL.
Definition: LogControl.cc:297
shared_ptr< LogControl::LineFormater > _lineFormater
Definition: LogControl.cc:319
std::ostream & getStream(const char *fil_r, const char *fnc_r, int lne_r)
Definition: LogControl.cc:255
std::map< std::string, StreamSet > StreamTable
Definition: LogControl.cc:365
static unsigned _depth
Definition: Logger.h:37
void logNothing()
Turn off logging.
Definition: LogControl.cc:479
virtual std::string format(const std::string &, logger::LogLevel, const char *, const char *, int, const std::string &)
Definition: LogControl.cc:130
Maintain logfile related options.
Definition: LogControl.h:95
virtual int writeout(const char *s, std::streamsize n)
Definition: LogControl.cc:202
void putStream(const std::string &group_r, LogLevel level_r, const char *file_r, const char *func_r, int line_r, const std::string &buffer_r)
That's what Loglinebuf calls.
Definition: LogControl.cc:439
shared_ptr< LogControl::LineWriter > _lineWriter
Definition: LogControl.cc:320
static Date now()
Return the current time.
Definition: Date.h:78
void putStream(const std::string &group_r, LogLevel level_r, const char *file_r, const char *func_r, int line_r, const std::string &message_r)
Format and write out a logline from Loglinebuf.
Definition: LogControl.cc:349
virtual std::streamsize xsputn(const char *s, std::streamsize n)
Definition: LogControl.cc:189
shared_ptr< LineWriter > getLineWriter() const
Get the current LineWriter.
Definition: LogControl.cc:470
static LogControlImpl & instance()
The LogControlImpl singleton.
Definition: LogControl.cc:405
Loglinebuf(const std::string &group_r, LogLevel level_r)
Definition: LogControl.cc:165
Pathname _file
Definition: SystemCheck.cc:34
void setLineFormater(const shared_ptr< LineFormater > &formater_r)
Assign a LineFormater.
Definition: LogControl.cc:476
shared_ptr< void > _outs
Definition: LogControl.h:75
shared_ptr< Loglinestream > StreamPtr
Definition: LogControl.cc:363
const char * _file
Definition: Logger.h:38
Excessive logging.
Definition: Logger.h:119
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
std::ostream & getStream(const char *group_r, LogLevel level_r, const char *file_r, const char *func_r, const int line_r)
Return a log stream to write on.
Definition: LogControl.cc:425
LogControl implementation (Singleton).
Definition: LogControl.cc:280
FileLineWriter(const Pathname &file_r, mode_t mode_r=0)
Definition: LogControl.cc:95
StreamTable _streamtable
one streambuffer per group and level
Definition: LogControl.cc:367