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