libzypp  11.13.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  // set unbuffered write
50  std::ofstream * fstr = 0;
51  _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) );
52  fstr->rdbuf()->pubsetbuf(0,0);
53  _str = &(*fstr);
54  if ( mode_r )
55  {
56  // not filesystem::chmod, as filesystem:: functions log,
57  // and this FileWriter is not yet in place.
58  ::chmod( file_r.asString().c_str(), mode_r );
59  }
60  }
61  }
62 
64  } // namespace log
66 
68  namespace base
69  {
70 
72  // LineFormater
74  std::string LogControl::LineFormater::format( const std::string & group_r,
75  logger::LogLevel level_r,
76  const char * file_r,
77  const char * func_r,
78  int line_r,
79  const std::string & message_r )
80  {
81  static char hostname[1024];
82  static char nohostname[] = "unknown";
83  std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
84  return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
85  now.c_str(), level_r,
86  ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
87  getpid(),
88  group_r.c_str(),
89  file_r, func_r, line_r,
90  message_r.c_str() );
91  }
92 
94  namespace logger
95  {
96 
97  inline void putStream( const std::string & group_r, LogLevel level_r,
98  const char * file_r, const char * func_r, int line_r,
99  const std::string & buffer_r );
100 
102  //
103  // CLASS NAME : Loglinebuf
104  //
105  class Loglinebuf : public std::streambuf {
106 
107  public:
109  Loglinebuf( const std::string & group_r, LogLevel level_r )
110  : _group( group_r )
111  , _level( level_r )
112  , _file( "" )
113  , _func( "" )
114  , _line( -1 )
115  {}
118  {
119  if ( !_buffer.empty() )
120  writeout( "\n", 1 );
121  }
122 
124  void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
125  {
126  _file = fil_r;
127  _func = fnc_r;
128  _line = lne_r;
129  }
130 
131  private:
133  virtual std::streamsize xsputn( const char * s, std::streamsize n )
134  { return writeout( s, n ); }
136  virtual int overflow( int ch = EOF )
137  {
138  if ( ch != EOF )
139  {
140  char tmp = ch;
141  writeout( &tmp, 1 );
142  }
143  return 0;
144  }
146  virtual int writeout( const char* s, std::streamsize n )
147  {
148  //logger::putStream( _group, _level, _file, _func, _line, _buffer );
149  //return n;
150  if ( s && n )
151  {
152  const char * c = s;
153  for ( int i = 0; i < n; ++i, ++c )
154  {
155  if ( *c == '\n' ) {
156  _buffer += std::string( s, c-s );
157  logger::putStream( _group, _level, _file, _func, _line, _buffer );
158  _buffer = std::string();
159  s = c+1;
160  }
161  }
162  if ( s < c )
163  {
164  _buffer += std::string( s, c-s );
165  }
166  }
167  return n;
168  }
169 
170  private:
171  std::string _group;
173  const char * _file;
174  const char * _func;
175  int _line;
176  std::string _buffer;
177  };
178 
180 
182  //
183  // CLASS NAME : Loglinestream
184  //
186 
187  public:
189  Loglinestream( const std::string & group_r, LogLevel level_r )
190  : _mybuf( group_r, level_r )
191  , _mystream( &_mybuf )
192  {}
195  { _mystream.flush(); }
196 
197  public:
199  std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
200  {
201  _mybuf.tagSet( fil_r, fnc_r, lne_r );
202  return _mystream;
203  }
204 
205  private:
207  std::ostream _mystream;
208  };
210 
212  //
213  // CLASS NAME : LogControlImpl
214  //
225  {
226  public:
227  bool isExcessive()
228  { return _excessive; }
229 
230  void excessive( bool onOff_r )
231  { _excessive = onOff_r; }
232 
234  void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
235  { _lineWriter = writer_r; }
236 
237  shared_ptr<LogControl::LineWriter> getLineWriter() const
238  { return _lineWriter; }
239 
241  void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
242  {
243  if ( format_r )
244  _lineFormater = format_r;
245  else
246  _lineFormater.reset( new LogControl::LineFormater );
247  }
248 
249  void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
250  {
251  if ( logfile_r.empty() )
252  setLineWriter( shared_ptr<LogControl::LineWriter>() );
253  else if ( logfile_r == Pathname( "-" ) )
254  setLineWriter( shared_ptr<LogControl::LineWriter>(new log::StderrLineWriter) );
255  else
256  setLineWriter( shared_ptr<LogControl::LineWriter>(new log::FileLineWriter(logfile_r, mode_r)) );
257  }
258 
259  private:
260  std::ostream _no_stream;
262 
263  shared_ptr<LogControl::LineFormater> _lineFormater;
264  shared_ptr<LogControl::LineWriter> _lineWriter;
265 
266  public:
268  std::ostream & getStream( const std::string & group_r,
269  LogLevel level_r,
270  const char * file_r,
271  const char * func_r,
272  const int line_r )
273  {
274  if ( ! _lineWriter )
275  return _no_stream;
276  if ( level_r == E_XXX && !_excessive )
277  return _no_stream;
278 
279  if ( !_streamtable[group_r][level_r] )
280  {
281  _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
282  }
283  return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r );
284  }
285 
287  void putStream( const std::string & group_r,
288  LogLevel level_r,
289  const char * file_r,
290  const char * func_r,
291  int line_r,
292  const std::string & message_r )
293  {
294  if ( _lineWriter )
295  _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
296  file_r, func_r, line_r,
297  message_r ) );
298  }
299 
300  private:
301  typedef shared_ptr<Loglinestream> StreamPtr;
302  typedef std::map<LogLevel,StreamPtr> StreamSet;
303  typedef std::map<std::string,StreamSet> StreamTable;
306 
307  private:
312  : _no_stream( NULL )
313  , _excessive( getenv("ZYPP_FULLLOG") )
314  , _lineFormater( new LogControl::LineFormater )
315  {
316  if ( getenv("ZYPP_LOGFILE") )
317  logfile( getenv("ZYPP_LOGFILE") );
318 
319  if ( getenv("ZYPP_PROFILING") )
320  {
321  shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater);
322  setLineFormater(formater);
323  }
324  }
325 
327  {
328  _lineWriter.reset();
329  }
330 
331  public:
338  static LogControlImpl & instance();
339  };
341 
342  // 'THE' LogControlImpl singleton
344  {
345  static LogControlImpl _instance;
346  return _instance;
347  }
348 
350 
352  inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
353  {
354  return str << "LogControlImpl";
355  }
356 
358  //
359  // Access from logger::
360  //
362 
363  std::ostream & getStream( const char * group_r,
364  LogLevel level_r,
365  const char * file_r,
366  const char * func_r,
367  const int line_r )
368  {
369  return LogControlImpl::instance().getStream( group_r,
370  level_r,
371  file_r,
372  func_r,
373  line_r );
374  }
375 
377  inline void putStream( const std::string & group_r, LogLevel level_r,
378  const char * file_r, const char * func_r, int line_r,
379  const std::string & buffer_r )
380  {
381  LogControlImpl::instance().putStream( group_r, level_r,
382  file_r, func_r, line_r,
383  buffer_r );
384  }
385 
386  bool isExcessive()
387  { return LogControlImpl::instance().isExcessive(); }
388 
390  } // namespace logger
392 
394  //
395  // CLASS NAME : LogControl
396  // Forward to LogControlImpl singleton.
397  //
399 
400  using logger::LogControlImpl;
401 
402  void LogControl::logfile( const Pathname & logfile_r )
403  { LogControlImpl::instance().logfile( logfile_r ); }
404 
405  void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
406  { LogControlImpl::instance().logfile( logfile_r, mode_r ); }
407 
408  shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const
410 
411  void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
412  { LogControlImpl::instance().setLineWriter( writer_r ); }
413 
414  void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r )
415  { LogControlImpl::instance().setLineFormater( formater_r ); }
416 
418  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>() ); }
419 
421  { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) ); }
422 
424  //
425  // LogControl::TmpExcessive
426  //
429  { LogControlImpl::instance().excessive( true ); }
431  { LogControlImpl::instance().excessive( false ); }
432 
433  /******************************************************************
434  **
435  ** FUNCTION NAME : operator<<
436  ** FUNCTION TYPE : std::ostream &
437  */
438  std::ostream & operator<<( std::ostream & str, const LogControl & obj )
439  {
440  return str << LogControlImpl::instance();
441  }
442 
444  } // namespace base
447 } // namespace zypp