libzypp 17.38.15
LogControl.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#include <sys/time.h>
13
14#include <iostream>
15#include <fstream>
16#include <string>
17#include <mutex>
18#include <map>
19
25#include <zypp-core/Date.h>
26#include <zypp-core/TriBool.h>
28
29#include <utility>
30#include <zypp-core/ng/io/Socket>
31#include <zypp-core/ng/io/SockAddr>
32#include <zypp-core/ng/base/EventLoop>
33#include <zypp-core/ng/base/EventDispatcher>
34#include <zypp-core/ng/base/Timer>
36#include <zypp-core/ng/thread/Wakeup>
38#include <zypp-core/ng/base/SocketNotifier>
39
40#include <thread>
41#include <variant>
42#include <atomic>
43#include <csignal>
44
45extern "C"
46{
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <fcntl.h>
50#include <unistd.h>
51#include <dirent.h>
52}
53
54using std::endl;
55
57
58namespace zypp
59{
60 constexpr std::string_view ZYPP_MAIN_THREAD_NAME( "Zypp-main" );
61
62 template<class> inline constexpr bool always_false_v = false;
63
68 class SpinLock {
69 public:
70 void lock () {
71 // acquire lock
72 while ( _atomicLock.test_and_set())
73 // Reschedule the current thread while we wait. Maybe, when it is our next turn, the lock is free again.
74 std::this_thread::yield();
75 }
76
77 void unlock() {
78 _atomicLock.clear();
79 }
80
81 private:
82 // we use a lock-free atomic flag here, so this lock can be safely obtained in a signal handler as well
83 std::atomic_flag _atomicLock = ATOMIC_FLAG_INIT;
84 };
85
87 {
88
89 public:
90 LogThread(const LogThread &) = delete;
91 LogThread(LogThread &&) = delete;
92 LogThread &operator=(const LogThread &) = delete;
94
96
97 static LogThread &instance () {
98 static LogThread t;
99 return t;
100 }
101
102 void setLineWriter ( zypp::shared_ptr<log::LineWriter> writer ) {
103 std::lock_guard lk( _lineWriterLock );
104 _lineWriter = std::move(writer);
105 }
106
107 zypp::shared_ptr<log::LineWriter> getLineWriter () {
108 std::lock_guard lk( _lineWriterLock );
109 auto lw = _lineWriter;
110 return lw;
111 }
112
113 void stop () {
114 _stopSignal.notify();
115 if ( _thread.get_id() != std::this_thread::get_id() )
116 _thread.join();
117 }
118
119 std::thread::id threadId () {
120 return _thread.get_id();
121 }
122
123 static std::string sockPath () {
124 static std::string path = zypp::str::Format("zypp-logsocket-%1%") % getpid();
125 return path;
126 }
127
128 private:
129
131 {
132 // Name the thread that started the logger, assuming it's the main thread.
134 _thread = std::thread( [this] () {
135 workerMain();
136 });
137 }
138
139 void workerMain () {
140
141 // force the kernel to pick another thread to handle signals
143
145
146 auto ev = zyppng::EventLoop::create();
147 auto server = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 );
148 auto stopNotifyWatch = _stopSignal.makeNotifier( );
149
150 std::vector<zyppng::Socket::Ptr> clients;
151
152 // bind to a abstract unix domain socket address, which means we do not need to care about cleaning it up
153 server->bind( std::make_shared<zyppng::UnixSockAddr>( sockPath(), true ) );
154 server->listen();
155
156 // wait for incoming connections from other threads
157 server->connectFunc( &zyppng::Socket::sigIncomingConnection, [&](){
158
159 auto cl = server->accept();
160 if ( !cl ) return;
161 clients.push_back( cl );
162
163 // wait until data is available, we operate line by line so we only
164 // log a string once we encounter \n
165 cl->connectFunc( &zyppng::Socket::sigReadyRead, [ this, sock = cl.get() ](){
166 auto writer = getLineWriter();
167 if ( !writer ) return;
168 while ( sock->canReadLine() ) {
169 auto br = sock->readLine();
170 writer->writeOut( std::string( br.data(), br.size() - 1 ) );
171 }
172 }, *cl);
173
174 // once a client disconnects we remove it from the std::vector so that the socket is not leaked
175 cl->connectFunc( &zyppng::Socket::sigDisconnected, [&clients, sock = std::weak_ptr(cl)](){
176 auto lock = sock.lock();
177 if ( !lock )
178 return;
179
180 auto idx = std::find_if( clients.begin(), clients.end(), [lock]( const auto &s ){ return lock.get() == s.get(); } );
181 clients.erase( idx );
182 });
183
184 });
185
186 stopNotifyWatch->connectFunc( &zyppng::SocketNotifier::sigActivated, [&ev]( const auto &, auto ) {
187 ev->quit();
188 });
189
190 ev->run();
191
192 // make sure we have written everything
193 auto writer = getLineWriter();
194 if ( writer ) {
195 for ( auto &sock : clients ){
196 auto br = sock->readLine();
197 while ( !br.empty() ) {
198 if ( br.back () == '\n' )
199 writer->writeOut( std::string( br.data(), br.size() - 1 ) );
200 else
201 writer->writeOut( std::string( br.data(), br.size() ) );
202
203 br = sock->readLine();
204 }
205 }
206 }
207 }
208
209 private:
210 std::thread _thread;
212
213 // since the public API uses boost::shared_ptr (via the alias zypp::shared_ptr) we can not use the atomic
214 // functionalities provided in std.
215 // this lock type can be used safely in signals
217 // boost shared_ptr has a lock free implementation of reference counting so it can be used from signal handlers as well
219 };
220
222 {
223 public:
225 // make sure the thread is running
227 }
228
229 LogClient(const LogClient &) = delete;
230 LogClient(LogClient &&) = delete;
231 LogClient &operator=(const LogClient &) = delete;
233
234 ~LogClient() { if (_sockFD >= 0) ::close(_sockFD); }
235
241 if ( _sockFD >= 0 )
242 return true;
243
244 _sockFD = ::socket( AF_UNIX, SOCK_STREAM, 0 );
245 if ( _sockFD == -1 )
246 return false;
247
249 return zyppng::trySocketConnection( _sockFD, addr, 100 );
250 }
251
255 void pushMessage ( std::string msg ) {
256 if ( inPushMessage ) {
257 return;
258 }
259
260 // make sure we do not end up in a busy loop
261 zypp::AutoDispose<bool *> res( &inPushMessage, [](auto val){
262 *val = false;
263 });
264 inPushMessage = true;
265
266 // if we are in the same thread as the Log worker we can directly push our messages out, no need to use the socket
267 if ( std::this_thread::get_id() == LogThread::instance().threadId() ) {
268 auto writer = LogThread::instance().getLineWriter();
269 if ( writer )
270 writer->writeOut( msg );
271 return;
272 }
273
274 if(!ensureConnection())
275 return;
276
277 if ( msg.back() != '\n' )
278 msg.push_back('\n');
279
280 size_t written = 0;
281 while ( written < msg.size() ) {
282 const auto res = zyppng::eintrSafeCall( ::send, _sockFD, msg.data() + written, msg.size() - written, MSG_NOSIGNAL );
283 if ( res == -1 ) {
284 //assume broken socket
285 ::close( _sockFD );
286 _sockFD = -1;
287 return;
288 }
289 written += res;
290 }
291 }
292
293 private:
294 int _sockFD = -1;
295 bool inPushMessage = false;
296 };
297
298 namespace debug
299 {
300 unsigned BlockTrace::_depth = 0;
301
302 BlockTrace::BlockTrace( const char * file_r, const char * fnc_r, int line_r, std::string msg_r )
303 : BlockTraceBase( file_r, fnc_r, line_r, std::move(msg_r) )
304 {
305 unsigned depth = _depth++;
306 zypp::base::logger::getStream( "BLOCK", zypp::base::logger::E_MIL, _file, _fnc, _line ) << "+++ (" << depth << ") " << _msg << endl;
307 }
308
310 {
311 unsigned depth = --_depth;
312 zypp::base::logger::getStream( "BLOCK", zypp::base::logger::E_MIL, _file, _fnc, _line ) << "--- (" << depth << ") " << _msg << endl;
313 }
314
315#ifndef ZYPP_NDEBUG
316 // Fg::Black: 30 Bg: 40 Attr::Normal: 22;27
317 // Fg::Red: 31 ... Attr::Bright: 1
318 // Fg::Green: 32 Attr::Reverse: 7
319 // Fg::Yellow: 33
320 // Fg::Blue: 34
321 // Fg::Magenta: 35
322 // Fg::Cyan: 36
323 // Fg::White: 37
324 // Fg::Default: 39
325 static constexpr std::string_view OO { "\033[0m" };
326 static constexpr std::string_view WH { "\033[37;40m" };
327 static constexpr std::string_view CY { "\033[36;40m" };
328 static constexpr std::string_view YE { "\033[33;1;40m" };
329 static constexpr std::string_view GR { "\033[32;40m" };
330 static constexpr std::string_view RE { "\033[31;1;40m" };
331 static constexpr std::string_view MA { "\033[35;40m" };
332
333 unsigned TraceLeave::_depth = 0;
334
335 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 )
336 {
337 static str::Format fmt { "***%2d %s%c %s(%s):%d %s" };
338 fmt % depth_r %std::string(depth_r,'.') % tag_r % Pathname::basename(file_r) % fnc_r % line_r % msg_r;
339 return fmt;
340 }
341
342 TraceLeave::TraceLeave( const char * file_r, const char * fnc_r, int line_r, std::string msg_r )
343 : BlockTraceBase( file_r, fnc_r, line_r, std::move(msg_r) )
344 {
345 unsigned depth = _depth++;
346 const std::string & m { tracestr( '>',depth, _msg, _file,_fnc,_line ) };
347 Osd(L_USR("TRACE"),depth) << m << endl;
348 }
349
351 {
352 unsigned depth = --_depth;
353 const std::string & m { tracestr( '<',depth, _msg, _file,_fnc,_line ) };
354 Osd(L_USR("TRACE"),depth) << m << endl;
355 }
356
357 Osd::Osd( std::ostream & str, int i )
358 : _strout { std::cerr }
359 , _strlog { str }
360 { _strout << (i?WH:YE); }
361
363 { _strout << OO; }
364
365 Osd & Osd::operator<<( std::ostream& (*iomanip)( std::ostream& ) )
366 {
367 _strout << iomanip;
368 _strlog << iomanip;
369 return *this;
370 }
371
373 {
374 static Osd str { L_USR("OSD") };
375 return str;
376 }
377#endif // ZYPP_NDEBUG
378} // namespace debug
379
381 namespace log
382 {
383
387
391
392 FileLineWriter::FileLineWriter( const Pathname & file_r, mode_t mode_r )
393 {
394 if ( file_r == Pathname("-") )
395 {
396 _str = &std::cerr;
397 }
398 else
399 {
400 if ( mode_r )
401 {
402 // not filesystem::assert_file as filesystem:: functions log,
403 // and this FileWriter is not yet in place.
404 int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r );
405 if ( fd != -1 )
406 ::close( fd );
407 }
408 // set unbuffered write
409 std::ofstream * fstr = 0;
410 _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) );
411 fstr->rdbuf()->pubsetbuf(0,0);
412 _str = &(*fstr);
413 }
414 }
415
417 } // namespace log
418
419
421 namespace base
422 {
424 namespace logger
425 {
426
427 inline void putStream( const std::string & group_r, LogLevel level_r,
428 const char * file_r, const char * func_r, int line_r,
429 const std::string & buffer_r );
430
432 //
433 // CLASS NAME : Loglinebuf
434 //
435 class Loglinebuf : public std::streambuf {
436
437 public:
439 Loglinebuf( std::string group_r, LogLevel level_r )
440 : _group(std::move( group_r ))
441 , _level( level_r )
442 , _file( "" )
443 , _func( "" )
444 , _line( -1 )
445 {}
446
447 Loglinebuf(const Loglinebuf &) = default;
448 Loglinebuf(Loglinebuf &&) = default;
449 Loglinebuf &operator=(const Loglinebuf &) = default;
451
453 ~Loglinebuf() override
454 {
455 if ( !_buffer.empty() )
456 writeout( "\n", 1 );
457 }
458
460 void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
461 {
462 _file = fil_r;
463 _func = fnc_r;
464 _line = lne_r;
465 }
466
467 private:
469 std::streamsize xsputn( const char * s, std::streamsize n ) override
470 { return writeout( s, n ); }
471
472 int overflow( int ch = EOF ) override
473 {
474 if ( ch != EOF )
475 {
476 char tmp = ch;
477 writeout( &tmp, 1 );
478 }
479 return 0;
480 }
481
482 virtual int writeout( const char* s, std::streamsize n )
483 {
484 //logger::putStream( _group, _level, _file, _func, _line, _buffer );
485 //return n;
486 if ( s && n )
487 {
488 const char * c = s;
489 for ( int i = 0; i < n; ++i, ++c )
490 {
491 if ( *c == '\n' ) {
492 _buffer += std::string( s, c-s );
494 _buffer = std::string();
495 s = c+1;
496 }
497 }
498 if ( s < c )
499 {
500 _buffer += std::string( s, c-s );
501 }
502 }
503 return n;
504 }
505
506 private:
507 std::string _group;
509 const char * _file;
510 const char * _func;
511 int _line;
512 std::string _buffer;
513 };
514
516
518 //
519 // CLASS NAME : Loglinestream
520 //
522
523 public:
525 Loglinestream( const std::string & group_r, LogLevel level_r )
526 : _mybuf( group_r, level_r )
527 , _mystream( &_mybuf )
528 {}
529
530 Loglinestream(const Loglinestream &) = delete;
534
537 { _mystream.flush(); }
538
539 public:
541 std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
542 {
543 _mybuf.tagSet( fil_r, fnc_r, lne_r );
544 return _mystream;
545 }
546
547 private:
549 std::ostream _mystream;
550 };
551
552
553 struct LogControlImpl;
554
555 /*
556 * Ugly hack to prevent the use of LogControlImpl when libzypp is shutting down.
557 * Due to the C++ standard, thread_local static instances are cleaned up before the first global static
558 * destructor is called. So all classes that use logging after that point in time would crash the
559 * application because it is accessing a variable that has already been destroyed.
560 */
562 // We are using a POD flag that does not have a destructor,
563 // to flag if the thread_local destructors were already executed.
564 // Since TLS data is stored in a segment that is available until the thread ceases to exist it should still be readable
565 // after thread_local c++ destructors were already executed. Or so I hope.
566 static thread_local int logControlValid = 0;
567 return logControlValid;
568 }
569
571 //
572 // CLASS NAME : LogControlImpl
573 //
584 {
585 public:
586 bool isExcessive() const { return _excessive; }
587
588 void excessive( bool onOff_r )
589 { _excessive = onOff_r; }
590
591
593 bool hideThreadName() const
594 {
595 if ( indeterminate(_hideThreadName) )
597 return bool(_hideThreadName);
598 }
599
600 void hideThreadName( bool onOff_r )
601 { _hideThreadName = onOff_r; }
602
605 {
606 auto impl = LogControlImpl::instance();
607 return impl ? impl->hideThreadName() : false;
608 }
609
610 static void instanceHideThreadName( bool onOff_r )
611 {
612 auto impl = LogControlImpl::instance();
613 if ( impl ) impl->hideThreadName( onOff_r );
614 }
615
617 static bool instanceLogToPPID( )
618 {
619 auto impl = LogControlImpl::instance();
620 return impl ? impl->_logToPPIDMode : false;
621 }
622
624 static void instanceSetLogToPPID( bool onOff_r )
625 {
626 auto impl = LogControlImpl::instance();
627 if ( impl )
628 impl->_logToPPIDMode = onOff_r;
629 }
630
634
637
640 {
641 if ( format_r )
642 _lineFormater = format_r;
643 else
645 }
646
647 void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
648 {
649 if ( logfile_r.empty() )
651 else if ( logfile_r == Pathname( "-" ) )
653 else
655 }
656
657 private:
659 std::ostream _no_stream;
661 bool _logToPPIDMode = false;
662 mutable TriBool _hideThreadName = indeterminate;
663
665
666 public:
668 std::ostream & getStream( const std::string & group_r,
669 LogLevel level_r,
670 const char * file_r,
671 const char * func_r,
672 const int line_r )
673 {
674 if ( ! getLineWriter() )
675 return _no_stream;
676 if ( level_r == E_XXX && !_excessive )
677 return _no_stream;
678
679 if ( !_streamtable[group_r][level_r] )
680 {
681 _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
682 }
683 std::ostream & ret( _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ) );
684 if ( !ret )
685 {
686 ret.clear();
687 ret << "---<RESET LOGSTREAM FROM FAILED STATE]" << endl;
688 }
689 return ret;
690 }
691
692 void putRawLine ( std::string &&line ) {
693 _logClient.pushMessage( std::move(line) );
694 }
695
697 void putStream( const std::string & group_r,
698 LogLevel level_r,
699 const char * file_r,
700 const char * func_r,
701 int line_r,
702 const std::string & message_r )
703 {
704 _logClient.pushMessage( _lineFormater->format( group_r, level_r,
705 file_r, func_r, line_r,
706 message_r ) );
707 }
708
709 private:
711 using StreamSet = std::map<LogLevel, StreamPtr>;
712 using StreamTable = std::map<std::string, StreamSet>;
716
717 private:
718
719 void readEnvVars () {
720 if ( getenv("ZYPP_LOGFILE") )
721 logfile( getenv("ZYPP_LOGFILE") );
722
723 if ( getenv("ZYPP_PROFILING") )
724 {
726 setLineFormater(formater);
727 }
728 }
729
733 : _no_stream( NULL )
734 , _excessive( getenv("ZYPP_FULLLOG") )
735 , _lineFormater( new LogControl::LineFormater )
736 {
739
740 // make sure the LogControl is invalidated when we fork
741 pthread_atfork( nullptr, nullptr, &LogControl::notifyFork );
742 }
743
744 public:
745
750
752 {
754 }
755
762 static LogControlImpl *instance();
763 };
764
765
766 // 'THE' LogControlImpl singleton
768 {
769 thread_local static LogControlImpl _instance;
770 if ( logControlValidFlag() > 0 )
771 return &_instance;
772 return nullptr;
773 }
774
776
778 inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & )
779 {
780 return str << "LogControlImpl";
781 }
782
784 //
785 // Access from logger::
786 //
788
789 std::ostream & getStream( const char * group_r,
790 LogLevel level_r,
791 const char * file_r,
792 const char * func_r,
793 const int line_r )
794 {
795 static std::ostream nstream(NULL);
796 auto control = LogControlImpl::instance();
797 if ( !control || !group_r || strlen(group_r ) == 0 ) {
798 return nstream;
799 }
800
801
802
803 return control->getStream( group_r,
804 level_r,
805 file_r,
806 func_r,
807 line_r );
808 }
809
811 inline void putStream( const std::string & group_r, LogLevel level_r,
812 const char * file_r, const char * func_r, int line_r,
813 const std::string & buffer_r )
814 {
815 auto control = LogControlImpl::instance();
816 if ( !control )
817 return;
818
819 control->putStream( group_r, level_r,
820 file_r, func_r, line_r,
821 buffer_r );
822 }
823
825 {
826 auto impl = LogControlImpl::instance();
827 if ( !impl )
828 return false;
829 return impl->isExcessive();
830 }
831
833 } // namespace logger
834
835
836 using logger::LogControlImpl;
837
839 // LineFormater
841 std::string LogControl::LineFormater::format( const std::string & group_r,
842 logger::LogLevel level_r,
843 const char * file_r,
844 const char * func_r,
845 int line_r,
846 const std::string & message_r )
847 {
848 // hostname changes are rare, look it up only once
849 static const char * hostname = []() -> const char * {
850 static char buf[1024];
851 return gethostname( buf, sizeof(buf) ) ? "unknown" : buf;
852 }();
853 struct timeval tp;
854 gettimeofday( &tp, NULL );
855 std::string now( Date( tp.tv_sec ).form( "%Y-%m-%d %H:%M:%S" ) );
856 now += str::form( ".%03ld", (long)(tp.tv_usec / 1000) );
857 std::string ret;
858
859 const bool logToPPID = LogControlImpl::instanceLogToPPID();
860 if ( !logToPPID && LogControlImpl::instanceHideThreadName() )
861 ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
862 now.c_str(), level_r,
863 hostname,
864 getpid(),
865 group_r.c_str(),
866 file_r, func_r, line_r,
867 message_r.c_str() );
868 else
869 ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d {T:%s} %s",
870 now.c_str(), level_r,
871 hostname,
872 logToPPID ? getppid() : getpid(),
873 group_r.c_str(),
874 file_r, func_r, line_r,
875 zyppng::ThreadData::current().name().c_str(),
876 message_r.c_str() );
877 return ret;
878 }
879
880 std::string LogControl::JournalLineFormater::format( const std::string & group_r,
881 logger::LogLevel level_r,
882 const char * file_r,
883 const char * func_r,
884 int line_r,
885 const std::string & message_r )
886 {
887 std::string ret;
889 ret = str::form( "<%d> [%s] %s(%s):%d %s",
890 level_r, group_r.c_str(),
891 file_r, func_r, line_r,
892 message_r.c_str() );
893 else
894 ret = str::form( "<%d> [%s] %s(%s):%d {T:%s} %s",
895 level_r, group_r.c_str(),
896 file_r, func_r, line_r,
897 zyppng::ThreadData::current().name().c_str(),
898 message_r.c_str() );
899 return ret;
900 }
901
902 //
903 // CLASS NAME : LogControl
904 // Forward to LogControlImpl singleton.
905 //
907
908
909 void LogControl::logfile( const Pathname & logfile_r )
910 {
911 auto impl = LogControlImpl::instance();
912 if ( !impl )
913 return;
914
915 impl->logfile( logfile_r );
916 }
917
918 void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
919 {
920 auto impl = LogControlImpl::instance();
921 if ( !impl )
922 return;
923
924 impl->logfile( logfile_r, mode_r );
925 }
926
928 {
929 auto impl = LogControlImpl::instance();
930 if ( !impl )
931 return nullptr;
932
933 return impl->getLineWriter();
934 }
935
937 {
938 auto impl = LogControlImpl::instance();
939 if ( !impl )
940 return;
941 impl->setLineWriter( writer_r );
942 }
943
945 {
946 auto impl = LogControlImpl::instance();
947 if ( !impl )
948 return;
949 impl->setLineFormater( formater_r );
950 }
951
956
958 {
959 auto impl = LogControlImpl::instance();
960 if ( !impl )
961 return;
962 impl->setLineWriter( shared_ptr<LineWriter>() );
963 }
964
966 {
967 auto impl = LogControlImpl::instance();
968 if ( !impl )
969 return;
970 impl->setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) );
971 }
972
977
982
983 void LogControl::logRawLine ( std::string &&line )
984 {
985 LogControlImpl::instance ()->putRawLine ( std::move(line) );
986 }
987
989 //
990 // LogControl::TmpExcessive
991 //
994 {
995 auto impl = LogControlImpl::instance();
996 if ( !impl )
997 return;
998 impl->excessive( true );
999 }
1001 {
1002 auto impl = LogControlImpl::instance();
1003 if ( !impl )
1004 return;
1005 impl->excessive( false );
1006 }
1007
1008 /******************************************************************
1009 **
1010 ** FUNCTION NAME : operator<<
1011 ** FUNCTION TYPE : std::ostream &
1012 */
1013 std::ostream & operator<<( std::ostream & str, const LogControl & )
1014 {
1015 auto impl = LogControlImpl::instance();
1016 if ( !impl )
1017 return str;
1018 return str << *impl;
1019 }
1020
1022 } // namespace base
1025} // namespace zypp
std::once_flag flagReadEnvAutomatically
Definition LogControl.cc:56
#define L_USR(GROUP)
Definition Logger.h:144
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
Store and operate on date (time_t).
Definition Date.h:33
std::string form(const std::string &format_r) const
Return string representation according to format as localtime.
Definition Date.h:112
bool ensureConnection()
LogClient(LogClient &&)=delete
LogClient(const LogClient &)=delete
LogClient & operator=(const LogClient &)=delete
LogClient & operator=(LogClient &&)=delete
void pushMessage(std::string msg)
shared_ptr< log::LineWriter > _lineWriter
std::thread _thread
LogThread & operator=(const LogThread &)=delete
zypp::shared_ptr< log::LineWriter > getLineWriter()
zyppng::Wakeup _stopSignal
LogThread(const LogThread &)=delete
std::thread::id threadId()
LogThread(LogThread &&)=delete
LogThread & operator=(LogThread &&)=delete
SpinLock _lineWriterLock
void setLineWriter(zypp::shared_ptr< log::LineWriter > writer)
static LogThread & instance()
Definition LogControl.cc:97
static std::string sockPath()
std::string basename() const
Return the last component of this path.
Definition Pathname.h:137
std::atomic_flag _atomicLock
Definition LogControl.cc:83
Maintain logfile related options.
Definition LogControl.h:97
friend std::ostream & operator<<(std::ostream &str, const LogControl &obj)
relates: LogControl Stream output
LogControl()
Default ctor: Singleton.
Definition LogControl.h:228
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:113
const std::string & asString() const
String representation.
Definition Pathname.h:94
bool empty() const
Test for an empty path.
Definition Pathname.h:117
static Ptr create(GMainContext *ctx=nullptr)
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
nullptr CURL handle void p CURLversion nullptr struct curl_slist list CURLM CURLM_INTERNAL_ERROR CURLM CURL CURLM_INTERNAL_ERROR CURLM curl_socket_t s
Definition curl_dl.cc:111
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition String.h:31
Definition ansi.h:855
String related utilities and Regular expression matching.
int & logControlValidFlag()
std::ostream & operator<<(std::ostream &str, const LogControlImpl &)
relates: LogControlImpl Stream output
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:186
@ E_XXX
Excessive logging.
Definition Logger.h:187
@ E_MIL
Milestone.
Definition Logger.h:189
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.
Osd & getOSD()
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:39
Easy-to use interface to the ZYPP dependency resolver.
constexpr bool always_false_v
Definition LogControl.cc:62
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.
std::string format(const std::string &, logger::LogLevel, const char *, const char *, int, const std::string &) override
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
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
BlockTraceBase(const BlockTraceBase &)=delete
BlockTrace(const BlockTrace &)=delete
static unsigned _depth
Definition Logger.h:49
std::ostream & _strlog
Definition Logger.h:91
Osd(std::ostream &, int=0)
std::ostream & _strout
Definition Logger.h:90
Osd & operator<<(Tp &&val)
Definition Logger.h:80
TraceLeave(const TraceLeave &)=delete
static unsigned _depth
Definition Logger.h:68
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:254
void setName(T &&name)
static ZYPP_API ThreadData & current()
Definition threaddata.cc:16
const std::string & name() const
Definition threaddata.cc:22