libzypp  12.16.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  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