libzypp 17.38.14
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
23#include <zypp-core/Date.h>
24#include <zypp-core/TriBool.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
43extern "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
52using std::endl;
53
55
56namespace 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
85 {
86
87 public:
88 LogThread(const LogThread &) = delete;
89 LogThread(LogThread &&) = delete;
90 LogThread &operator=(const LogThread &) = delete;
92
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 ( _ownerPid != getpid() )
114 {
115 // We are in a forked child: the worker thread only exists in the
116 // parent, join() would block forever (e.g. a fork server calling
117 // exit() hangs in this dtor at __run_exit_handlers). Detach so
118 // ~thread() does not std::terminate().
119 _thread.detach();
120 return;
121 }
122 if ( _thread.get_id() != std::this_thread::get_id() )
123 _thread.join();
124 }
125
126 std::thread::id threadId () {
127 return _thread.get_id();
128 }
129
130 static std::string sockPath () {
131 static std::string path = zypp::str::Format("zypp-logsocket-%1%") % getpid();
132 return path;
133 }
134
135 private:
136
138 {
139 // Name the thread that started the logger, assuming it's the main thread.
141 _thread = std::thread( [this] () {
142 workerMain();
143 });
144 }
145
146 pid_t _ownerPid = getpid();
147
148 void workerMain () {
149
150 // force the kernel to pick another thread to handle signals
152
154
155 auto ev = zyppng::EventLoop::create();
156 auto server = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 );
157 auto stopNotifyWatch = _stopSignal.makeNotifier( );
158
159 std::vector<zyppng::Socket::Ptr> clients;
160
161 // bind to a abstract unix domain socket address, which means we do not need to care about cleaning it up
162 server->bind( std::make_shared<zyppng::UnixSockAddr>( sockPath(), true ) );
163 server->listen();
164
165 // wait for incoming connections from other threads
166 server->connectFunc( &zyppng::Socket::sigIncomingConnection, [&](){
167
168 auto cl = server->accept();
169 if ( !cl ) return;
170 clients.push_back( cl );
171
172 // wait until data is available, we operate line by line so we only
173 // log a string once we encounter \n
174 cl->connectFunc( &zyppng::Socket::sigReadyRead, [ this, sock = cl.get() ](){
175 auto writer = getLineWriter();
176 if ( !writer ) return;
177 while ( sock->canReadLine() ) {
178 auto br = sock->readLine();
179 writer->writeOut( std::string( br.data(), br.size() - 1 ) );
180 }
181 }, *cl);
182
183 // once a client disconnects we remove it from the std::vector so that the socket is not leaked
184 cl->connectFunc( &zyppng::Socket::sigDisconnected, [&clients, sock = std::weak_ptr(cl)](){
185 auto lock = sock.lock();
186 if ( !lock )
187 return;
188
189 auto idx = std::find_if( clients.begin(), clients.end(), [lock]( const auto &s ){ return lock.get() == s.get(); } );
190 clients.erase( idx );
191 });
192
193 });
194
195 stopNotifyWatch->connectFunc( &zyppng::SocketNotifier::sigActivated, [&ev]( const auto &, auto ) {
196 ev->quit();
197 });
198
199 ev->run();
200
201 // make sure we have written everything
202 auto writer = getLineWriter();
203 if ( writer ) {
204 for ( auto &sock : clients ){
205 auto br = sock->readLine();
206 while ( !br.empty() ) {
207 if ( br.back () == '\n' )
208 writer->writeOut( std::string( br.data(), br.size() - 1 ) );
209 else
210 writer->writeOut( std::string( br.data(), br.size() ) );
211
212 br = sock->readLine();
213 }
214 }
215 }
216 }
217
218 private:
219 std::thread _thread;
221
222 // since the public API uses boost::shared_ptr (via the alias zypp::shared_ptr) we can not use the atomic
223 // functionalities provided in std.
224 // this lock type can be used safely in signals
226 // boost shared_ptr has a lock free implementation of reference counting so it can be used from signal handlers as well
228 };
229
231 {
232 public:
234 // make sure the thread is running
236 }
237
238 LogClient(const LogClient &) = delete;
239 LogClient(LogClient &&) = delete;
240 LogClient &operator=(const LogClient &) = delete;
242
243 ~LogClient() { if (_sockFD >= 0) ::close(_sockFD); }
244
250 if ( _sockFD >= 0 )
251 return true;
252
253 _sockFD = ::socket( AF_UNIX, SOCK_STREAM, 0 );
254 if ( _sockFD == -1 )
255 return false;
256
258 return zyppng::trySocketConnection( _sockFD, addr, 100 );
259 }
260
264 void pushMessage ( std::string msg ) {
265 if ( inPushMessage ) {
266 return;
267 }
268
269 // make sure we do not end up in a busy loop
270 zypp::AutoDispose<bool *> res( &inPushMessage, [](auto val){
271 *val = false;
272 });
273 inPushMessage = true;
274
275 // if we are in the same thread as the Log worker we can directly push our messages out, no need to use the socket
276 if ( std::this_thread::get_id() == LogThread::instance().threadId() ) {
277 auto writer = LogThread::instance().getLineWriter();
278 if ( writer )
279 writer->writeOut( msg );
280 return;
281 }
282
283 if(!ensureConnection())
284 return;
285
286 if ( msg.back() != '\n' )
287 msg.push_back('\n');
288
289 size_t written = 0;
290 while ( written < msg.size() ) {
291 const auto res = zyppng::eintrSafeCall( ::send, _sockFD, msg.data() + written, msg.size() - written, MSG_NOSIGNAL );
292 if ( res == -1 ) {
293 //assume broken socket
294 ::close( _sockFD );
295 _sockFD = -1;
296 return;
297 }
298 written += res;
299 }
300 }
301
302 private:
303 int _sockFD = -1;
304 bool inPushMessage = false;
305 };
306
307 namespace debug
308 {
309 unsigned BlockTrace::_depth = 0;
310
311 BlockTrace::BlockTrace( const char * file_r, const char * fnc_r, int line_r, std::string msg_r )
312 : BlockTraceBase( file_r, fnc_r, line_r, std::move(msg_r) )
313 {
314 unsigned depth = _depth++;
315 zypp::base::logger::getStream( "BLOCK", zypp::base::logger::E_MIL, _file, _fnc, _line ) << "+++ (" << depth << ") " << _msg << endl;
316 }
317
319 {
320 unsigned depth = --_depth;
321 zypp::base::logger::getStream( "BLOCK", zypp::base::logger::E_MIL, _file, _fnc, _line ) << "--- (" << depth << ") " << _msg << endl;
322 }
323
324#ifndef ZYPP_NDEBUG
325 // Fg::Black: 30 Bg: 40 Attr::Normal: 22;27
326 // Fg::Red: 31 ... Attr::Bright: 1
327 // Fg::Green: 32 Attr::Reverse: 7
328 // Fg::Yellow: 33
329 // Fg::Blue: 34
330 // Fg::Magenta: 35
331 // Fg::Cyan: 36
332 // Fg::White: 37
333 // Fg::Default: 39
334 static constexpr std::string_view OO { "\033[0m" };
335 static constexpr std::string_view WH { "\033[37;40m" };
336 static constexpr std::string_view CY { "\033[36;40m" };
337 static constexpr std::string_view YE { "\033[33;1;40m" };
338 static constexpr std::string_view GR { "\033[32;40m" };
339 static constexpr std::string_view RE { "\033[31;1;40m" };
340 static constexpr std::string_view MA { "\033[35;40m" };
341
342 unsigned TraceLeave::_depth = 0;
343
344 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 )
345 {
346 static str::Format fmt { "***%2d %s%c %s(%s):%d %s" };
347 fmt % depth_r %std::string(depth_r,'.') % tag_r % Pathname::basename(file_r) % fnc_r % line_r % msg_r;
348 return fmt;
349 }
350
351 TraceLeave::TraceLeave( const char * file_r, const char * fnc_r, int line_r, std::string msg_r )
352 : BlockTraceBase( file_r, fnc_r, line_r, std::move(msg_r) )
353 {
354 unsigned depth = _depth++;
355 const std::string & m { tracestr( '>',depth, _msg, _file,_fnc,_line ) };
356 Osd(L_USR("TRACE"),depth) << m << endl;
357 }
358
360 {
361 unsigned depth = --_depth;
362 const std::string & m { tracestr( '<',depth, _msg, _file,_fnc,_line ) };
363 Osd(L_USR("TRACE"),depth) << m << endl;
364 }
365
366 Osd::Osd( std::ostream & str, int i )
367 : _strout { std::cerr }
368 , _strlog { str }
369 { _strout << (i?WH:YE); }
370
372 { _strout << OO; }
373
374 Osd & Osd::operator<<( std::ostream& (*iomanip)( std::ostream& ) )
375 {
376 _strout << iomanip;
377 _strlog << iomanip;
378 return *this;
379 }
380
382 {
383 static Osd str { L_USR("OSD") };
384 return str;
385 }
386#endif // ZYPP_NDEBUG
387} // namespace debug
388
390 namespace log
391 {
392
396
400
401 FileLineWriter::FileLineWriter( const Pathname & file_r, mode_t mode_r )
402 {
403 if ( file_r == Pathname("-") )
404 {
405 _str = &std::cerr;
406 }
407 else
408 {
409 if ( mode_r )
410 {
411 // not filesystem::assert_file as filesystem:: functions log,
412 // and this FileWriter is not yet in place.
413 int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r );
414 if ( fd != -1 )
415 ::close( fd );
416 }
417 // set unbuffered write
418 std::ofstream * fstr = 0;
419 _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) );
420 fstr->rdbuf()->pubsetbuf(0,0);
421 _str = &(*fstr);
422 }
423 }
424
426 } // namespace log
427
428
430 namespace base
431 {
433 namespace logger
434 {
435
436 inline void putStream( const std::string & group_r, LogLevel level_r,
437 const char * file_r, const char * func_r, int line_r,
438 const std::string & buffer_r );
439
441 //
442 // CLASS NAME : Loglinebuf
443 //
444 class Loglinebuf : public std::streambuf {
445
446 public:
448 Loglinebuf( std::string group_r, LogLevel level_r )
449 : _group(std::move( group_r ))
450 , _level( level_r )
451 , _file( "" )
452 , _func( "" )
453 , _line( -1 )
454 {}
455
456 Loglinebuf(const Loglinebuf &) = default;
457 Loglinebuf(Loglinebuf &&) = default;
458 Loglinebuf &operator=(const Loglinebuf &) = default;
460
462 ~Loglinebuf() override
463 {
464 if ( !_buffer.empty() )
465 writeout( "\n", 1 );
466 }
467
469 void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
470 {
471 _file = fil_r;
472 _func = fnc_r;
473 _line = lne_r;
474 }
475
476 private:
478 std::streamsize xsputn( const char * s, std::streamsize n ) override
479 { return writeout( s, n ); }
480
481 int overflow( int ch = EOF ) override
482 {
483 if ( ch != EOF )
484 {
485 char tmp = ch;
486 writeout( &tmp, 1 );
487 }
488 return 0;
489 }
490
491 virtual int writeout( const char* s, std::streamsize n )
492 {
493 //logger::putStream( _group, _level, _file, _func, _line, _buffer );
494 //return n;
495 if ( s && n )
496 {
497 const char * c = s;
498 for ( int i = 0; i < n; ++i, ++c )
499 {
500 if ( *c == '\n' ) {
501 _buffer += std::string( s, c-s );
503 _buffer = std::string();
504 s = c+1;
505 }
506 }
507 if ( s < c )
508 {
509 _buffer += std::string( s, c-s );
510 }
511 }
512 return n;
513 }
514
515 private:
516 std::string _group;
518 const char * _file;
519 const char * _func;
520 int _line;
521 std::string _buffer;
522 };
523
525
527 //
528 // CLASS NAME : Loglinestream
529 //
531
532 public:
534 Loglinestream( const std::string & group_r, LogLevel level_r )
535 : _mybuf( group_r, level_r )
536 , _mystream( &_mybuf )
537 {}
538
539 Loglinestream(const Loglinestream &) = delete;
543
546 { _mystream.flush(); }
547
548 public:
550 std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
551 {
552 _mybuf.tagSet( fil_r, fnc_r, lne_r );
553 return _mystream;
554 }
555
556 private:
558 std::ostream _mystream;
559 };
560
561
562 struct LogControlImpl;
563
564 /*
565 * Ugly hack to prevent the use of LogControlImpl when libzypp is shutting down.
566 * Due to the C++ standard, thread_local static instances are cleaned up before the first global static
567 * destructor is called. So all classes that use logging after that point in time would crash the
568 * application because it is accessing a variable that has already been destroyed.
569 */
571 // We are using a POD flag that does not have a destructor,
572 // to flag if the thread_local destructors were already executed.
573 // Since TLS data is stored in a segment that is available until the thread ceases to exist it should still be readable
574 // after thread_local c++ destructors were already executed. Or so I hope.
575 static thread_local int logControlValid = 0;
576 return logControlValid;
577 }
578
580 //
581 // CLASS NAME : LogControlImpl
582 //
593 {
594 public:
595 bool isExcessive() const { return _excessive; }
596
597 void excessive( bool onOff_r )
598 { _excessive = onOff_r; }
599
600
602 bool hideThreadName() const
603 {
604 if ( indeterminate(_hideThreadName) )
606 return bool(_hideThreadName);
607 }
608
609 void hideThreadName( bool onOff_r )
610 { _hideThreadName = onOff_r; }
611
614 {
615 auto impl = LogControlImpl::instance();
616 return impl ? impl->hideThreadName() : false;
617 }
618
619 static void instanceHideThreadName( bool onOff_r )
620 {
621 auto impl = LogControlImpl::instance();
622 if ( impl ) impl->hideThreadName( onOff_r );
623 }
624
626 static bool instanceLogToPPID( )
627 {
628 auto impl = LogControlImpl::instance();
629 return impl ? impl->_logToPPIDMode : false;
630 }
631
633 static void instanceSetLogToPPID( bool onOff_r )
634 {
635 auto impl = LogControlImpl::instance();
636 if ( impl )
637 impl->_logToPPIDMode = onOff_r;
638 }
639
643
646
649 {
650 if ( format_r )
651 _lineFormater = format_r;
652 else
654 }
655
656 void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
657 {
658 if ( logfile_r.empty() )
660 else if ( logfile_r == Pathname( "-" ) )
662 else
664 }
665
666 private:
668 std::ostream _no_stream;
670 bool _logToPPIDMode = false;
671 mutable TriBool _hideThreadName = indeterminate;
672
674
675 public:
677 std::ostream & getStream( const std::string & group_r,
678 LogLevel level_r,
679 const char * file_r,
680 const char * func_r,
681 const int line_r )
682 {
683 if ( ! getLineWriter() )
684 return _no_stream;
685 if ( level_r == E_XXX && !_excessive )
686 return _no_stream;
687
688 if ( !_streamtable[group_r][level_r] )
689 {
690 _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
691 }
692 std::ostream & ret( _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ) );
693 if ( !ret )
694 {
695 ret.clear();
696 ret << "---<RESET LOGSTREAM FROM FAILED STATE]" << endl;
697 }
698 return ret;
699 }
700
701 void putRawLine ( std::string &&line ) {
702 _logClient.pushMessage( std::move(line) );
703 }
704
706 void putStream( const std::string & group_r,
707 LogLevel level_r,
708 const char * file_r,
709 const char * func_r,
710 int line_r,
711 const std::string & message_r )
712 {
713 _logClient.pushMessage( _lineFormater->format( group_r, level_r,
714 file_r, func_r, line_r,
715 message_r ) );
716 }
717
718 private:
720 using StreamSet = std::map<LogLevel, StreamPtr>;
721 using StreamTable = std::map<std::string, StreamSet>;
725
726 private:
727
728 void readEnvVars () {
729 if ( getenv("ZYPP_LOGFILE") )
730 logfile( getenv("ZYPP_LOGFILE") );
731
732 if ( getenv("ZYPP_PROFILING") )
733 {
735 setLineFormater(formater);
736 }
737 }
738
742 : _no_stream( NULL )
743 , _excessive( getenv("ZYPP_FULLLOG") )
744 , _lineFormater( new LogControl::LineFormater )
745 {
748
749 // make sure the LogControl is invalidated when we fork
750 pthread_atfork( nullptr, nullptr, &LogControl::notifyFork );
751 }
752
753 public:
754
759
761 {
763 }
764
771 static LogControlImpl *instance();
772 };
773
774
775 // 'THE' LogControlImpl singleton
777 {
778 thread_local static LogControlImpl _instance;
779 if ( logControlValidFlag() > 0 )
780 return &_instance;
781 return nullptr;
782 }
783
785
787 inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & )
788 {
789 return str << "LogControlImpl";
790 }
791
793 //
794 // Access from logger::
795 //
797
798 std::ostream & getStream( const char * group_r,
799 LogLevel level_r,
800 const char * file_r,
801 const char * func_r,
802 const int line_r )
803 {
804 static std::ostream nstream(NULL);
805 auto control = LogControlImpl::instance();
806 if ( !control || !group_r || strlen(group_r ) == 0 ) {
807 return nstream;
808 }
809
810
811
812 return control->getStream( group_r,
813 level_r,
814 file_r,
815 func_r,
816 line_r );
817 }
818
820 inline void putStream( const std::string & group_r, LogLevel level_r,
821 const char * file_r, const char * func_r, int line_r,
822 const std::string & buffer_r )
823 {
824 auto control = LogControlImpl::instance();
825 if ( !control )
826 return;
827
828 control->putStream( group_r, level_r,
829 file_r, func_r, line_r,
830 buffer_r );
831 }
832
834 {
835 auto impl = LogControlImpl::instance();
836 if ( !impl )
837 return false;
838 return impl->isExcessive();
839 }
840
842 } // namespace logger
843
844
845 using logger::LogControlImpl;
846
848 // LineFormater
850 std::string LogControl::LineFormater::format( const std::string & group_r,
851 logger::LogLevel level_r,
852 const char * file_r,
853 const char * func_r,
854 int line_r,
855 const std::string & message_r )
856 {
857 static char hostname[1024];
858 static char nohostname[] = "unknown";
859 std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
860 std::string ret;
861
862 const bool logToPPID = LogControlImpl::instanceLogToPPID();
863 if ( !logToPPID && LogControlImpl::instanceHideThreadName() )
864 ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
865 now.c_str(), level_r,
866 ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
867 getpid(),
868 group_r.c_str(),
869 file_r, func_r, line_r,
870 message_r.c_str() );
871 else
872 ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d {T:%s} %s",
873 now.c_str(), level_r,
874 ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
875 logToPPID ? getppid() : getpid(),
876 group_r.c_str(),
877 file_r, func_r, line_r,
879 message_r.c_str() );
880 return ret;
881 }
882
883 std::string LogControl::JournalLineFormater::format( const std::string & group_r,
884 logger::LogLevel level_r,
885 const char * file_r,
886 const char * func_r,
887 int line_r,
888 const std::string & message_r )
889 {
890 std::string ret;
892 ret = str::form( "<%d> [%s] %s(%s):%d %s",
893 level_r, group_r.c_str(),
894 file_r, func_r, line_r,
895 message_r.c_str() );
896 else
897 ret = str::form( "<%d> [%s] %s(%s):%d {T:%s} %s",
898 level_r, group_r.c_str(),
899 file_r, func_r, line_r,
901 message_r.c_str() );
902 return ret;
903 }
904
905 //
906 // CLASS NAME : LogControl
907 // Forward to LogControlImpl singleton.
908 //
910
911
912 void LogControl::logfile( const Pathname & logfile_r )
913 {
914 auto impl = LogControlImpl::instance();
915 if ( !impl )
916 return;
917
918 impl->logfile( logfile_r );
919 }
920
921 void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
922 {
923 auto impl = LogControlImpl::instance();
924 if ( !impl )
925 return;
926
927 impl->logfile( logfile_r, mode_r );
928 }
929
931 {
932 auto impl = LogControlImpl::instance();
933 if ( !impl )
934 return nullptr;
935
936 return impl->getLineWriter();
937 }
938
940 {
941 auto impl = LogControlImpl::instance();
942 if ( !impl )
943 return;
944 impl->setLineWriter( writer_r );
945 }
946
948 {
949 auto impl = LogControlImpl::instance();
950 if ( !impl )
951 return;
952 impl->setLineFormater( formater_r );
953 }
954
959
961 {
962 auto impl = LogControlImpl::instance();
963 if ( !impl )
964 return;
965 impl->setLineWriter( shared_ptr<LineWriter>() );
966 }
967
969 {
970 auto impl = LogControlImpl::instance();
971 if ( !impl )
972 return;
973 impl->setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) );
974 }
975
980
985
986 void LogControl::logRawLine ( std::string &&line )
987 {
988 LogControlImpl::instance ()->putRawLine ( std::move(line) );
989 }
990
992 //
993 // LogControl::TmpExcessive
994 //
997 {
998 auto impl = LogControlImpl::instance();
999 if ( !impl )
1000 return;
1001 impl->excessive( true );
1002 }
1004 {
1005 auto impl = LogControlImpl::instance();
1006 if ( !impl )
1007 return;
1008 impl->excessive( false );
1009 }
1010
1011 /******************************************************************
1012 **
1013 ** FUNCTION NAME : operator<<
1014 ** FUNCTION TYPE : std::ostream &
1015 */
1016 std::ostream & operator<<( std::ostream & str, const LogControl & )
1017 {
1018 auto impl = LogControlImpl::instance();
1019 if ( !impl )
1020 return str;
1021 return str << *impl;
1022 }
1023
1025 } // namespace base
1028} // namespace zypp
std::once_flag flagReadEnvAutomatically
Definition LogControl.cc:54
#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
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)
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:95
static std::string sockPath()
Pathname()
Default ctor: an empty path.
Definition Pathname.h:51
std::string basename() const
Return the last component of this path.
Definition Pathname.h:137
std::atomic_flag _atomicLock
Definition LogControl.cc:81
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
std::shared_ptr< SocketNotifier > makeNotifier(const bool enabled=true) const
Definition wakeup.cpp:39
void notify()
Definition wakeup.cpp:23
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition String.h:31
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
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:60
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