libzypp  15.28.6
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 
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  std::ostream & ret( _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ) );
323  if ( !ret )
324  {
325  ret.clear();
326  ret << "---<RESET LOGSTREAM FROM FAILED STATE]" << endl;
327  }
328  return ret;
329  }
330 
332  void putStream( const std::string & group_r,
333  LogLevel level_r,
334  const char * file_r,
335  const char * func_r,
336  int line_r,
337  const std::string & message_r )
338  {
339  if ( _lineWriter )
340  _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
341  file_r, func_r, line_r,
342  message_r ) );
343  }
344 
345  private:
346  typedef shared_ptr<Loglinestream> StreamPtr;
347  typedef std::map<LogLevel,StreamPtr> StreamSet;
348  typedef std::map<std::string,StreamSet> StreamTable;
351 
352  private:
357  : _no_stream( NULL )
358  , _excessive( getenv("ZYPP_FULLLOG") )
359  , _lineFormater( new LogControl::LineFormater )
360  {
361  if ( getenv("ZYPP_LOGFILE") )
362  logfile( getenv("ZYPP_LOGFILE") );
363 
364  if ( getenv("ZYPP_PROFILING") )
365  {
366  shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater);
367  setLineFormater(formater);
368  }
369  }
370 
372  {
373  _lineWriter.reset();
374  }
375 
376  public:
383  static LogControlImpl & instance();
384  };
386 
387  // 'THE' LogControlImpl singleton
388  inline LogControlImpl & LogControlImpl::instance()
389  {
390  static LogControlImpl _instance;
391  return _instance;
392  }
393 
395 
397  inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
398  {
399  return str << "LogControlImpl";
400  }
401 
403  //
404  // Access from logger::
405  //
407 
408  std::ostream & getStream( const char * group_r,
409  LogLevel level_r,
410  const char * file_r,
411  const char * func_r,
412  const int line_r )
413  {
414  return LogControlImpl::instance().getStream( group_r,
415  level_r,
416  file_r,
417  func_r,
418  line_r );
419  }
420 
422  inline void putStream( const std::string & group_r, LogLevel level_r,
423  const char * file_r, const char * func_r, int line_r,
424  const std::string & buffer_r )
425  {
426  LogControlImpl::instance().putStream( group_r, level_r,
427  file_r, func_r, line_r,
428  buffer_r );
429  }
430 
431  bool isExcessive()
432  { return LogControlImpl::instance().isExcessive(); }
433 
435  } // namespace logger
437 
439  //
440  // CLASS NAME : LogControl
441  // Forward to LogControlImpl singleton.
442  //
444 
445  using logger::LogControlImpl;
446 
447  void LogControl::logfile( const Pathname & logfile_r )
448  { LogControlImpl::instance().logfile( logfile_r ); }
449 
450  void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
451  { LogControlImpl::instance().logfile( logfile_r, mode_r ); }
452 
453  shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const
454  { return LogControlImpl::instance().getLineWriter(); }
455 
456  void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
457  { LogControlImpl::instance().setLineWriter( writer_r ); }
458 
459  void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r )
460  { LogControlImpl::instance().setLineFormater( formater_r ); }
461 
463  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>() ); }
464 
466  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) ); }
467 
469  //
470  // LogControl::TmpExcessive
471  //
474  { LogControlImpl::instance().excessive( true ); }
476  { LogControlImpl::instance().excessive( false ); }
477 
478  /******************************************************************
479  **
480  ** FUNCTION NAME : operator<<
481  ** FUNCTION TYPE : std::ostream &
482  */
483  std::ostream & operator<<( std::ostream & str, const LogControl & obj )
484  {
485  return str << LogControlImpl::instance();
486  }
487 
489  } // namespace base
492 } // namespace zypp
std::map< LogLevel, StreamPtr > StreamSet
Definition: LogControl.cc:347
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
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 logfile(const Pathname &logfile_r)
Set path for the logfile.
Definition: LogControl.cc:447
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:397
void setLineWriter(const shared_ptr< LineWriter > &writer_r)
Assign a LineWriter.
Definition: LogControl.cc:456
void logToStdErr()
Log to std::err.
Definition: LogControl.cc:465
const std::string & _buffer
Definition: PluginScript.cc:62
friend std::ostream & operator<<(std::ostream &str, const LogControl &obj)
Definition: LogControl.cc:483
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:348
void logNothing()
Turn off logging.
Definition: LogControl.cc:462
virtual std::string format(const std::string &, logger::LogLevel, const char *, const char *, int, const std::string &)
Definition: LogControl.cc:113
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's what Loglinebuf calls.
Definition: LogControl.cc:422
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:332
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
void setLineFormater(const shared_ptr< LineFormater > &formater_r)
Assign a LineFormater.
Definition: LogControl.cc:459
shared_ptr< void > _outs
Definition: LogControl.h:75
shared_ptr< Loglinestream > StreamPtr
Definition: LogControl.cc:346
Excessive logging.
Definition: Logger.h:104
shared_ptr< LineWriter > getLineWriter() const
Get the current LineWriter.
Definition: LogControl.cc:453
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:408
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:350