libzypp  17.31.0
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 #include <mutex>
16 #include <map>
17 
18 #include <zypp-core/base/Logger.h>
19 #include <zypp-core/base/LogControl.h>
20 #include <zypp-core/base/ProfilingFormater.h>
21 #include <zypp-core/base/String.h>
22 #include <zypp-core/Date.h>
23 #include <zypp-core/TriBool.h>
24 #include <zypp-core/AutoDispose.h>
25 
26 #include <zypp-core/zyppng/io/Socket>
27 #include <zypp-core/zyppng/io/SockAddr>
28 #include <zypp-core/zyppng/base/EventLoop>
29 #include <zypp-core/zyppng/base/EventDispatcher>
30 #include <zypp-core/zyppng/base/Timer>
31 #include <zypp-core/zyppng/base/private/linuxhelpers_p.h>
32 #include <zypp-core/zyppng/thread/Wakeup>
33 #include <zypp-core/zyppng/base/private/threaddata_p.h>
34 #include <zypp-core/zyppng/base/SocketNotifier>
35 
36 #include <thread>
37 #include <variant>
38 #include <atomic>
39 #include <csignal>
40 
41 extern "C"
42 {
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 #include <unistd.h>
47 #include <dirent.h>
48 }
49 
50 using std::endl;
51 
52 std::once_flag flagReadEnvAutomatically;
53 
54 namespace zypp
55 {
56  constexpr std::string_view ZYPP_MAIN_THREAD_NAME( "Zypp-main" );
57 
58  template<class> inline constexpr bool always_false_v = false;
59 
64  class SpinLock {
65  public:
66  void lock () {
67  // acquire lock
68  while ( _atomicLock.test_and_set())
69  // Reschedule the current thread while we wait. Maybe, when it is our next turn, the lock is free again.
70  std::this_thread::yield();
71  }
72 
73  void unlock() {
74  _atomicLock.clear();
75  }
76 
77  private:
78  // we use a lock-free atomic flag here, so this lock can be safely obtained in a signal handler as well
79  std::atomic_flag _atomicLock = ATOMIC_FLAG_INIT;
80  };
81 
82  class LogThread
83  {
84 
85  public:
86 
88  stop();
89  }
90 
91  static LogThread &instance () {
92  static LogThread t;
93  return t;
94  }
95 
96  void setLineWriter ( boost::shared_ptr<log::LineWriter> writer ) {
97  std::lock_guard lk( _lineWriterLock );
98  _lineWriter = writer;
99  }
100 
101  boost::shared_ptr<log::LineWriter> getLineWriter () {
102  std::lock_guard lk( _lineWriterLock );
103  auto lw = _lineWriter;
104  return lw;
105  }
106 
107  void stop () {
108  _stopSignal.notify();
109  if ( _thread.get_id() != std::this_thread::get_id() )
110  _thread.join();
111  }
112 
113  std::thread::id threadId () {
114  return _thread.get_id();
115  }
116 
117  static std::string sockPath () {
118  static std::string path = zypp::str::Format("zypp-logsocket-%1%") % getpid();
119  return path;
120  }
121 
122  private:
123 
125  {
126  // Name the thread that started the logger, assuming it's the main thread.
127  zyppng::ThreadData::current().setName(ZYPP_MAIN_THREAD_NAME);
128  _thread = std::thread( [this] () {
129  workerMain();
130  });
131  }
132 
133  void workerMain () {
134 
135  // force the kernel to pick another thread to handle those signals
136  zyppng::blockSignalsForCurrentThread( { SIGTERM, SIGINT, SIGPIPE, } );
137 
138  zyppng::ThreadData::current().setName("Zypp-Log");
139 
140  auto ev = zyppng::EventLoop::create();
141  auto server = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 );
142  auto stopNotifyWatch = _stopSignal.makeNotifier( );
143 
144  std::vector<zyppng::Socket::Ptr> clients;
145 
146  // bind to a abstract unix domain socket address, which means we do not need to care about cleaning it up
147  server->bind( std::make_shared<zyppng::UnixSockAddr>( sockPath(), true ) );
148  server->listen();
149 
150  // wait for incoming connections from other threads
151  server->connectFunc( &zyppng::Socket::sigIncomingConnection, [&](){
152 
153  auto cl = server->accept();
154  if ( !cl ) return;
155  clients.push_back( cl );
156 
157  // wait until data is available, we operate line by line so we only
158  // log a string once we encounter \n
159  cl->connectFunc( &zyppng::Socket::sigReadyRead, [ this, sock = cl.get() ](){
160  auto writer = getLineWriter();
161  if ( !writer ) return;
162  while ( sock->canReadLine() ) {
163  auto br = sock->readLine();
164  writer->writeOut( std::string( br.data(), br.size() - 1 ) );
165  }
166  }, *cl);
167 
168  // once a client disconnects we remove it from the std::vector so that the socket is not leaked
169  cl->connectFunc( &zyppng::Socket::sigDisconnected, [&clients, sock = std::weak_ptr(cl)](){
170  auto lock = sock.lock();
171  if ( !lock )
172  return;
173 
174  auto idx = std::find_if( clients.begin(), clients.end(), [lock]( const auto &s ){ return lock.get() == s.get(); } );
175  clients.erase( idx );
176  });
177 
178  });
179 
180  stopNotifyWatch->connectFunc( &zyppng::SocketNotifier::sigActivated, [&ev]( const auto &, auto ) {
181  ev->quit();
182  });
183 
184  ev->run();
185 
186  // make sure we have written everything
187  auto writer = getLineWriter();
188  if ( writer ) {
189  for ( auto &sock : clients ){
190  auto br = sock->readLine();
191  while ( !br.empty() ) {
192  if ( br.back () == '\n' )
193  writer->writeOut( std::string( br.data(), br.size() - 1 ) );
194  else
195  writer->writeOut( std::string( br.data(), br.size() ) );
196 
197  br = sock->readLine();
198  }
199  }
200  }
201  }
202 
203  private:
204  std::thread _thread;
205  zyppng::Wakeup _stopSignal;
206 
207  // since the public API uses boost::shared_ptr we can not use the atomic
208  // functionalities provided in std.
209  // this lock type can be used safely in signals
211  // boost shared_ptr has a lock free implementation of reference counting so it can be used from signal handlers as well
212  boost::shared_ptr<log::LineWriter> _lineWriter{ nullptr };
213  };
214 
215  class LogClient
216  {
217  public:
219  // make sure the thread is running
221  }
222 
224  ::close( _sockFD );
225  }
226 
232  if ( _sockFD >= 0 )
233  return true;
234 
235  _sockFD = ::socket( AF_UNIX, SOCK_STREAM, 0 );
236  if ( _sockFD == -1 )
237  return false;
238 
239  zyppng::UnixSockAddr addr( LogThread::sockPath(), true );
240  return zyppng::trySocketConnection( _sockFD, addr, 100 );
241  }
242 
246  void pushMessage ( std::string &&msg ) {
247  if ( inPushMessage ) {
248  return;
249  }
250 
251  // make sure we do not end up in a busy loop
252  zypp::AutoDispose<bool *> res( &inPushMessage, [](auto val){
253  *val = false;
254  });
255  inPushMessage = true;
256 
257  // if we are in the same thread as the Log worker we can directly push our messages out, no need to use the socket
258  if ( std::this_thread::get_id() == LogThread::instance().threadId() ) {
259  auto writer = LogThread::instance().getLineWriter();
260  if ( writer )
261  writer->writeOut( msg );
262  return;
263  }
264 
265  if(!ensureConnection())
266  return;
267 
268  if ( msg.back() != '\n' )
269  msg.push_back('\n');
270 
271  size_t written = 0;
272  while ( written < msg.size() ) {
273  const auto res = zyppng::eintrSafeCall( ::send, _sockFD, msg.data() + written, msg.size() - written, MSG_NOSIGNAL );
274  if ( res == -1 ) {
275  //assume broken socket
276  ::close( _sockFD );
277  _sockFD = -1;
278  return;
279  }
280  written += res;
281  }
282  }
283 
284  private:
285  int _sockFD = -1;
286  bool inPushMessage = false;
287  };
288 
289 #ifndef ZYPP_NDEBUG
290  namespace debug
291  {
292  // Fg::Black: 30 Bg: 40 Attr::Normal: 22;27
293  // Fg::Red: 31 ... Attr::Bright: 1
294  // Fg::Green: 32 Attr::Reverse: 7
295  // Fg::Yellow: 33
296  // Fg::Blue: 34
297  // Fg::Magenta: 35
298  // Fg::Cyan: 36
299  // Fg::White: 37
300  // Fg::Default: 39
301  static constexpr std::string_view OO { "\033[0m" };
302  static constexpr std::string_view WH { "\033[37;40m" };
303  static constexpr std::string_view CY { "\033[36;40m" };
304  static constexpr std::string_view YE { "\033[33;1;40m" };
305  static constexpr std::string_view GR { "\033[32;40m" };
306  static constexpr std::string_view RE { "\033[31;1;40m" };
307  static constexpr std::string_view MA { "\033[35;40m" };
308 
309  unsigned TraceLeave::_depth = 1;
310 
311  std::string tracestr( char tag_r, unsigned depth_r, const char * file_r, const char * fnc_r, int line_r )
312  {
313  static str::Format fmt { "*** %s %s(%s):%d" };
314  fmt % std::string(depth_r,tag_r) % file_r % fnc_r % line_r;
315  return fmt;
316  }
317 
318  TraceLeave::TraceLeave( const char * file_r, const char * fnc_r, int line_r )
319  : _file( std::move(file_r) )
320  , _fnc( std::move(fnc_r) )
321  , _line( line_r )
322  {
323  const std::string & m { tracestr( '>',_depth++, _file,_fnc,_line ) };
324  USR << m << endl;
325  Osd(L_USR("TRACE"),1) << m << endl;
326  }
327 
329  {
330  const std::string & m { tracestr( '<',--_depth, _file,_fnc,_line ) };
331  USR << m << endl;
332  Osd(L_USR("TRACE"),1) << m << endl;
333  }
334 
335  Osd::Osd( std::ostream & str, int i )
336  : _strout { std::cerr }
337  , _strlog { str }
338  { _strout << (i?WH:YE); }
339 
341  { _strout << OO; }
342 
343  Osd & Osd::operator<<( std::ostream& (*iomanip)( std::ostream& ) )
344  {
345  _strout << iomanip;
346  _strlog << iomanip;
347  return *this;
348  }
349 }
350 #endif // ZYPP_NDEBUG
351 
353  namespace log
354  {
355 
357  : StreamLineWriter( std::cout )
358  {}
359 
361  : StreamLineWriter( std::cerr )
362  {}
363 
364  FileLineWriter::FileLineWriter( const Pathname & file_r, mode_t mode_r )
365  {
366  if ( file_r == Pathname("-") )
367  {
368  _str = &std::cerr;
369  }
370  else
371  {
372  if ( mode_r )
373  {
374  // not filesystem::assert_file as filesystem:: functions log,
375  // and this FileWriter is not yet in place.
376  int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r );
377  if ( fd != -1 )
378  ::close( fd );
379  }
380  // set unbuffered write
381  std::ofstream * fstr = 0;
382  _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) );
383  fstr->rdbuf()->pubsetbuf(0,0);
384  _str = &(*fstr);
385  }
386  }
387 
389  } // namespace log
391 
393  namespace base
394  {
395  namespace logger
397  {
398 
399  inline void putStream( const std::string & group_r, LogLevel level_r,
400  const char * file_r, const char * func_r, int line_r,
401  const std::string & buffer_r );
402 
404  //
405  // CLASS NAME : Loglinebuf
406  //
407  class Loglinebuf : public std::streambuf {
408 
409  public:
411  Loglinebuf( const std::string & group_r, LogLevel level_r )
412  : _group( group_r )
413  , _level( level_r )
414  , _file( "" )
415  , _func( "" )
416  , _line( -1 )
417  {}
420  {
421  if ( !_buffer.empty() )
422  writeout( "\n", 1 );
423  }
424 
426  void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
427  {
428  _file = fil_r;
429  _func = fnc_r;
430  _line = lne_r;
431  }
432 
433  private:
435  virtual std::streamsize xsputn( const char * s, std::streamsize n )
436  { return writeout( s, n ); }
438  virtual int overflow( int ch = EOF )
439  {
440  if ( ch != EOF )
441  {
442  char tmp = ch;
443  writeout( &tmp, 1 );
444  }
445  return 0;
446  }
448  virtual int writeout( const char* s, std::streamsize n )
449  {
450  //logger::putStream( _group, _level, _file, _func, _line, _buffer );
451  //return n;
452  if ( s && n )
453  {
454  const char * c = s;
455  for ( int i = 0; i < n; ++i, ++c )
456  {
457  if ( *c == '\n' ) {
458  _buffer += std::string( s, c-s );
460  _buffer = std::string();
461  s = c+1;
462  }
463  }
464  if ( s < c )
465  {
466  _buffer += std::string( s, c-s );
467  }
468  }
469  return n;
470  }
471 
472  private:
473  std::string _group;
475  const char * _file;
476  const char * _func;
477  int _line;
478  std::string _buffer;
479  };
480 
482 
484  //
485  // CLASS NAME : Loglinestream
486  //
488 
489  public:
491  Loglinestream( const std::string & group_r, LogLevel level_r )
492  : _mybuf( group_r, level_r )
493  , _mystream( &_mybuf )
494  {}
497  { _mystream.flush(); }
498 
499  public:
501  std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
502  {
503  _mybuf.tagSet( fil_r, fnc_r, lne_r );
504  return _mystream;
505  }
506 
507  private:
509  std::ostream _mystream;
510  };
512 
513  struct LogControlImpl;
514 
515  /*
516  * Ugly hack to prevent the use of LogControlImpl when libzypp is shutting down.
517  * Due to the C++ standard, thread_local static instances are cleaned up before the first global static
518  * destructor is called. So all classes that use logging after that point in time would crash the
519  * application because it is accessing a variable that has already been destroyed.
520  */
522  // We are using a POD flag that does not have a destructor,
523  // to flag if the thread_local destructors were already executed.
524  // Since TLS data is stored in a segment that is available until the thread ceases to exist it should still be readable
525  // after thread_local c++ destructors were already executed. Or so I hope.
526  static thread_local int logControlValid = 0;
527  return logControlValid;
528  }
529 
531  //
532  // CLASS NAME : LogControlImpl
533  //
544  {
545  public:
546  bool isExcessive() const
547  { return _excessive; }
548 
549  void excessive( bool onOff_r )
550  { _excessive = onOff_r; }
551 
552 
554  bool hideThreadName() const
555  {
556  if ( indeterminate(_hideThreadName) )
557  _hideThreadName = ( zyppng::ThreadData::current().name() == ZYPP_MAIN_THREAD_NAME );
558  return bool(_hideThreadName);
559  }
561  void hideThreadName( bool onOff_r )
562  { _hideThreadName = onOff_r; }
563 
566  {
567  auto impl = LogControlImpl::instance();
568  return impl ? impl->hideThreadName() : false;
569  }
571  static void instanceHideThreadName( bool onOff_r )
572  {
573  auto impl = LogControlImpl::instance();
574  if ( impl ) impl->hideThreadName( onOff_r );
575  }
576 
578  static bool instanceLogToPPID( )
579  {
580  auto impl = LogControlImpl::instance();
581  return impl ? impl->_logToPPIDMode : false;
582  }
583 
585  static void instanceSetLogToPPID( bool onOff_r )
586  {
587  auto impl = LogControlImpl::instance();
588  if ( impl )
589  impl->_logToPPIDMode = onOff_r;
590  }
591 
593  void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
594  { LogThread::instance().setLineWriter( writer_r ); }
595 
596  shared_ptr<LogControl::LineWriter> getLineWriter() const
597  { return LogThread::instance().getLineWriter(); }
598 
600  void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
601  {
602  if ( format_r )
603  _lineFormater = format_r;
604  else
606  }
607 
608  void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
609  {
610  if ( logfile_r.empty() )
611  setLineWriter( shared_ptr<LogControl::LineWriter>() );
612  else if ( logfile_r == Pathname( "-" ) )
613  setLineWriter( shared_ptr<LogControl::LineWriter>(new log::StderrLineWriter) );
614  else
615  setLineWriter( shared_ptr<LogControl::LineWriter>(new log::FileLineWriter(logfile_r, mode_r)) );
616  }
617 
618  private:
620  std::ostream _no_stream;
622  bool _logToPPIDMode = false;
623  mutable TriBool _hideThreadName = indeterminate;
624 
625  shared_ptr<LogControl::LineFormater> _lineFormater;
626 
627  public:
629  std::ostream & getStream( const std::string & group_r,
630  LogLevel level_r,
631  const char * file_r,
632  const char * func_r,
633  const int line_r )
634  {
635  if ( ! getLineWriter() )
636  return _no_stream;
637  if ( level_r == E_XXX && !_excessive )
638  return _no_stream;
639 
640  if ( !_streamtable[group_r][level_r] )
641  {
642  _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
643  }
644  std::ostream & ret( _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ) );
645  if ( !ret )
646  {
647  ret.clear();
648  ret << "---<RESET LOGSTREAM FROM FAILED STATE]" << endl;
649  }
650  return ret;
651  }
652 
653  void putRawLine ( std::string &&line ) {
654  _logClient.pushMessage( std::move(line) );
655  }
656 
658  void putStream( const std::string & group_r,
659  LogLevel level_r,
660  const char * file_r,
661  const char * func_r,
662  int line_r,
663  const std::string & message_r )
664  {
665  _logClient.pushMessage( _lineFormater->format( group_r, level_r,
666  file_r, func_r, line_r,
667  message_r ) );
668  }
669 
670  private:
671  typedef shared_ptr<Loglinestream> StreamPtr;
672  typedef std::map<LogLevel,StreamPtr> StreamSet;
673  typedef std::map<std::string,StreamSet> StreamTable;
676  zyppng::Socket::Ptr _sock;
677 
678  private:
679 
680  void readEnvVars () {
681  if ( getenv("ZYPP_LOGFILE") )
682  logfile( getenv("ZYPP_LOGFILE") );
683 
684  if ( getenv("ZYPP_PROFILING") )
685  {
686  shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater);
687  setLineFormater(formater);
688  }
689  }
694  : _no_stream( NULL )
695  , _excessive( getenv("ZYPP_FULLLOG") )
696  , _lineFormater( new LogControl::LineFormater )
697  {
698  logControlValidFlag() = 1;
699  std::call_once( flagReadEnvAutomatically, &LogControlImpl::readEnvVars, this);
700 
701  // make sure the LogControl is invalidated when we fork
702  pthread_atfork( nullptr, nullptr, &LogControl::notifyFork );
703  }
704 
705  public:
706 
708  {
709  logControlValidFlag() = 0;
710  }
711 
718  static LogControlImpl *instance();
719  };
721 
722  // 'THE' LogControlImpl singleton
724  {
725  thread_local static LogControlImpl _instance;
726  if ( logControlValidFlag() > 0 )
727  return &_instance;
728  return nullptr;
729  }
730 
732 
734  inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & )
735  {
736  return str << "LogControlImpl";
737  }
738 
740  //
741  // Access from logger::
742  //
744 
745  std::ostream & getStream( const char * group_r,
746  LogLevel level_r,
747  const char * file_r,
748  const char * func_r,
749  const int line_r )
750  {
751  static std::ostream nstream(NULL);
752  auto control = LogControlImpl::instance();
753  if ( !control || !group_r || strlen(group_r ) == 0 ) {
754  return nstream;
755  }
756 
757 
758 
759  return control->getStream( group_r,
760  level_r,
761  file_r,
762  func_r,
763  line_r );
764  }
765 
767  inline void putStream( const std::string & group_r, LogLevel level_r,
768  const char * file_r, const char * func_r, int line_r,
769  const std::string & buffer_r )
770  {
771  auto control = LogControlImpl::instance();
772  if ( !control )
773  return;
774 
775  control->putStream( group_r, level_r,
776  file_r, func_r, line_r,
777  buffer_r );
778  }
779 
780  bool isExcessive()
781  {
782  auto impl = LogControlImpl::instance();
783  if ( !impl )
784  return false;
785  return impl->isExcessive();
786  }
787 
789  } // namespace logger
791 
792  using logger::LogControlImpl;
793 
795  // LineFormater
797  std::string LogControl::LineFormater::format( const std::string & group_r,
798  logger::LogLevel level_r,
799  const char * file_r,
800  const char * func_r,
801  int line_r,
802  const std::string & message_r )
803  {
804  static char hostname[1024];
805  static char nohostname[] = "unknown";
806  std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
807  std::string ret;
808 
809  const bool logToPPID = LogControlImpl::instanceLogToPPID();
810  if ( !logToPPID && LogControlImpl::instanceHideThreadName() )
811  ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
812  now.c_str(), level_r,
813  ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
814  getpid(),
815  group_r.c_str(),
816  file_r, func_r, line_r,
817  message_r.c_str() );
818  else
819  ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d {T:%s} %s",
820  now.c_str(), level_r,
821  ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
822  logToPPID ? getppid() : getpid(),
823  group_r.c_str(),
824  file_r, func_r, line_r,
825  zyppng::ThreadData::current().name().c_str(),
826  message_r.c_str() );
827  return ret;
828  }
829 
831  //
832  // CLASS NAME : LogControl
833  // Forward to LogControlImpl singleton.
834  //
836 
837 
838  void LogControl::logfile( const Pathname & logfile_r )
839  {
840  auto impl = LogControlImpl::instance();
841  if ( !impl )
842  return;
843 
844  impl->logfile( logfile_r );
845  }
846 
847  void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
848  {
849  auto impl = LogControlImpl::instance();
850  if ( !impl )
851  return;
852 
853  impl->logfile( logfile_r, mode_r );
854  }
855 
856  shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const
857  {
858  auto impl = LogControlImpl::instance();
859  if ( !impl )
860  return nullptr;
861 
862  return impl->getLineWriter();
863  }
864 
865  void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
866  {
867  auto impl = LogControlImpl::instance();
868  if ( !impl )
869  return;
870  impl->setLineWriter( writer_r );
871  }
872 
873  void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r )
874  {
875  auto impl = LogControlImpl::instance();
876  if ( !impl )
877  return;
878  impl->setLineFormater( formater_r );
879  }
880 
882  {
884  }
885 
887  {
888  auto impl = LogControlImpl::instance();
889  if ( !impl )
890  return;
891  impl->setLineWriter( shared_ptr<LineWriter>() );
892  }
893 
895  {
896  auto impl = LogControlImpl::instance();
897  if ( !impl )
898  return;
899  impl->setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) );
900  }
901 
903  {
905  }
906 
908  {
910  }
911 
912  void LogControl::logRawLine ( std::string &&line )
913  {
914  LogControlImpl::instance ()->putRawLine ( std::move(line) );
915  }
916 
918  //
919  // LogControl::TmpExcessive
920  //
923  {
924  auto impl = LogControlImpl::instance();
925  if ( !impl )
926  return;
927  impl->excessive( true );
928  }
930  {
931  auto impl = LogControlImpl::instance();
932  if ( !impl )
933  return;
934  impl->excessive( false );
935  }
936 
937  /******************************************************************
938  **
939  ** FUNCTION NAME : operator<<
940  ** FUNCTION TYPE : std::ostream &
941  */
942  std::ostream & operator<<( std::ostream & str, const LogControl & )
943  {
944  auto impl = LogControlImpl::instance();
945  if ( !impl )
946  return str;
947  return str << *impl;
948  }
949 
951  } // namespace base
954 } // namespace zypp
std::map< LogLevel, StreamPtr > StreamSet
Definition: LogControl.cc:672
void enableLogForwardingMode(bool enable=true)
Definition: LogControl.cc:881
std::atomic_flag _atomicLock
Definition: LogControl.cc:79
Osd & operator<<(Tp &&val)
Definition: Logger.h:48
LogLevel
Definition of log levels.
Definition: Logger.h:152
constexpr bool always_false_v
Definition: LogControl.cc:58
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:629
static constexpr std::string_view MA
Definition: LogControl.cc:307
Base class for ostream based LineWriter.
Definition: LogControl.h:44
std::ostream & _strlog
Definition: Logger.h:59
void tagSet(const char *fil_r, const char *fnc_r, int lne_r)
Definition: LogControl.cc:426
Loglinestream(const std::string &group_r, LogLevel level_r)
Definition: LogControl.cc:491
static void instanceSetLogToPPID(bool onOff_r)
Definition: LogControl.cc:585
static constexpr std::string_view WH
Definition: LogControl.cc:302
const char * c_str() const
String representation.
Definition: Pathname.h:110
String related utilities and Regular expression matching.
std::ostream & _strout
Definition: Logger.h:58
Definition: Arch.h:351
LineWriter to file.
Definition: LogControl.h:72
If you want to format loglines by yourself, derive from this, and overload format.
Definition: LogControl.h:114
static void instanceHideThreadName(bool onOff_r)
Definition: LogControl.cc:571
Convenient building of std::string with boost::format.
Definition: String.h:252
LineWriter to stderr.
Definition: LogControl.h:63
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
Osd(std::ostream &, int=0)
Definition: LogControl.cc:335
void setLineWriter(const shared_ptr< LogControl::LineWriter > &writer_r)
NULL _lineWriter indicates no loggin.
Definition: LogControl.cc:593
static std::string sockPath()
Definition: LogControl.cc:117
void logfile(const Pathname &logfile_r, mode_t mode_r=0640)
Definition: LogControl.cc:608
void logfile(const Pathname &logfile_r)
Set path for the logfile.
Definition: LogControl.cc:838
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition: String.h:30
void setLineWriter(const shared_ptr< LineWriter > &writer_r)
Assign a LineWriter.
Definition: LogControl.cc:865
bool _logToPPIDMode
Hint for formatter to use the PPID and always show the thread name.
Definition: LogControl.cc:622
void logToStdErr()
Log to std::err.
Definition: LogControl.cc:894
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
const char * _fnc
Definition: Logger.h:36
TraceLeave(const TraceLeave &)=delete
std::thread::id threadId()
Definition: LogControl.cc:113
static bool instanceLogToPPID()
Hint for formatter wether we forward all logs to a parents log.
Definition: LogControl.cc:578
shared_ptr< LogControl::LineWriter > getLineWriter() const
Definition: LogControl.cc:596
zyppng::Wakeup _stopSignal
Definition: LogControl.cc:205
const std::string & asString() const
String representation.
Definition: Pathname.h:91
static constexpr std::string_view GR
Definition: LogControl.cc:305
friend std::ostream & operator<<(std::ostream &str, const LogControl &obj)
Definition: LogControl.cc:942
static constexpr std::string_view YE
Definition: LogControl.cc:304
#define USR
Definition: Logger.h:101
virtual int overflow(int ch=EOF)
Definition: LogControl.cc:438
void setLineFormater(const shared_ptr< LogControl::LineFormater > &format_r)
Assert _lineFormater is not NULL.
Definition: LogControl.cc:600
shared_ptr< LogControl::LineFormater > _lineFormater
Definition: LogControl.cc:625
std::ostream & getStream(const char *fil_r, const char *fnc_r, int lne_r)
Definition: LogControl.cc:501
bool hideThreadName() const
Hint for Formater whether to hide the thread name.
Definition: LogControl.cc:554
static LogControlImpl * instance()
The LogControlImpl singleton.
Definition: LogControl.cc:723
std::thread _thread
Definition: LogControl.cc:204
boost::shared_ptr< log::LineWriter > _lineWriter
Definition: LogControl.cc:212
boost::shared_ptr< log::LineWriter > getLineWriter()
Definition: LogControl.cc:101
std::once_flag flagReadEnvAutomatically
Definition: LogControl.cc:52
void putRawLine(std::string &&line)
Definition: LogControl.cc:653
TriBool _hideThreadName
Hint for Formater whether to hide the thread name.
Definition: LogControl.cc:623
std::map< std::string, StreamSet > StreamTable
Definition: LogControl.cc:673
static constexpr std::string_view RE
Definition: LogControl.cc:306
static unsigned _depth
Definition: Logger.h:34
void logNothing()
Turn off logging.
Definition: LogControl.cc:886
void setLineWriter(boost::shared_ptr< log::LineWriter > writer)
Definition: LogControl.cc:96
#define L_USR(GROUP)
Definition: Logger.h:110
virtual std::string format(const std::string &, logger::LogLevel, const char *, const char *, int, const std::string &)
Definition: LogControl.cc:797
Maintain logfile related options.
Definition: LogControl.h:96
virtual int writeout(const char *s, std::streamsize n)
Definition: LogControl.cc:448
static constexpr std::string_view OO
Definition: LogControl.cc:301
static void notifyFork()
This will completely disable logging.
Definition: LogControl.cc:907
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:767
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:658
virtual std::streamsize xsputn(const char *s, std::streamsize n)
Definition: LogControl.cc:435
void logRawLine(std::string &&line)
will push a line to the logthread without formatting it
Definition: LogControl.cc:912
void hideThreadName(bool onOff_r)
Definition: LogControl.cc:561
bool ensureConnection()
Definition: LogControl.cc:231
shared_ptr< LineWriter > getLineWriter() const
Get the current LineWriter.
Definition: LogControl.cc:856
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition: AutoDispose.h:93
SpinLock _lineWriterLock
Definition: LogControl.cc:210
Loglinebuf(const std::string &group_r, LogLevel level_r)
Definition: LogControl.cc:411
Pathname _file
Definition: SystemCheck.cc:34
int & logControlValidFlag()
Definition: LogControl.cc:521
void setLineFormater(const shared_ptr< LineFormater > &formater_r)
Assign a LineFormater.
Definition: LogControl.cc:873
shared_ptr< void > _outs
Definition: LogControl.h:76
shared_ptr< Loglinestream > StreamPtr
Definition: LogControl.cc:671
const char * _file
Definition: Logger.h:35
constexpr std::string_view ZYPP_MAIN_THREAD_NAME("Zypp-main")
void pushMessage(std::string &&msg)
Definition: LogControl.cc:246
Excessive logging.
Definition: Logger.h:153
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
void emergencyShutdown()
will cause the log thread to exit and flush all sockets
Definition: LogControl.cc:902
std::string tracestr(char tag_r, unsigned depth_r, const char *file_r, const char *fnc_r, int line_r)
Definition: LogControl.cc:311
static constexpr std::string_view CY
Definition: LogControl.cc:303
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:745
static LogThread & instance()
Definition: LogControl.cc:91
LogControl implementation (thread_local Singleton).
Definition: LogControl.cc:543
FileLineWriter(const Pathname &file_r, mode_t mode_r=0)
Definition: LogControl.cc:364
std::ostream & operator<<(std::ostream &str, const LogControlImpl &)
Definition: LogControl.cc:734
StreamTable _streamtable
one streambuffer per group and level
Definition: LogControl.cc:675