libzypp 17.25.7
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
16#include <zypp/base/Logger.h>
19#include <zypp/base/String.h>
20#include <zypp/Date.h>
21#include <zypp/PathInfo.h>
22
23using std::endl;
24
26namespace zypp
27{
28
29#ifndef ZYPP_NDEBUG
30 namespace debug
31 {
32 void osdlog( const std::string & msg_r, unsigned level_r )
33 {
34 // Fg::Black: 30 Bg: 40 Attr::Normal: 22;27
35 // Fg::Red: 31 ... Attr::Bright: 1
36 // Fg::Green: 32 Attr::Reverse: 7
37 // Fg::Yellow: 33
38 // Fg::Blue: 34
39 // Fg::Magenta: 35
40 // Fg::Cyan: 36
41 // Fg::White: 37
42 // Fg::Default: 39
43 static const char * ansi[] = {
44 "\033[37;40m", // 0 w
45 "\033[36;40m", // 1 c
46 "\033[33;1;40m", // 2 y
47 "\033[32;40m", // 3 g
48 "\033[31;1;40m", // 4 r
49 "\033[35;40m", // 5 m
50 };
51 static const unsigned n = sizeof(ansi)/sizeof(const char *);
52 switch ( level_r )
53 {
54 case 'w': level_r = 0; break;
55 case 'c': level_r = 1; break;
56 case 'y': level_r = 2; break;
57 case 'g': level_r = 3; break;
58 case 'r': level_r = 4; break;
59 case 'm': level_r = 5; break;
60 }
61 std::cerr << ansi[level_r%n] << "OSD[" << msg_r << "]\033[0m" << std::endl;
62 }
63
64
65 unsigned TraceLeave::_depth = 0;
66
67 TraceLeave::TraceLeave( const char * file_r, const char * fnc_r, int line_r )
68 : _file( std::move(file_r) )
69 , _fnc( std::move(fnc_r) )
70 , _line( line_r )
71 {
72 //std::string::size_type p( _file.find_last_of( '/' ) );
73 //if ( p != std::string::npos )
74 //_file.erase( 0, p+1 );
75 USR << ">>> " << std::string(_depth++,'>') << " " << _file << "(" << _fnc << "):" << _line << endl;
76 }
77
79 { USR << "<<< " << std::string(--_depth,'<') << " " << _file << "(" << _fnc << "):" << _line << endl; }
80}
81#endif // ZYPP_NDEBUG
82
84 namespace log
85 {
86
88 : StreamLineWriter( std::cout )
89 {}
90
92 : StreamLineWriter( std::cerr )
93 {}
94
95 FileLineWriter::FileLineWriter( const Pathname & file_r, mode_t mode_r )
96 {
97 if ( file_r == Pathname("-") )
98 {
99 _str = &std::cerr;
100 }
101 else
102 {
103 if ( mode_r )
104 {
105 // not filesystem::assert_file as filesystem:: functions log,
106 // and this FileWriter is not yet in place.
107 int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r );
108 if ( fd != -1 )
109 ::close( fd );
110 }
111 // set unbuffered write
112 std::ofstream * fstr = 0;
113 _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) );
114 fstr->rdbuf()->pubsetbuf(0,0);
115 _str = &(*fstr);
116 }
117 }
118
120 } // namespace log
122
124 namespace base
125 {
126
128 // LineFormater
130 std::string LogControl::LineFormater::format( const std::string & group_r,
131 logger::LogLevel level_r,
132 const char * file_r,
133 const char * func_r,
134 int line_r,
135 const std::string & message_r )
136 {
137 static char hostname[1024];
138 static char nohostname[] = "unknown";
139 std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
140 return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
141 now.c_str(), level_r,
142 ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
143 getpid(),
144 group_r.c_str(),
145 file_r, func_r, line_r,
146 message_r.c_str() );
147 }
148
150 namespace logger
151 {
152
153 inline void putStream( const std::string & group_r, LogLevel level_r,
154 const char * file_r, const char * func_r, int line_r,
155 const std::string & buffer_r );
156
158 //
159 // CLASS NAME : Loglinebuf
160 //
161 class Loglinebuf : public std::streambuf {
162
163 public:
165 Loglinebuf( const std::string & group_r, LogLevel level_r )
166 : _group( group_r )
167 , _level( level_r )
168 , _file( "" )
169 , _func( "" )
170 , _line( -1 )
171 {}
174 {
175 if ( !_buffer.empty() )
176 writeout( "\n", 1 );
177 }
178
180 void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
181 {
182 _file = fil_r;
183 _func = fnc_r;
184 _line = lne_r;
185 }
186
187 private:
189 virtual std::streamsize xsputn( const char * s, std::streamsize n )
190 { return writeout( s, n ); }
192 virtual int overflow( int ch = EOF )
193 {
194 if ( ch != EOF )
195 {
196 char tmp = ch;
197 writeout( &tmp, 1 );
198 }
199 return 0;
200 }
202 virtual int writeout( const char* s, std::streamsize n )
203 {
204 //logger::putStream( _group, _level, _file, _func, _line, _buffer );
205 //return n;
206 if ( s && n )
207 {
208 const char * c = s;
209 for ( int i = 0; i < n; ++i, ++c )
210 {
211 if ( *c == '\n' ) {
212 _buffer += std::string( s, c-s );
213 logger::putStream( _group, _level, _file, _func, _line, _buffer );
214 _buffer = std::string();
215 s = c+1;
216 }
217 }
218 if ( s < c )
219 {
220 _buffer += std::string( s, c-s );
221 }
222 }
223 return n;
224 }
225
226 private:
227 std::string _group;
229 const char * _file;
230 const char * _func;
231 int _line;
232 std::string _buffer;
233 };
234
236
238 //
239 // CLASS NAME : Loglinestream
240 //
242
243 public:
245 Loglinestream( const std::string & group_r, LogLevel level_r )
246 : _mybuf( group_r, level_r )
247 , _mystream( &_mybuf )
248 {}
251 { _mystream.flush(); }
252
253 public:
255 std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
256 {
257 _mybuf.tagSet( fil_r, fnc_r, lne_r );
258 return _mystream;
259 }
260
261 private:
263 std::ostream _mystream;
264 };
266
268 //
269 // CLASS NAME : LogControlImpl
270 //
281 {
282 public:
284 { return _excessive; }
285
286 void excessive( bool onOff_r )
287 { _excessive = onOff_r; }
288
290 void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
291 { _lineWriter = writer_r; }
292
293 shared_ptr<LogControl::LineWriter> getLineWriter() const
294 { return _lineWriter; }
295
297 void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
298 {
299 if ( format_r )
300 _lineFormater = format_r;
301 else
302 _lineFormater.reset( new LogControl::LineFormater );
303 }
304
305 void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
306 {
307 if ( logfile_r.empty() )
308 setLineWriter( shared_ptr<LogControl::LineWriter>() );
309 else if ( logfile_r == Pathname( "-" ) )
310 setLineWriter( shared_ptr<LogControl::LineWriter>(new log::StderrLineWriter) );
311 else
312 setLineWriter( shared_ptr<LogControl::LineWriter>(new log::FileLineWriter(logfile_r, mode_r)) );
313 }
314
315 private:
316 std::ostream _no_stream;
318
319 shared_ptr<LogControl::LineFormater> _lineFormater;
320 shared_ptr<LogControl::LineWriter> _lineWriter;
321
322 public:
324 std::ostream & getStream( const std::string & group_r,
325 LogLevel level_r,
326 const char * file_r,
327 const char * func_r,
328 const int line_r )
329 {
330 if ( ! _lineWriter )
331 return _no_stream;
332 if ( level_r == E_XXX && !_excessive )
333 return _no_stream;
334
335 if ( !_streamtable[group_r][level_r] )
336 {
337 _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) );
338 }
339 std::ostream & ret( _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ) );
340 if ( !ret )
341 {
342 ret.clear();
343 ret << "---<RESET LOGSTREAM FROM FAILED STATE]" << endl;
344 }
345 return ret;
346 }
347
349 void putStream( const std::string & group_r,
350 LogLevel level_r,
351 const char * file_r,
352 const char * func_r,
353 int line_r,
354 const std::string & message_r )
355 {
356 if ( _lineWriter )
357 _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
358 file_r, func_r, line_r,
359 message_r ) );
360 }
361
362 private:
363 typedef shared_ptr<Loglinestream> StreamPtr;
364 typedef std::map<LogLevel,StreamPtr> StreamSet;
365 typedef std::map<std::string,StreamSet> StreamTable;
368
369 private:
374 : _no_stream( NULL )
375 , _excessive( getenv("ZYPP_FULLLOG") )
376 , _lineFormater( new LogControl::LineFormater )
377 {
378 if ( getenv("ZYPP_LOGFILE") )
379 logfile( getenv("ZYPP_LOGFILE") );
380
381 if ( getenv("ZYPP_PROFILING") )
382 {
383 shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater);
384 setLineFormater(formater);
385 }
386 }
387
389 {
390 _lineWriter.reset();
391 }
392
393 public:
400 static LogControlImpl & instance();
401 };
403
404 // 'THE' LogControlImpl singleton
406 {
407 static LogControlImpl _instance;
408 return _instance;
409 }
410
412
414 inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
415 {
416 return str << "LogControlImpl";
417 }
418
420 //
421 // Access from logger::
422 //
424
425 std::ostream & getStream( const char * group_r,
426 LogLevel level_r,
427 const char * file_r,
428 const char * func_r,
429 const int line_r )
430 {
431 return LogControlImpl::instance().getStream( group_r,
432 level_r,
433 file_r,
434 func_r,
435 line_r );
436 }
437
439 inline void putStream( const std::string & group_r, LogLevel level_r,
440 const char * file_r, const char * func_r, int line_r,
441 const std::string & buffer_r )
442 {
443 LogControlImpl::instance().putStream( group_r, level_r,
444 file_r, func_r, line_r,
445 buffer_r );
446 }
447
450
452 } // namespace logger
454
456 //
457 // CLASS NAME : LogControl
458 // Forward to LogControlImpl singleton.
459 //
461
462 using logger::LogControlImpl;
463
464 void LogControl::logfile( const Pathname & logfile_r )
465 { LogControlImpl::instance().logfile( logfile_r ); }
466
467 void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
468 { LogControlImpl::instance().logfile( logfile_r, mode_r ); }
469
470 shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const
472
473 void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
474 { LogControlImpl::instance().setLineWriter( writer_r ); }
475
476 void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r )
477 { LogControlImpl::instance().setLineFormater( formater_r ); }
478
480 { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>() ); }
481
483 { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) ); }
484
486 //
487 // LogControl::TmpExcessive
488 //
493 { LogControlImpl::instance().excessive( false ); }
494
495 /******************************************************************
496 **
497 ** FUNCTION NAME : operator<<
498 ** FUNCTION TYPE : std::ostream &
499 */
500 std::ostream & operator<<( std::ostream & str, const LogControl & obj )
501 {
502 return str << LogControlImpl::instance();
503 }
504
506 } // namespace base
509} // namespace zypp
#define USR
Definition: Logger.h:84
const std::string & _buffer
Definition: PluginScript.cc:62
static Date now()
Return the current time.
Definition: Date.h:78
Maintain logfile related options.
Definition: LogControl.h:97
friend std::ostream & operator<<(std::ostream &str, const LogControl &obj)
Definition: LogControl.cc:500
shared_ptr< LineWriter > getLineWriter() const
Get the current LineWriter.
Definition: LogControl.cc:470
void setLineWriter(const shared_ptr< LineWriter > &writer_r)
Assign a LineWriter.
Definition: LogControl.cc:473
void logToStdErr()
Log to std::err.
Definition: LogControl.cc:482
void logNothing()
Turn off logging.
Definition: LogControl.cc:479
void setLineFormater(const shared_ptr< LineFormater > &formater_r)
Assign a LineFormater.
Definition: LogControl.cc:476
static LogControl instance()
Singleton access.
Definition: LogControl.h:102
void logfile(const Pathname &logfile_r)
Set path for the logfile.
Definition: LogControl.cc:464
virtual int overflow(int ch=EOF)
Definition: LogControl.cc:192
virtual std::streamsize xsputn(const char *s, std::streamsize n)
Definition: LogControl.cc:189
Loglinebuf(const std::string &group_r, LogLevel level_r)
Definition: LogControl.cc:165
void tagSet(const char *fil_r, const char *fnc_r, int lne_r)
Definition: LogControl.cc:180
virtual int writeout(const char *s, std::streamsize n)
Definition: LogControl.cc:202
Loglinestream(const std::string &group_r, LogLevel level_r)
Definition: LogControl.cc:245
std::ostream & getStream(const char *fil_r, const char *fnc_r, int lne_r)
Definition: LogControl.cc:255
const char * c_str() const
String representation.
Definition: Pathname.h:110
const std::string & asString() const
String representation.
Definition: Pathname.h:91
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
Definition: Arch.h:348
String related utilities and Regular expression matching.
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.
Definition: LogControl.cc:439
LogLevel
Definition of log levels.
Definition: Logger.h:118
@ E_XXX
Excessive logging.
Definition: Logger.h:119
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.
Definition: LogControl.cc:425
void osdlog(const std::string &msg_r, unsigned level_r)
Definition: LogControl.cc:32
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
Pathname _file
Definition: SystemCheck.cc:34
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 &)
Definition: LogControl.cc:130
LogControl implementation (Singleton).
Definition: LogControl.cc:281
std::ostream & operator<<(std::ostream &str, const LogControlImpl &obj)
Stream output.
Definition: LogControl.cc:414
void setLineWriter(const shared_ptr< LogControl::LineWriter > &writer_r)
NULL _lineWriter indicates no loggin.
Definition: LogControl.cc:290
StreamTable _streamtable
one streambuffer per group and level
Definition: LogControl.cc:367
std::map< LogLevel, StreamPtr > StreamSet
Definition: LogControl.cc:364
static LogControlImpl & instance()
The LogControlImpl singleton.
Definition: LogControl.cc:405
std::map< std::string, StreamSet > StreamTable
Definition: LogControl.cc:365
shared_ptr< Loglinestream > StreamPtr
Definition: LogControl.cc:363
void setLineFormater(const shared_ptr< LogControl::LineFormater > &format_r)
Assert _lineFormater is not NULL.
Definition: LogControl.cc:297
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)
Definition: LogControl.cc:324
void logfile(const Pathname &logfile_r, mode_t mode_r=0640)
Definition: LogControl.cc:305
shared_ptr< LogControl::LineWriter > getLineWriter() const
Definition: LogControl.cc:293
shared_ptr< LogControl::LineWriter > _lineWriter
Definition: LogControl.cc:320
shared_ptr< LogControl::LineFormater > _lineFormater
Definition: LogControl.cc:319
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.
Definition: LogControl.cc:349
TraceLeave(const TraceLeave &)=delete
static unsigned _depth
Definition: Logger.h:37
const char * _fnc
Definition: Logger.h:39
const char * _file
Definition: Logger.h:38
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)
Definition: LogControl.cc:95
LineWriter to stderr.
Definition: LogControl.h:64
Base class for ostream based LineWriter.
Definition: LogControl.h:45