libzypp 17.37.17
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/zyppng/io/Socket>
29#include <zypp-core/zyppng/io/SockAddr>
30#include <zypp-core/zyppng/base/EventLoop>
31#include <zypp-core/zyppng/base/EventDispatcher>
32#include <zypp-core/zyppng/base/Timer>
34#include <zypp-core/zyppng/thread/Wakeup>
36#include <zypp-core/zyppng/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 () {
112 _stopSignal.notify();
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
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
217 };
218
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;
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}
358#endif // ZYPP_NDEBUG
359
361 namespace log
362 {
363
367
371
372 FileLineWriter::FileLineWriter( const Pathname & file_r, mode_t mode_r )
373 {
374 if ( file_r == Pathname("-") )
375 {
376 _str = &std::cerr;
377 }
378 else
379 {
380 if ( mode_r )
381 {
382 // not filesystem::assert_file as filesystem:: functions log,
383 // and this FileWriter is not yet in place.
384 int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r );
385 if ( fd != -1 )
386 ::close( fd );
387 }
388 // set unbuffered write
389 std::ofstream * fstr = 0;
390 _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) );
391 fstr->rdbuf()->pubsetbuf(0,0);
392 _str = &(*fstr);
393 }
394 }
395
397 } // namespace log
398
399
401 namespace base
402 {
404 namespace logger
405 {
406
407 inline void putStream( const std::string & group_r, LogLevel level_r,
408 const char * file_r, const char * func_r, int line_r,
409 const std::string & buffer_r );
410
412 //
413 // CLASS NAME : Loglinebuf
414 //
415 class Loglinebuf : public std::streambuf {
416
417 public:
419 Loglinebuf( std::string group_r, LogLevel level_r )
420 : _group(std::move( group_r ))
421 , _level( level_r )
422 , _file( "" )
423 , _func( "" )
424 , _line( -1 )
425 {}
426
427 Loglinebuf(const Loglinebuf &) = default;
428 Loglinebuf(Loglinebuf &&) = default;
429 Loglinebuf &operator=(const Loglinebuf &) = default;
431
433 ~Loglinebuf() override
434 {
435 if ( !_buffer.empty() )
436 writeout( "\n", 1 );
437 }
438
440 void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
441 {
442 _file = fil_r;
443 _func = fnc_r;
444 _line = lne_r;
445 }
446
447 private:
449 std::streamsize xsputn( const char * s, std::streamsize n ) override
450 { return writeout( s, n ); }
451
452 int overflow( int ch = EOF ) override
453 {
454 if ( ch != EOF )
455 {
456 char tmp = ch;
457 writeout( &tmp, 1 );
458 }
459 return 0;
460 }
461
462 virtual int writeout( const char* s, std::streamsize n )
463 {
464 //logger::putStream( _group, _level, _file, _func, _line, _buffer );
465 //return n;
466 if ( s && n )
467 {
468 const char * c = s;
469 for ( int i = 0; i < n; ++i, ++c )
470 {
471 if ( *c == '\n' ) {
472 _buffer += std::string( s, c-s );
474 _buffer = std::string();
475 s = c+1;
476 }
477 }
478 if ( s < c )
479 {
480 _buffer += std::string( s, c-s );
481 }
482 }
483 return n;
484 }
485
486 private:
487 std::string _group;
489 const char * _file;
490 const char * _func;
491 int _line;
492 std::string _buffer;
493 };
494
496
498 //
499 // CLASS NAME : Loglinestream
500 //
502
503 public:
505 Loglinestream( const std::string & group_r, LogLevel level_r )
506 : _mybuf( group_r, level_r )
507 , _mystream( &_mybuf )
508 {}
509
510 Loglinestream(const Loglinestream &) = delete;
514
517 { _mystream.flush(); }
518
519 public:
521 std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
522 {
523 _mybuf.tagSet( fil_r, fnc_r, lne_r );
524 return _mystream;
525 }
526
527 private:
529 std::ostream _mystream;
530 };
531
532
533 struct LogControlImpl;
534
535 /*
536 * Ugly hack to prevent the use of LogControlImpl when libzypp is shutting down.
537 * Due to the C++ standard, thread_local static instances are cleaned up before the first global static
538 * destructor is called. So all classes that use logging after that point in time would crash the
539 * application because it is accessing a variable that has already been destroyed.
540 */
542 // We are using a POD flag that does not have a destructor,
543 // to flag if the thread_local destructors were already executed.
544 // Since TLS data is stored in a segment that is available until the thread ceases to exist it should still be readable
545 // after thread_local c++ destructors were already executed. Or so I hope.
546 static thread_local int logControlValid = 0;
547 return logControlValid;
548 }
549
551 //
552 // CLASS NAME : LogControlImpl
553 //
564 {
565 public:
566 bool isExcessive() const { return _excessive; }
567
568 void excessive( bool onOff_r )
569 { _excessive = onOff_r; }
570
571
573 bool hideThreadName() const
574 {
575 if ( indeterminate(_hideThreadName) )
577 return bool(_hideThreadName);
578 }
579
580 void hideThreadName( bool onOff_r )
581 { _hideThreadName = onOff_r; }
582
585 {
586 auto impl = LogControlImpl::instance();
587 return impl ? impl->hideThreadName() : false;
588 }
589
590 static void instanceHideThreadName( bool onOff_r )
591 {
592 auto impl = LogControlImpl::instance();
593 if ( impl ) impl->hideThreadName( onOff_r );
594 }
595
597 static bool instanceLogToPPID( )
598 {
599 auto impl = LogControlImpl::instance();
600 return impl ? impl->_logToPPIDMode : false;
601 }
602
604 static void instanceSetLogToPPID( bool onOff_r )
605 {
606 auto impl = LogControlImpl::instance();
607 if ( impl )
608 impl->_logToPPIDMode = onOff_r;
609 }
610
614
617
620 {
621 if ( format_r )
622 _lineFormater = format_r;
623 else
625 }
626
627 void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
628 {
629 if ( logfile_r.empty() )
631 else if ( logfile_r == Pathname( "-" ) )
633 else
635 }
636
637 private:
639 std::ostream _no_stream;
641 bool _logToPPIDMode = false;
642 mutable TriBool _hideThreadName = indeterminate;
643
645
646 public:
648 std::ostream & getStream( const std::string & group_r,
649 LogLevel level_r,
650 const char * file_r,
651 const char * func_r,
652 const int line_r )
653 {
654 if ( ! getLineWriter() )
655 return _no_stream;
656 if ( level_r == E_XXX && !_excessive )
657 return _no_stream;
658
659 if ( !_streamtable[group_r][level_r] )
660 {
661 _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
662 }
663 std::ostream & ret( _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ) );
664 if ( !ret )
665 {
666 ret.clear();
667 ret << "---<RESET LOGSTREAM FROM FAILED STATE]" << endl;
668 }
669 return ret;
670 }
671
672 void putRawLine ( std::string &&line ) {
673 _logClient.pushMessage( std::move(line) );
674 }
675
677 void putStream( const std::string & group_r,
678 LogLevel level_r,
679 const char * file_r,
680 const char * func_r,
681 int line_r,
682 const std::string & message_r )
683 {
684 _logClient.pushMessage( _lineFormater->format( group_r, level_r,
685 file_r, func_r, line_r,
686 message_r ) );
687 }
688
689 private:
691 using StreamSet = std::map<LogLevel, StreamPtr>;
692 using StreamTable = std::map<std::string, StreamSet>;
696
697 private:
698
699 void readEnvVars () {
700 if ( getenv("ZYPP_LOGFILE") )
701 logfile( getenv("ZYPP_LOGFILE") );
702
703 if ( getenv("ZYPP_PROFILING") )
704 {
706 setLineFormater(formater);
707 }
708 }
709
713 : _no_stream( NULL )
714 , _excessive( getenv("ZYPP_FULLLOG") )
715 , _lineFormater( new LogControl::LineFormater )
716 {
719
720 // make sure the LogControl is invalidated when we fork
721 pthread_atfork( nullptr, nullptr, &LogControl::notifyFork );
722 }
723
724 public:
725
730
732 {
734 }
735
742 static LogControlImpl *instance();
743 };
744
745
746 // 'THE' LogControlImpl singleton
748 {
749 thread_local static LogControlImpl _instance;
750 if ( logControlValidFlag() > 0 )
751 return &_instance;
752 return nullptr;
753 }
754
756
758 inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & )
759 {
760 return str << "LogControlImpl";
761 }
762
764 //
765 // Access from logger::
766 //
768
769 std::ostream & getStream( const char * group_r,
770 LogLevel level_r,
771 const char * file_r,
772 const char * func_r,
773 const int line_r )
774 {
775 static std::ostream nstream(NULL);
776 auto control = LogControlImpl::instance();
777 if ( !control || !group_r || strlen(group_r ) == 0 ) {
778 return nstream;
779 }
780
781
782
783 return control->getStream( group_r,
784 level_r,
785 file_r,
786 func_r,
787 line_r );
788 }
789
791 inline void putStream( const std::string & group_r, LogLevel level_r,
792 const char * file_r, const char * func_r, int line_r,
793 const std::string & buffer_r )
794 {
795 auto control = LogControlImpl::instance();
796 if ( !control )
797 return;
798
799 control->putStream( group_r, level_r,
800 file_r, func_r, line_r,
801 buffer_r );
802 }
803
805 {
806 auto impl = LogControlImpl::instance();
807 if ( !impl )
808 return false;
809 return impl->isExcessive();
810 }
811
813 } // namespace logger
814
815
816 using logger::LogControlImpl;
817
819 // LineFormater
821 std::string LogControl::LineFormater::format( const std::string & group_r,
822 logger::LogLevel level_r,
823 const char * file_r,
824 const char * func_r,
825 int line_r,
826 const std::string & message_r )
827 {
828 static char hostname[1024];
829 static char nohostname[] = "unknown";
830 std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
831 std::string ret;
832
833 const bool logToPPID = LogControlImpl::instanceLogToPPID();
834 if ( !logToPPID && LogControlImpl::instanceHideThreadName() )
835 ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
836 now.c_str(), level_r,
837 ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
838 getpid(),
839 group_r.c_str(),
840 file_r, func_r, line_r,
841 message_r.c_str() );
842 else
843 ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d {T:%s} %s",
844 now.c_str(), level_r,
845 ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
846 logToPPID ? getppid() : getpid(),
847 group_r.c_str(),
848 file_r, func_r, line_r,
849 zyppng::ThreadData::current().name().c_str(),
850 message_r.c_str() );
851 return ret;
852 }
853
855 //
856 // CLASS NAME : LogControl
857 // Forward to LogControlImpl singleton.
858 //
860
861
862 void LogControl::logfile( const Pathname & logfile_r )
863 {
864 auto impl = LogControlImpl::instance();
865 if ( !impl )
866 return;
867
868 impl->logfile( logfile_r );
869 }
870
871 void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
872 {
873 auto impl = LogControlImpl::instance();
874 if ( !impl )
875 return;
876
877 impl->logfile( logfile_r, mode_r );
878 }
879
881 {
882 auto impl = LogControlImpl::instance();
883 if ( !impl )
884 return nullptr;
885
886 return impl->getLineWriter();
887 }
888
890 {
891 auto impl = LogControlImpl::instance();
892 if ( !impl )
893 return;
894 impl->setLineWriter( writer_r );
895 }
896
898 {
899 auto impl = LogControlImpl::instance();
900 if ( !impl )
901 return;
902 impl->setLineFormater( formater_r );
903 }
904
909
911 {
912 auto impl = LogControlImpl::instance();
913 if ( !impl )
914 return;
915 impl->setLineWriter( shared_ptr<LineWriter>() );
916 }
917
919 {
920 auto impl = LogControlImpl::instance();
921 if ( !impl )
922 return;
923 impl->setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) );
924 }
925
930
935
936 void LogControl::logRawLine ( std::string &&line )
937 {
938 LogControlImpl::instance ()->putRawLine ( std::move(line) );
939 }
940
942 //
943 // LogControl::TmpExcessive
944 //
947 {
948 auto impl = LogControlImpl::instance();
949 if ( !impl )
950 return;
951 impl->excessive( true );
952 }
954 {
955 auto impl = LogControlImpl::instance();
956 if ( !impl )
957 return;
958 impl->excessive( false );
959 }
960
961 /******************************************************************
962 **
963 ** FUNCTION NAME : operator<<
964 ** FUNCTION TYPE : std::ostream &
965 */
966 std::ostream & operator<<( std::ostream & str, const LogControl & )
967 {
968 auto impl = LogControlImpl::instance();
969 if ( !impl )
970 return str;
971 return str << *impl;
972 }
973
975 } // namespace base
978} // namespace zypp
std::once_flag flagReadEnvAutomatically
Definition LogControl.cc:54
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()
std::string basename() const
Return the last component of this path.
Definition Pathname.h:130
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)
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
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 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: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.
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:254
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