libzypp  14.48.5
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 
30  namespace log
31  {
32 
34  : StreamLineWriter( std::cout )
35  {}
36 
38  : StreamLineWriter( std::cerr )
39  {}
40 
41  FileLineWriter::FileLineWriter( const Pathname & file_r, mode_t mode_r )
42  {
43  if ( file_r == Pathname("-") )
44  {
45  _str = &std::cerr;
46  }
47  else
48  {
49  if ( mode_r )
50  {
51  // not filesystem::assert_file as filesystem:: functions log,
52  // and this FileWriter is not yet in place.
53  int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r );
54  if ( fd != -1 )
55  ::close( fd );
56  }
57  // set unbuffered write
58  std::ofstream * fstr = 0;
59  _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) );
60  fstr->rdbuf()->pubsetbuf(0,0);
61  _str = &(*fstr);
62  }
63  }
64 
66  } // namespace log
68 
70  namespace base
71  {
72 
74  // LineFormater
76  std::string LogControl::LineFormater::format( const std::string & group_r,
77  logger::LogLevel level_r,
78  const char * file_r,
79  const char * func_r,
80  int line_r,
81  const std::string & message_r )
82  {
83  static char hostname[1024];
84  static char nohostname[] = "unknown";
85  std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
86  return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
87  now.c_str(), level_r,
88  ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
89  getpid(),
90  group_r.c_str(),
91  file_r, func_r, line_r,
92  message_r.c_str() );
93  }
94 
96  namespace logger
97  {
98 
99  inline void putStream( const std::string & group_r, LogLevel level_r,
100  const char * file_r, const char * func_r, int line_r,
101  const std::string & buffer_r );
102 
104  //
105  // CLASS NAME : Loglinebuf
106  //
107  class Loglinebuf : public std::streambuf {
108 
109  public:
111  Loglinebuf( const std::string & group_r, LogLevel level_r )
112  : _group( group_r )
113  , _level( level_r )
114  , _file( "" )
115  , _func( "" )
116  , _line( -1 )
117  {}
120  {
121  if ( !_buffer.empty() )
122  writeout( "\n", 1 );
123  }
124 
126  void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
127  {
128  _file = fil_r;
129  _func = fnc_r;
130  _line = lne_r;
131  }
132 
133  private:
135  virtual std::streamsize xsputn( const char * s, std::streamsize n )
136  { return writeout( s, n ); }
138  virtual int overflow( int ch = EOF )
139  {
140  if ( ch != EOF )
141  {
142  char tmp = ch;
143  writeout( &tmp, 1 );
144  }
145  return 0;
146  }
148  virtual int writeout( const char* s, std::streamsize n )
149  {
150  //logger::putStream( _group, _level, _file, _func, _line, _buffer );
151  //return n;
152  if ( s && n )
153  {
154  const char * c = s;
155  for ( int i = 0; i < n; ++i, ++c )
156  {
157  if ( *c == '\n' ) {
158  _buffer += std::string( s, c-s );
159  logger::putStream( _group, _level, _file, _func, _line, _buffer );
160  _buffer = std::string();
161  s = c+1;
162  }
163  }
164  if ( s < c )
165  {
166  _buffer += std::string( s, c-s );
167  }
168  }
169  return n;
170  }
171 
172  private:
173  std::string _group;
175  const char * _file;
176  const char * _func;
177  int _line;
178  std::string _buffer;
179  };
180 
182 
184  //
185  // CLASS NAME : Loglinestream
186  //
188 
189  public:
191  Loglinestream( const std::string & group_r, LogLevel level_r )
192  : _mybuf( group_r, level_r )
193  , _mystream( &_mybuf )
194  {}
197  { _mystream.flush(); }
198 
199  public:
201  std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
202  {
203  _mybuf.tagSet( fil_r, fnc_r, lne_r );
204  return _mystream;
205  }
206 
207  private:
209  std::ostream _mystream;
210  };
212 
214  //
215  // CLASS NAME : LogControlImpl
216  //
227  {
228  public:
229  bool isExcessive()
230  { return _excessive; }
231 
232  void excessive( bool onOff_r )
233  { _excessive = onOff_r; }
234 
236  void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
237  { _lineWriter = writer_r; }
238 
239  shared_ptr<LogControl::LineWriter> getLineWriter() const
240  { return _lineWriter; }
241 
243  void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
244  {
245  if ( format_r )
246  _lineFormater = format_r;
247  else
248  _lineFormater.reset( new LogControl::LineFormater );
249  }
250 
251  void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
252  {
253  if ( logfile_r.empty() )
254  setLineWriter( shared_ptr<LogControl::LineWriter>() );
255  else if ( logfile_r == Pathname( "-" ) )
256  setLineWriter( shared_ptr<LogControl::LineWriter>(new log::StderrLineWriter) );
257  else
258  setLineWriter( shared_ptr<LogControl::LineWriter>(new log::FileLineWriter(logfile_r, mode_r)) );
259  }
260 
261  private:
262  std::ostream _no_stream;
264 
265  shared_ptr<LogControl::LineFormater> _lineFormater;
266  shared_ptr<LogControl::LineWriter> _lineWriter;
267 
268  public:
270  std::ostream & getStream( const std::string & group_r,
271  LogLevel level_r,
272  const char * file_r,
273  const char * func_r,
274  const int line_r )
275  {
276  if ( ! _lineWriter )
277  return _no_stream;
278  if ( level_r == E_XXX && !_excessive )
279  return _no_stream;
280 
281  if ( !_streamtable[group_r][level_r] )
282  {
283  _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
284  }
285  std::ostream & ret( _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ) );
286  if ( !ret )
287  {
288  ret.clear();
289  ret << "---<RESET LOGSTREAM FROM FAILED STATE]" << endl;
290  }
291  return ret;
292  }
293 
295  void putStream( const std::string & group_r,
296  LogLevel level_r,
297  const char * file_r,
298  const char * func_r,
299  int line_r,
300  const std::string & message_r )
301  {
302  if ( _lineWriter )
303  _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
304  file_r, func_r, line_r,
305  message_r ) );
306  }
307 
308  private:
309  typedef shared_ptr<Loglinestream> StreamPtr;
310  typedef std::map<LogLevel,StreamPtr> StreamSet;
311  typedef std::map<std::string,StreamSet> StreamTable;
314 
315  private:
320  : _no_stream( NULL )
321  , _excessive( getenv("ZYPP_FULLLOG") )
322  , _lineFormater( new LogControl::LineFormater )
323  {
324  if ( getenv("ZYPP_LOGFILE") )
325  logfile( getenv("ZYPP_LOGFILE") );
326 
327  if ( getenv("ZYPP_PROFILING") )
328  {
329  shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater);
330  setLineFormater(formater);
331  }
332  }
333 
335  {
336  _lineWriter.reset();
337  }
338 
339  public:
346  static LogControlImpl & instance();
347  };
349 
350  // 'THE' LogControlImpl singleton
351  inline LogControlImpl & LogControlImpl::instance()
352  {
353  static LogControlImpl _instance;
354  return _instance;
355  }
356 
358 
360  inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
361  {
362  return str << "LogControlImpl";
363  }
364 
366  //
367  // Access from logger::
368  //
370 
371  std::ostream & getStream( const char * group_r,
372  LogLevel level_r,
373  const char * file_r,
374  const char * func_r,
375  const int line_r )
376  {
377  return LogControlImpl::instance().getStream( group_r,
378  level_r,
379  file_r,
380  func_r,
381  line_r );
382  }
383 
385  inline void putStream( const std::string & group_r, LogLevel level_r,
386  const char * file_r, const char * func_r, int line_r,
387  const std::string & buffer_r )
388  {
389  LogControlImpl::instance().putStream( group_r, level_r,
390  file_r, func_r, line_r,
391  buffer_r );
392  }
393 
394  bool isExcessive()
395  { return LogControlImpl::instance().isExcessive(); }
396 
398  } // namespace logger
400 
402  //
403  // CLASS NAME : LogControl
404  // Forward to LogControlImpl singleton.
405  //
407 
408  using logger::LogControlImpl;
409 
410  void LogControl::logfile( const Pathname & logfile_r )
411  { LogControlImpl::instance().logfile( logfile_r ); }
412 
413  void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
414  { LogControlImpl::instance().logfile( logfile_r, mode_r ); }
415 
416  shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const
417  { return LogControlImpl::instance().getLineWriter(); }
418 
419  void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
420  { LogControlImpl::instance().setLineWriter( writer_r ); }
421 
422  void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r )
423  { LogControlImpl::instance().setLineFormater( formater_r ); }
424 
426  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>() ); }
427 
429  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) ); }
430 
432  //
433  // LogControl::TmpExcessive
434  //
437  { LogControlImpl::instance().excessive( true ); }
439  { LogControlImpl::instance().excessive( false ); }
440 
441  /******************************************************************
442  **
443  ** FUNCTION NAME : operator<<
444  ** FUNCTION TYPE : std::ostream &
445  */
446  std::ostream & operator<<( std::ostream & str, const LogControl & obj )
447  {
448  return str << LogControlImpl::instance();
449  }
450 
452  } // namespace base
455 } // namespace zypp
std::map< LogLevel, StreamPtr > StreamSet
Definition: LogControl.cc:310
LogLevel
Definition of log levels.
Definition: Logger.h:86
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:270
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:126
shared_ptr< LogControl::LineWriter > getLineWriter() const
Definition: LogControl.cc:239
Loglinestream(const std::string &group_r, LogLevel level_r)
Definition: LogControl.cc:191
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:236
void logfile(const Pathname &logfile_r, mode_t mode_r=0640)
Definition: LogControl.cc:251
void logfile(const Pathname &logfile_r)
Set path for the logfile.
Definition: LogControl.cc:410
static LogControl instance()
Singleton access.
Definition: LogControl.h:101
std::ostream & operator<<(std::ostream &str, const LogControlImpl &obj)
Definition: LogControl.cc:360
void setLineWriter(const shared_ptr< LineWriter > &writer_r)
Assign a LineWriter.
Definition: LogControl.cc:419
void logToStdErr()
Log to std::err.
Definition: LogControl.cc:428
const std::string & _buffer
Definition: PluginScript.cc:62
friend std::ostream & operator<<(std::ostream &str, const LogControl &obj)
Definition: LogControl.cc:446
virtual int overflow(int ch=EOF)
Definition: LogControl.cc:138
void setLineFormater(const shared_ptr< LogControl::LineFormater > &format_r)
Assert _lineFormater is not NULL.
Definition: LogControl.cc:243
shared_ptr< LogControl::LineFormater > _lineFormater
Definition: LogControl.cc:265
std::ostream & getStream(const char *fil_r, const char *fnc_r, int lne_r)
Definition: LogControl.cc:201
std::map< std::string, StreamSet > StreamTable
Definition: LogControl.cc:311
void logNothing()
Turn off logging.
Definition: LogControl.cc:425
virtual std::string format(const std::string &, logger::LogLevel, const char *, const char *, int, const std::string &)
Definition: LogControl.cc:76
Maintain logfile related options.
Definition: LogControl.h:95
virtual int writeout(const char *s, std::streamsize n)
Definition: LogControl.cc:148
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:385
shared_ptr< LogControl::LineWriter > _lineWriter
Definition: LogControl.cc:266
static Date now()
Return the current time.
Definition: Date.h:77
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:295
virtual std::streamsize xsputn(const char *s, std::streamsize n)
Definition: LogControl.cc:135
Loglinebuf(const std::string &group_r, LogLevel level_r)
Definition: LogControl.cc:111
Pathname _file
Definition: SystemCheck.cc:32
void setLineFormater(const shared_ptr< LineFormater > &formater_r)
Assign a LineFormater.
Definition: LogControl.cc:422
shared_ptr< void > _outs
Definition: LogControl.h:75
shared_ptr< Loglinestream > StreamPtr
Definition: LogControl.cc:309
Excessive logging.
Definition: Logger.h:87
shared_ptr< LineWriter > getLineWriter() const
Get the current LineWriter.
Definition: LogControl.cc:416
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:371
LogControl implementation (Singleton).
Definition: LogControl.cc:226
FileLineWriter(const Pathname &file_r, mode_t mode_r=0)
Definition: LogControl.cc:41
StreamTable _streamtable
one streambuffer per group and level
Definition: LogControl.cc:313