libzypp  13.10.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 
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  return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r );
286  }
287 
289  void putStream( const std::string & group_r,
290  LogLevel level_r,
291  const char * file_r,
292  const char * func_r,
293  int line_r,
294  const std::string & message_r )
295  {
296  if ( _lineWriter )
297  _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
298  file_r, func_r, line_r,
299  message_r ) );
300  }
301 
302  private:
303  typedef shared_ptr<Loglinestream> StreamPtr;
304  typedef std::map<LogLevel,StreamPtr> StreamSet;
305  typedef std::map<std::string,StreamSet> StreamTable;
308 
309  private:
314  : _no_stream( NULL )
315  , _excessive( getenv("ZYPP_FULLLOG") )
316  , _lineFormater( new LogControl::LineFormater )
317  {
318  if ( getenv("ZYPP_LOGFILE") )
319  logfile( getenv("ZYPP_LOGFILE") );
320 
321  if ( getenv("ZYPP_PROFILING") )
322  {
323  shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater);
324  setLineFormater(formater);
325  }
326  }
327 
329  {
330  _lineWriter.reset();
331  }
332 
333  public:
340  static LogControlImpl & instance();
341  };
343 
344  // 'THE' LogControlImpl singleton
345  inline LogControlImpl & LogControlImpl::instance()
346  {
347  static LogControlImpl _instance;
348  return _instance;
349  }
350 
352 
354  inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
355  {
356  return str << "LogControlImpl";
357  }
358 
360  //
361  // Access from logger::
362  //
364 
365  std::ostream & getStream( const char * group_r,
366  LogLevel level_r,
367  const char * file_r,
368  const char * func_r,
369  const int line_r )
370  {
371  return LogControlImpl::instance().getStream( group_r,
372  level_r,
373  file_r,
374  func_r,
375  line_r );
376  }
377 
379  inline void putStream( const std::string & group_r, LogLevel level_r,
380  const char * file_r, const char * func_r, int line_r,
381  const std::string & buffer_r )
382  {
383  LogControlImpl::instance().putStream( group_r, level_r,
384  file_r, func_r, line_r,
385  buffer_r );
386  }
387 
388  bool isExcessive()
389  { return LogControlImpl::instance().isExcessive(); }
390 
392  } // namespace logger
394 
396  //
397  // CLASS NAME : LogControl
398  // Forward to LogControlImpl singleton.
399  //
401 
402  using logger::LogControlImpl;
403 
404  void LogControl::logfile( const Pathname & logfile_r )
405  { LogControlImpl::instance().logfile( logfile_r ); }
406 
407  void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
408  { LogControlImpl::instance().logfile( logfile_r, mode_r ); }
409 
410  shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const
411  { return LogControlImpl::instance().getLineWriter(); }
412 
413  void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
414  { LogControlImpl::instance().setLineWriter( writer_r ); }
415 
416  void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r )
417  { LogControlImpl::instance().setLineFormater( formater_r ); }
418 
420  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>() ); }
421 
423  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) ); }
424 
426  //
427  // LogControl::TmpExcessive
428  //
431  { LogControlImpl::instance().excessive( true ); }
433  { LogControlImpl::instance().excessive( false ); }
434 
435  /******************************************************************
436  **
437  ** FUNCTION NAME : operator<<
438  ** FUNCTION TYPE : std::ostream &
439  */
440  std::ostream & operator<<( std::ostream & str, const LogControl & obj )
441  {
442  return str << LogControlImpl::instance();
443  }
444 
446  } // namespace base
449 } // namespace zypp
std::map< LogLevel, StreamPtr > StreamSet
Definition: LogControl.cc:304
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
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:404
static LogControl instance()
Singleton access.
Definition: LogControl.h:101
std::ostream & operator<<(std::ostream &str, const LogControlImpl &obj)
Definition: LogControl.cc:354
void setLineWriter(const shared_ptr< LineWriter > &writer_r)
Assign a LineWriter.
Definition: LogControl.cc:413
void logToStdErr()
Log to std::err.
Definition: LogControl.cc:422
const std::string & _buffer
Definition: PluginScript.cc:59
friend std::ostream & operator<<(std::ostream &str, const LogControl &obj)
Definition: LogControl.cc:440
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:305
void logNothing()
Turn off logging.
Definition: LogControl.cc:419
std::string form(const char *format,...)
Printf style construction of std::string.
Definition: String.cc:34
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&#39;s what Loglinebuf calls.
Definition: LogControl.cc:379
shared_ptr< LogControl::LineWriter > _lineWriter
Definition: LogControl.cc:266
static Date now()
Return the current time.
Definition: Date.h:76
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:289
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:416
shared_ptr< void > _outs
Definition: LogControl.h:75
shared_ptr< Loglinestream > StreamPtr
Definition: LogControl.cc:303
Excessive logging.
Definition: Logger.h:87
shared_ptr< LineWriter > getLineWriter() const
Get the current LineWriter.
Definition: LogControl.cc:410
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:365
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:307