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