libzypp 17.35.18
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
22#include <zypp-core/Date.h>
23#include <zypp-core/TriBool.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
42extern "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
51using std::endl;
52
54
55namespace 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
84 {
85
86 public:
87 LogThread(const LogThread &) = delete;
88 LogThread(LogThread &&) = delete;
89 LogThread &operator=(const LogThread &) = delete;
91
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 () {
111 _stopSignal.notify();
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
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
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;
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
366
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
397
398
400 namespace base
401 {
403 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;
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 ); }
450
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 }
460
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;
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 };
530
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 }
578
579 void hideThreadName( bool onOff_r )
580 { _hideThreadName = onOff_r; }
581
584 {
585 auto impl = LogControlImpl::instance();
586 return impl ? impl->hideThreadName() : false;
587 }
588
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
613
616
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() )
630 else if ( logfile_r == Pathname( "-" ) )
632 else
634 }
635
636 private:
638 std::ostream _no_stream;
640 bool _logToPPIDMode = false;
641 mutable TriBool _hideThreadName = indeterminate;
642
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:
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 {
705 setLineFormater(formater);
706 }
707 }
708
712 : _no_stream( NULL )
713 , _excessive( getenv("ZYPP_FULLLOG") )
714 , _lineFormater( new LogControl::LineFormater )
715 {
718
719 // make sure the LogControl is invalidated when we fork
720 pthread_atfork( nullptr, nullptr, &LogControl::notifyFork );
721 }
722
723 public:
724
729
731 {
733 }
734
741 static LogControlImpl *instance();
742 };
743
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
804 {
805 auto impl = LogControlImpl::instance();
806 if ( !impl )
807 return false;
808 return impl->isExcessive();
809 }
810
812 } // namespace logger
813
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
880 {
881 auto impl = LogControlImpl::instance();
882 if ( !impl )
883 return nullptr;
884
885 return impl->getLineWriter();
886 }
887
889 {
890 auto impl = LogControlImpl::instance();
891 if ( !impl )
892 return;
893 impl->setLineWriter( writer_r );
894 }
895
897 {
898 auto impl = LogControlImpl::instance();
899 if ( !impl )
900 return;
901 impl->setLineFormater( formater_r );
902 }
903
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
929
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
std::once_flag flagReadEnvAutomatically
Definition LogControl.cc:53
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
static Date now()
Return the current time.
Definition Date.h:78
bool ensureConnection()
LogClient(LogClient &&)=delete
LogClient(const LogClient &)=delete
LogClient & operator=(const LogClient &)=delete
LogClient & operator=(LogClient &&)=delete
void pushMessage(std::string msg)
boost::shared_ptr< log::LineWriter > getLineWriter()
std::thread _thread
LogThread & operator=(const LogThread &)=delete
zyppng::Wakeup _stopSignal
LogThread(const LogThread &)=delete
std::thread::id threadId()
LogThread(LogThread &&)=delete
LogThread & operator=(LogThread &&)=delete
SpinLock _lineWriterLock
static LogThread & instance()
Definition LogControl.cc:94
static std::string sockPath()
boost::shared_ptr< log::LineWriter > _lineWriter
void setLineWriter(boost::shared_ptr< log::LineWriter > writer)
Definition LogControl.cc:99
std::string basename() const
Return the last component of this path.
Definition Pathname.h:130
std::atomic_flag _atomicLock
Definition LogControl.cc:80
Maintain logfile related options.
Definition LogControl.h:97
friend std::ostream & operator<<(std::ostream &str, const LogControl &obj)
LogControl()
Default ctor: Singleton.
Definition LogControl.h:215
shared_ptr< LineWriter > getLineWriter() const
Get the current LineWriter.
void setLineWriter(const shared_ptr< LineWriter > &writer_r)
Assign a LineWriter.
void logToStdErr()
Log to std::err.
void logRawLine(std::string &&line)
will push a line to the logthread without formatting it
void logNothing()
Turn off logging.
static void notifyFork()
This will completely disable logging.
void setLineFormater(const shared_ptr< LineFormater > &formater_r)
Assign a LineFormater.
void enableLogForwardingMode(bool enable=true)
void logfile(const Pathname &logfile_r)
Set path for the logfile.
void emergencyShutdown()
will cause the log thread to exit and flush all sockets
int overflow(int ch=EOF) override
std::streamsize xsputn(const char *s, std::streamsize n) override
Loglinebuf(const Loglinebuf &)=default
Loglinebuf(std::string group_r, LogLevel level_r)
Loglinebuf(Loglinebuf &&)=default
Loglinebuf & operator=(const Loglinebuf &)=default
void tagSet(const char *fil_r, const char *fnc_r, int lne_r)
virtual int writeout(const char *s, std::streamsize n)
Loglinebuf & operator=(Loglinebuf &&)=default
Loglinestream(const std::string &group_r, LogLevel level_r)
Loglinestream(const Loglinestream &)=delete
Loglinestream & operator=(const Loglinestream &)=delete
std::ostream & getStream(const char *fil_r, const char *fnc_r, int lne_r)
Loglinestream(Loglinestream &&)=delete
Loglinestream & operator=(Loglinestream &&)=delete
const char * c_str() const
String representation.
Definition Pathname.h:112
const std::string & asString() const
String representation.
Definition Pathname.h:93
bool empty() const
Test for an empty path.
Definition Pathname.h:116
static Ptr create()
SignalProxy< void()> sigReadyRead()
Definition iodevice.cc:368
SignalProxy< void(const SocketNotifier &sock, int evTypes)> sigActivated()
static Ptr create(int domain, int type, int protocol)
Definition socket.cc:458
SignalProxy< void()> sigDisconnected()
Definition socket.cc:882
SignalProxy< void()> sigIncomingConnection()
Definition socket.cc:872
std::shared_ptr< Socket > Ptr
Definition socket.h:71
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:37
Definition Arch.h:364
String related utilities and Regular expression matching.
int & logControlValidFlag()
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's what Loglinebuf calls.
LogLevel
Definition of log levels.
Definition Logger.h:156
@ E_XXX
Excessive logging.
Definition Logger.h:157
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.
static constexpr std::string_view WH
static constexpr std::string_view OO
static constexpr std::string_view YE
static constexpr std::string_view CY
static constexpr std::string_view GR
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)
static constexpr std::string_view MA
static constexpr std::string_view RE
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:37
Easy-to use interface to the ZYPP dependency resolver.
constexpr bool always_false_v
Definition LogControl.cc:59
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition String.h:30
constexpr std::string_view ZYPP_MAIN_THREAD_NAME("Zypp-main")
bool blockAllSignalsForCurrentThread()
bool trySocketConnection(int &sockFD, const SockAddr &addr, uint64_t timeout)
auto eintrSafeCall(Fun &&function, Args &&... args)
static LogControlImpl * instance()
The LogControlImpl singleton.
static bool instanceHideThreadName()
LogControlImpl()
Singleton ctor.
static void instanceSetLogToPPID(bool onOff_r)
static bool instanceLogToPPID()
Hint for formatter wether we forward all logs to a parents log.
If you want to format loglines by yourself, derive from this, and overload format.
Definition LogControl.h:115
virtual std::string format(const std::string &, logger::LogLevel, const char *, const char *, int, const std::string &)
LogControl implementation (thread_local Singleton).
void putRawLine(std::string &&line)
void setLineWriter(const shared_ptr< LogControl::LineWriter > &writer_r)
NULL _lineWriter indicates no loggin.
static LogControlImpl * instance()
The LogControlImpl singleton.
LogControlImpl(LogControlImpl &&)=delete
LogControlImpl & operator=(const LogControlImpl &)=delete
std::ostream & operator<<(std::ostream &str, const LogControlImpl &)
Stream output.
static void instanceHideThreadName(bool onOff_r)
static void instanceSetLogToPPID(bool onOff_r)
StreamTable _streamtable
one streambuffer per group and level
static bool instanceLogToPPID()
Hint for formatter wether we forward all logs to a parents log.
LogControlImpl(const LogControlImpl &)=delete
std::map< std::string, StreamSet > StreamTable
bool _logToPPIDMode
Hint for formatter to use the PPID and always show the thread name.
void setLineFormater(const shared_ptr< LogControl::LineFormater > &format_r)
Assert _lineFormater is not NULL.
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)
void logfile(const Pathname &logfile_r, mode_t mode_r=0640)
shared_ptr< LogControl::LineWriter > getLineWriter() const
std::map< LogLevel, StreamPtr > StreamSet
shared_ptr< LogControl::LineFormater > _lineFormater
LogControlImpl & operator=(LogControlImpl &&)=delete
bool hideThreadName() const
Hint for Formater whether to hide the thread name.
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.
TriBool _hideThreadName
Hint for Formater whether to hide the thread name.
shared_ptr< Loglinestream > StreamPtr
std::ostream & _strlog
Definition Logger.h:63
Osd(std::ostream &, int=0)
std::ostream & _strout
Definition Logger.h:62
Osd & operator<<(Tp &&val)
Definition Logger.h:52
TraceLeave(const TraceLeave &)=delete
static unsigned _depth
Definition Logger.h:36
std::string _msg
Definition Logger.h:40
const char * _fnc
Definition Logger.h:38
const char * _file
Definition Logger.h:37
LineWriter to file.
Definition LogControl.h:73
shared_ptr< void > _outs
Definition LogControl.h:76
FileLineWriter(const Pathname &file_r, mode_t mode_r=0)
LineWriter to stderr.
Definition LogControl.h:64
StreamLineWriter(std::ostream &str_r)
Definition LogControl.h:46
Convenient building of std::string with boost::format.
Definition String.h:253
void setName(T &&name)
static ZYPP_API ThreadData & current()
Definition threaddata.cc:16
const std::string & name() const
Definition threaddata.cc:22
#define L_USR(GROUP)
Definition Logger.h:114