libzypp 17.35.9
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 () {
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
141 zyppng::ThreadData::current().setName("Zypp-Log");
142
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
223 LogThread::instance();
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
245 zyppng::UnixSockAddr addr( LogThread::sockPath(), true );
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 = 1;
316
317 std::string tracestr( char tag_r, unsigned depth_r, const char * file_r, const char * fnc_r, int line_r )
318 {
319 static str::Format fmt { "*** %s %s(%s):%d" };
320 fmt % std::string(depth_r,tag_r) % file_r % fnc_r % line_r;
321 return fmt;
322 }
323
324 TraceLeave::TraceLeave( const char * file_r, const char * fnc_r, int line_r )
325 : _file( std::move(file_r) )
326 , _fnc( std::move(fnc_r) )
327 , _line( line_r )
328 {
329 const std::string & m { tracestr( '>',_depth++, _file,_fnc,_line ) };
330 USR << m << endl;
331 Osd(L_USR("TRACE"),1) << m << endl;
332 }
333
335 {
336 const std::string & m { tracestr( '<',--_depth, _file,_fnc,_line ) };
337 USR << m << endl;
338 Osd(L_USR("TRACE"),1) << m << endl;
339 }
340
341 Osd::Osd( std::ostream & str, int i )
342 : _strout { std::cerr }
343 , _strlog { str }
344 { _strout << (i?WH:YE); }
345
347 { _strout << OO; }
348
349 Osd & Osd::operator<<( std::ostream& (*iomanip)( std::ostream& ) )
350 {
351 _strout << iomanip;
352 _strlog << iomanip;
353 return *this;
354 }
355}
356#endif // ZYPP_NDEBUG
357
359 namespace log
360 {
361
365
369
371 {
372 if ( file_r == Pathname("-") )
373 {
374 _str = &std::cerr;
375 }
376 else
377 {
378 if ( mode_r )
379 {
380 // not filesystem::assert_file as filesystem:: functions log,
381 // and this FileWriter is not yet in place.
382 int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r );
383 if ( fd != -1 )
384 ::close( fd );
385 }
386 // set unbuffered write
387 std::ofstream * fstr = 0;
388 _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) );
389 fstr->rdbuf()->pubsetbuf(0,0);
390 _str = &(*fstr);
391 }
392 }
393
395 } // namespace log
397
399 namespace base
400 {
402 namespace logger
403 {
404
405 inline void putStream( const std::string & group_r, LogLevel level_r,
406 const char * file_r, const char * func_r, int line_r,
407 const std::string & buffer_r );
408
410 //
411 // CLASS NAME : Loglinebuf
412 //
413 class Loglinebuf : public std::streambuf {
414
415 public:
418 : _group(std::move( group_r ))
419 , _level( level_r )
420 , _file( "" )
421 , _func( "" )
422 , _line( -1 )
423 {}
424
425 Loglinebuf(const Loglinebuf &) = default;
426 Loglinebuf(Loglinebuf &&) = default;
427 Loglinebuf &operator=(const Loglinebuf &) = default;
429
431 ~Loglinebuf() override
432 {
433 if ( !_buffer.empty() )
434 writeout( "\n", 1 );
435 }
436
438 void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
439 {
440 _file = fil_r;
441 _func = fnc_r;
442 _line = lne_r;
443 }
444
445 private:
447 std::streamsize xsputn( const char * s, std::streamsize n ) override
448 { return writeout( s, n ); }
450 int overflow( int ch = EOF ) override
451 {
452 if ( ch != EOF )
453 {
454 char tmp = ch;
455 writeout( &tmp, 1 );
456 }
457 return 0;
458 }
460 virtual int writeout( const char* s, std::streamsize n )
461 {
462 //logger::putStream( _group, _level, _file, _func, _line, _buffer );
463 //return n;
464 if ( s && n )
465 {
466 const char * c = s;
467 for ( int i = 0; i < n; ++i, ++c )
468 {
469 if ( *c == '\n' ) {
470 _buffer += std::string( s, c-s );
472 _buffer = std::string();
473 s = c+1;
474 }
475 }
476 if ( s < c )
477 {
478 _buffer += std::string( s, c-s );
479 }
480 }
481 return n;
482 }
483
484 private:
485 std::string _group;
487 const char * _file;
488 const char * _func;
489 int _line;
490 std::string _buffer;
491 };
492
494
496 //
497 // CLASS NAME : Loglinestream
498 //
500
501 public:
503 Loglinestream( const std::string & group_r, LogLevel level_r )
505 , _mystream( &_mybuf )
506 {}
507
508 Loglinestream(const Loglinestream &) = delete;
512
515 { _mystream.flush(); }
516
517 public:
519 std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
520 {
522 return _mystream;
523 }
524
525 private:
527 std::ostream _mystream;
528 };
530
531 struct LogControlImpl;
532
533 /*
534 * Ugly hack to prevent the use of LogControlImpl when libzypp is shutting down.
535 * Due to the C++ standard, thread_local static instances are cleaned up before the first global static
536 * destructor is called. So all classes that use logging after that point in time would crash the
537 * application because it is accessing a variable that has already been destroyed.
538 */
540 // We are using a POD flag that does not have a destructor,
541 // to flag if the thread_local destructors were already executed.
542 // Since TLS data is stored in a segment that is available until the thread ceases to exist it should still be readable
543 // after thread_local c++ destructors were already executed. Or so I hope.
544 static thread_local int logControlValid = 0;
545 return logControlValid;
546 }
547
549 //
550 // CLASS NAME : LogControlImpl
551 //
562 {
563 public:
564 bool isExcessive() const { return _excessive; }
565
566 void excessive( bool onOff_r )
567 { _excessive = onOff_r; }
568
569
571 bool hideThreadName() const
572 {
573 if ( indeterminate(_hideThreadName) )
575 return bool(_hideThreadName);
576 }
580
583 {
585 return impl ? impl->hideThreadName() : false;
586 }
588 static void instanceHideThreadName( bool onOff_r )
589 {
591 if ( impl ) impl->hideThreadName( onOff_r );
592 }
593
595 static bool instanceLogToPPID( )
596 {
598 return impl ? impl->_logToPPIDMode : false;
599 }
600
602 static void instanceSetLogToPPID( bool onOff_r )
603 {
605 if ( impl )
606 impl->_logToPPIDMode = onOff_r;
607 }
608
612
615
624
634
635 private:
637 std::ostream _no_stream;
639 bool _logToPPIDMode = false;
640 mutable TriBool _hideThreadName = indeterminate;
641
643
644 public:
646 std::ostream & getStream( const std::string & group_r,
648 const char * file_r,
649 const char * func_r,
650 const int line_r )
651 {
652 if ( ! getLineWriter() )
653 return _no_stream;
654 if ( level_r == E_XXX && !_excessive )
655 return _no_stream;
656
658 {
660 }
661 std::ostream & ret( _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ) );
662 if ( !ret )
663 {
664 ret.clear();
665 ret << "---<RESET LOGSTREAM FROM FAILED STATE]" << endl;
666 }
667 return ret;
668 }
669
670 void putRawLine ( std::string &&line ) {
671 _logClient.pushMessage( std::move(line) );
672 }
673
675 void putStream( const std::string & group_r,
677 const char * file_r,
678 const char * func_r,
679 int line_r,
680 const std::string & message_r )
681 {
684 message_r ) );
685 }
686
687 private:
689 using StreamSet = std::map<LogLevel, StreamPtr>;
690 using StreamTable = std::map<std::string, StreamSet>;
694
695 private:
696
697 void readEnvVars () {
698 if ( getenv("ZYPP_LOGFILE") )
699 logfile( getenv("ZYPP_LOGFILE") );
700
701 if ( getenv("ZYPP_PROFILING") )
702 {
705 }
706 }
711 : _no_stream( NULL )
712 , _excessive( getenv("ZYPP_FULLLOG") )
713 , _lineFormater( new LogControl::LineFormater )
714 {
717
718 // make sure the LogControl is invalidated when we fork
719 pthread_atfork( nullptr, nullptr, &LogControl::notifyFork );
720 }
721
722 public:
723
728
730 {
732 }
733
740 static LogControlImpl *instance();
741 };
743
744 // 'THE' LogControlImpl singleton
746 {
747 thread_local static LogControlImpl _instance;
748 if ( logControlValidFlag() > 0 )
749 return &_instance;
750 return nullptr;
751 }
752
754
756 inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & )
757 {
758 return str << "LogControlImpl";
759 }
760
762 //
763 // Access from logger::
764 //
766
767 std::ostream & getStream( const char * group_r,
769 const char * file_r,
770 const char * func_r,
771 const int line_r )
772 {
773 static std::ostream nstream(NULL);
775 if ( !control || !group_r || strlen(group_r ) == 0 ) {
776 return nstream;
777 }
778
779
780
781 return control->getStream( group_r,
782 level_r,
783 file_r,
784 func_r,
785 line_r );
786 }
787
789 inline void putStream( const std::string & group_r, LogLevel level_r,
790 const char * file_r, const char * func_r, int line_r,
791 const std::string & buffer_r )
792 {
794 if ( !control )
795 return;
796
797 control->putStream( group_r, level_r,
799 buffer_r );
800 }
801
803 {
805 if ( !impl )
806 return false;
807 return impl->isExcessive();
808 }
809
811 } // namespace logger
813
814 using logger::LogControlImpl;
815
817 // LineFormater
819 std::string LogControl::LineFormater::format( const std::string & group_r,
821 const char * file_r,
822 const char * func_r,
823 int line_r,
824 const std::string & message_r )
825 {
826 static char hostname[1024];
827 static char nohostname[] = "unknown";
828 std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
829 std::string ret;
830
833 ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
834 now.c_str(), level_r,
835 ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
836 getpid(),
837 group_r.c_str(),
839 message_r.c_str() );
840 else
841 ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d {T:%s} %s",
842 now.c_str(), level_r,
843 ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
844 logToPPID ? getppid() : getpid(),
845 group_r.c_str(),
847 zyppng::ThreadData::current().name().c_str(),
848 message_r.c_str() );
849 return ret;
850 }
851
853 //
854 // CLASS NAME : LogControl
855 // Forward to LogControlImpl singleton.
856 //
858
859
861 {
863 if ( !impl )
864 return;
865
866 impl->logfile( logfile_r );
867 }
868
870 {
872 if ( !impl )
873 return;
874
875 impl->logfile( logfile_r, mode_r );
876 }
877
879 {
881 if ( !impl )
882 return nullptr;
883
884 return impl->getLineWriter();
885 }
886
888 {
890 if ( !impl )
891 return;
892 impl->setLineWriter( writer_r );
893 }
894
896 {
898 if ( !impl )
899 return;
900 impl->setLineFormater( formater_r );
901 }
902
907
909 {
911 if ( !impl )
912 return;
913 impl->setLineWriter( shared_ptr<LineWriter>() );
914 }
915
917 {
919 if ( !impl )
920 return;
921 impl->setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) );
922 }
923
928
933
934 void LogControl::logRawLine ( std::string &&line )
935 {
936 LogControlImpl::instance ()->putRawLine ( std::move(line) );
937 }
938
940 //
941 // LogControl::TmpExcessive
942 //
945 {
947 if ( !impl )
948 return;
949 impl->excessive( true );
950 }
952 {
954 if ( !impl )
955 return;
956 impl->excessive( false );
957 }
958
959 /******************************************************************
960 **
961 ** FUNCTION NAME : operator<<
962 ** FUNCTION TYPE : std::ostream &
963 */
964 std::ostream & operator<<( std::ostream & str, const LogControl & )
965 {
967 if ( !impl )
968 return str;
969 return str << *impl;
970 }
971
973 } // namespace base
976} // 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
void reset()
Reset to default Ctor values.
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::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)
shared_ptr< LineWriter > getLineWriter() const
Get the current LineWriter.
void setLineWriter(const shared_ptr< LineWriter > &writer_r)
Assign a LineWriter.
void emergencyShutdown()
will cause the log thread to exit and flush all sockets
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.
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
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::shared_ptr< SocketNotifier > makeNotifier(const bool enabled=true) const
Definition wakeup.cpp:39
void notify()
Definition wakeup.cpp:23
zypp::Pathname _file
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:154
@ E_XXX
Excessive logging.
Definition Logger.h:155
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
std::string tracestr(char tag_r, unsigned depth_r, const char *file_r, const char *fnc_r, int line_r)
static constexpr std::string_view OO
static constexpr std::string_view YE
static constexpr std::string_view CY
static constexpr std::string_view GR
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)
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.
std::ostream & _strlog
Definition Logger.h:61
Osd(std::ostream &, int=0)
std::ostream & _strout
Definition Logger.h:60
Osd & operator<<(Tp &&val)
Definition Logger.h:50
static unsigned _depth
Definition Logger.h:36
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
Base class for ostream based LineWriter.
Definition LogControl.h:45
Convenient building of std::string with boost::format.
Definition String.h:253
static ZYPP_API ThreadData & current()
Definition threaddata.cc:16
#define USR
Definition Logger.h:103
#define L_USR(GROUP)
Definition Logger.h:112