libzypp  16.15.3
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 #endif // ZYPP_NDEBUG
65 
67  namespace log
68  {
69 
70  StdoutLineWriter::StdoutLineWriter()
71  : StreamLineWriter( std::cout )
72  {}
73 
75  : StreamLineWriter( std::cerr )
76  {}
77 
78  FileLineWriter::FileLineWriter( const Pathname & file_r, mode_t mode_r )
79  {
80  if ( file_r == Pathname("-") )
81  {
82  _str = &std::cerr;
83  }
84  else
85  {
86  if ( mode_r )
87  {
88  // not filesystem::assert_file as filesystem:: functions log,
89  // and this FileWriter is not yet in place.
90  int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r );
91  if ( fd != -1 )
92  ::close( fd );
93  }
94  // set unbuffered write
95  std::ofstream * fstr = 0;
96  _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) );
97  fstr->rdbuf()->pubsetbuf(0,0);
98  _str = &(*fstr);
99  }
100  }
101 
103  } // namespace log
105 
107  namespace base
108  {
109 
111  // LineFormater
113  std::string LogControl::LineFormater::format( const std::string & group_r,
114  logger::LogLevel level_r,
115  const char * file_r,
116  const char * func_r,
117  int line_r,
118  const std::string & message_r )
119  {
120  static char hostname[1024];
121  static char nohostname[] = "unknown";
122  std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
123  return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
124  now.c_str(), level_r,
125  ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
126  getpid(),
127  group_r.c_str(),
128  file_r, func_r, line_r,
129  message_r.c_str() );
130  }
131 
133  namespace logger
134  {
135 
136  inline void putStream( const std::string & group_r, LogLevel level_r,
137  const char * file_r, const char * func_r, int line_r,
138  const std::string & buffer_r );
139 
141  //
142  // CLASS NAME : Loglinebuf
143  //
144  class Loglinebuf : public std::streambuf {
145 
146  public:
148  Loglinebuf( const std::string & group_r, LogLevel level_r )
149  : _group( group_r )
150  , _level( level_r )
151  , _file( "" )
152  , _func( "" )
153  , _line( -1 )
154  {}
157  {
158  if ( !_buffer.empty() )
159  writeout( "\n", 1 );
160  }
161 
163  void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
164  {
165  _file = fil_r;
166  _func = fnc_r;
167  _line = lne_r;
168  }
169 
170  private:
172  virtual std::streamsize xsputn( const char * s, std::streamsize n )
173  { return writeout( s, n ); }
175  virtual int overflow( int ch = EOF )
176  {
177  if ( ch != EOF )
178  {
179  char tmp = ch;
180  writeout( &tmp, 1 );
181  }
182  return 0;
183  }
185  virtual int writeout( const char* s, std::streamsize n )
186  {
187  //logger::putStream( _group, _level, _file, _func, _line, _buffer );
188  //return n;
189  if ( s && n )
190  {
191  const char * c = s;
192  for ( int i = 0; i < n; ++i, ++c )
193  {
194  if ( *c == '\n' ) {
195  _buffer += std::string( s, c-s );
196  logger::putStream( _group, _level, _file, _func, _line, _buffer );
197  _buffer = std::string();
198  s = c+1;
199  }
200  }
201  if ( s < c )
202  {
203  _buffer += std::string( s, c-s );
204  }
205  }
206  return n;
207  }
208 
209  private:
210  std::string _group;
212  const char * _file;
213  const char * _func;
214  int _line;
215  std::string _buffer;
216  };
217 
219 
221  //
222  // CLASS NAME : Loglinestream
223  //
225 
226  public:
228  Loglinestream( const std::string & group_r, LogLevel level_r )
229  : _mybuf( group_r, level_r )
230  , _mystream( &_mybuf )
231  {}
234  { _mystream.flush(); }
235 
236  public:
238  std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
239  {
240  _mybuf.tagSet( fil_r, fnc_r, lne_r );
241  return _mystream;
242  }
243 
244  private:
246  std::ostream _mystream;
247  };
249 
251  //
252  // CLASS NAME : LogControlImpl
253  //
264  {
265  public:
266  bool isExcessive()
267  { return _excessive; }
268 
269  void excessive( bool onOff_r )
270  { _excessive = onOff_r; }
271 
273  void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
274  { _lineWriter = writer_r; }
275 
276  shared_ptr<LogControl::LineWriter> getLineWriter() const
277  { return _lineWriter; }
278 
280  void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
281  {
282  if ( format_r )
283  _lineFormater = format_r;
284  else
285  _lineFormater.reset( new LogControl::LineFormater );
286  }
287 
288  void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
289  {
290  if ( logfile_r.empty() )
291  setLineWriter( shared_ptr<LogControl::LineWriter>() );
292  else if ( logfile_r == Pathname( "-" ) )
293  setLineWriter( shared_ptr<LogControl::LineWriter>(new log::StderrLineWriter) );
294  else
295  setLineWriter( shared_ptr<LogControl::LineWriter>(new log::FileLineWriter(logfile_r, mode_r)) );
296  }
297 
298  private:
299  std::ostream _no_stream;
301 
302  shared_ptr<LogControl::LineFormater> _lineFormater;
303  shared_ptr<LogControl::LineWriter> _lineWriter;
304 
305  public:
307  std::ostream & getStream( const std::string & group_r,
308  LogLevel level_r,
309  const char * file_r,
310  const char * func_r,
311  const int line_r )
312  {
313  if ( ! _lineWriter )
314  return _no_stream;
315  if ( level_r == E_XXX && !_excessive )
316  return _no_stream;
317 
318  if ( !_streamtable[group_r][level_r] )
319  {
320  _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
321  }
322  return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r );
323  }
324 
326  void putStream( const std::string & group_r,
327  LogLevel level_r,
328  const char * file_r,
329  const char * func_r,
330  int line_r,
331  const std::string & message_r )
332  {
333  if ( _lineWriter )
334  _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
335  file_r, func_r, line_r,
336  message_r ) );
337  }
338 
339  private:
340  typedef shared_ptr<Loglinestream> StreamPtr;
341  typedef std::map<LogLevel,StreamPtr> StreamSet;
342  typedef std::map<std::string,StreamSet> StreamTable;
344  StreamTable _streamtable;
345 
346  private:
351  : _no_stream( NULL )
352  , _excessive( getenv("ZYPP_FULLLOG") )
353  , _lineFormater( new LogControl::LineFormater )
354  {
355  if ( getenv("ZYPP_LOGFILE") )
356  logfile( getenv("ZYPP_LOGFILE") );
357 
358  if ( getenv("ZYPP_PROFILING") )
359  {
360  shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater);
361  setLineFormater(formater);
362  }
363  }
364 
366  {
367  _lineWriter.reset();
368  }
369 
370  public:
377  static LogControlImpl & instance();
378  };
380 
381  // 'THE' LogControlImpl singleton
382  inline LogControlImpl & LogControlImpl::instance()
383  {
384  static LogControlImpl _instance;
385  return _instance;
386  }
387 
389 
391  inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
392  {
393  return str << "LogControlImpl";
394  }
395 
397  //
398  // Access from logger::
399  //
401 
402  std::ostream & getStream( const char * group_r,
403  LogLevel level_r,
404  const char * file_r,
405  const char * func_r,
406  const int line_r )
407  {
408  return LogControlImpl::instance().getStream( group_r,
409  level_r,
410  file_r,
411  func_r,
412  line_r );
413  }
414 
416  inline void putStream( const std::string & group_r, LogLevel level_r,
417  const char * file_r, const char * func_r, int line_r,
418  const std::string & buffer_r )
419  {
420  LogControlImpl::instance().putStream( group_r, level_r,
421  file_r, func_r, line_r,
422  buffer_r );
423  }
424 
425  bool isExcessive()
426  { return LogControlImpl::instance().isExcessive(); }
427 
429  } // namespace logger
431 
433  //
434  // CLASS NAME : LogControl
435  // Forward to LogControlImpl singleton.
436  //
438 
440 
441  void LogControl::logfile( const Pathname & logfile_r )
442  { LogControlImpl::instance().logfile( logfile_r ); }
443 
444  void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
445  { LogControlImpl::instance().logfile( logfile_r, mode_r ); }
446 
447  shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const
448  { return LogControlImpl::instance().getLineWriter(); }
449 
450  void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
451  { LogControlImpl::instance().setLineWriter( writer_r ); }
452 
453  void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r )
454  { LogControlImpl::instance().setLineFormater( formater_r ); }
455 
456  void LogControl::logNothing()
457  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>() ); }
458 
459  void LogControl::logToStdErr()
460  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) ); }
461 
463  //
464  // LogControl::TmpExcessive
465  //
467  LogControl::TmpExcessive::TmpExcessive()
468  { LogControlImpl::instance().excessive( true ); }
469  LogControl::TmpExcessive::~TmpExcessive()
470  { LogControlImpl::instance().excessive( false ); }
471 
472  /******************************************************************
473  **
474  ** FUNCTION NAME : operator<<
475  ** FUNCTION TYPE : std::ostream &
476  */
477  std::ostream & operator<<( std::ostream & str, const LogControl & obj )
478  {
479  return str << LogControlImpl::instance();
480  }
481 
483  } // namespace base
486 } // namespace zypp
std::map< LogLevel, StreamPtr > StreamSet
Definition: LogControl.cc:341
LogLevel
Definition of log levels.
Definition: Logger.h:103
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:307
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:163
shared_ptr< LogControl::LineWriter > getLineWriter() const
Definition: LogControl.cc:276
Loglinestream(const std::string &group_r, LogLevel level_r)
Definition: LogControl.cc:228
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:273
void logfile(const Pathname &logfile_r, mode_t mode_r=0640)
Definition: LogControl.cc:288
void osdlog(const std::string &msg_r, unsigned level_r)
Definition: LogControl.cc:32
std::ostream & operator<<(std::ostream &str, const LogControlImpl &obj)
Definition: LogControl.cc:391
std::ostream & operator<<(std::ostream &str, const Exception &obj)
Definition: Exception.cc:120
const std::string & _buffer
Definition: PluginScript.cc:62
virtual int overflow(int ch=EOF)
Definition: LogControl.cc:175
void setLineFormater(const shared_ptr< LogControl::LineFormater > &format_r)
Assert _lineFormater is not NULL.
Definition: LogControl.cc:280
shared_ptr< LogControl::LineFormater > _lineFormater
Definition: LogControl.cc:302
std::ostream & getStream(const char *fil_r, const char *fnc_r, int lne_r)
Definition: LogControl.cc:238
std::map< std::string, StreamSet > StreamTable
Definition: LogControl.cc:342
Maintain logfile related options.
Definition: LogControl.h:95
virtual int writeout(const char *s, std::streamsize n)
Definition: LogControl.cc:185
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&#39;s what Loglinebuf calls.
Definition: LogControl.cc:416
shared_ptr< LogControl::LineWriter > _lineWriter
Definition: LogControl.cc:303
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:326
virtual std::streamsize xsputn(const char *s, std::streamsize n)
Definition: LogControl.cc:172
Loglinebuf(const std::string &group_r, LogLevel level_r)
Definition: LogControl.cc:148
Pathname _file
Definition: SystemCheck.cc:34
shared_ptr< Loglinestream > StreamPtr
Definition: LogControl.cc:340
Excessive logging.
Definition: Logger.h:104
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:402
LogControl implementation (Singleton).
Definition: LogControl.cc:263
FileLineWriter(const Pathname &file_r, mode_t mode_r=0)
Definition: LogControl.cc:78
StreamTable _streamtable
one streambuffer per group and level
Definition: LogControl.cc:344