#include "zypp/base/Logger.h"
#include "zypp/base/LogControl.h"
+#include "zypp/base/ProfilingFormater.h"
#include "zypp/base/String.h"
+#include "zypp/Date.h"
+#include "zypp/PathInfo.h"
using std::endl;
///////////////////////////////////////////////////////////////////
namespace zypp
{ /////////////////////////////////////////////////////////////////
+
+#ifndef ZYPP_NDEBUG
+ namespace debug
+ {
+ void osdlog( const std::string & msg_r, unsigned level_r )
+ {
+ // Fg::Black: 30 Bg: 40 Attr::Normal: 22;27
+ // Fg::Red: 31 ... Attr::Bright: 1
+ // Fg::Green: 32 Attr::Reverse: 7
+ // Fg::Yellow: 33
+ // Fg::Blue: 34
+ // Fg::Magenta: 35
+ // Fg::Cyan: 36
+ // Fg::White: 37
+ // Fg::Default: 39
+ static const char * ansi[] = {
+ "\033[37;40m", // 0 w
+ "\033[36;40m", // 1 c
+ "\033[33;1;40m", // 2 y
+ "\033[32;40m", // 3 g
+ "\033[31;1;40m", // 4 r
+ "\033[35;40m", // 5 m
+ };
+ static const unsigned n = sizeof(ansi)/sizeof(const char *);
+ switch ( level_r )
+ {
+ case 'w': level_r = 0; break;
+ case 'c': level_r = 1; break;
+ case 'y': level_r = 2; break;
+ case 'g': level_r = 3; break;
+ case 'r': level_r = 4; break;
+ case 'm': level_r = 5; break;
+ }
+ std::cerr << ansi[level_r%n] << "OSD[" << msg_r << "]\033[0m" << std::endl;
+ }
+}
+#endif // ZYPP_NDEBUG
+
///////////////////////////////////////////////////////////////////
- namespace base
+ namespace log
{ /////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////
- namespace logger
- { /////////////////////////////////////////////////////////////////
- void logFormat( const std::string & group_r, LogLevel level_r,
- const char * file_r, const char * func_r, int line_r,
- const std::string & buffer_r );
+ StdoutLineWriter::StdoutLineWriter()
+ : StreamLineWriter( std::cout )
+ {}
- ///////////////////////////////////////////////////////////////////
- struct StdErrWriter : public LogControl::LineWriter
+ StderrLineWriter::StderrLineWriter()
+ : StreamLineWriter( std::cerr )
+ {}
+
+ FileLineWriter::FileLineWriter( const Pathname & file_r, mode_t mode_r )
+ {
+ if ( file_r == Pathname("-") )
{
- virtual void writeOut( const std::string & formated_r )
- {
- std::cerr << formated_r << endl;
- }
- };
- ///////////////////////////////////////////////////////////////////
- struct FileWriter : public LogControl::LineWriter
+ _str = &std::cerr;
+ }
+ else
{
- FileWriter( const Pathname & logfile_r )
- : _logfile( logfile_r )
- {}
- Pathname _logfile;
+ if ( mode_r )
+ {
+ // not filesystem::assert_file as filesystem:: functions log,
+ // and this FileWriter is not yet in place.
+ int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r );
+ if ( fd != -1 )
+ ::close( fd );
+ }
+ // set unbuffered write
+ std::ofstream * fstr = 0;
+ _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) );
+ fstr->rdbuf()->pubsetbuf(0,0);
+ _str = &(*fstr);
+ }
+ }
- virtual void writeOut( const std::string & formated_r )
- {
- std::ofstream outs( _logfile.asString().c_str(), std::ios_base::app );
- outs << formated_r << endl;
- }
- };
+ /////////////////////////////////////////////////////////////////
+ } // namespace log
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ namespace base
+ { /////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
+ // LineFormater
+ ///////////////////////////////////////////////////////////////////
+ std::string LogControl::LineFormater::format( const std::string & group_r,
+ logger::LogLevel level_r,
+ const char * file_r,
+ const char * func_r,
+ int line_r,
+ const std::string & message_r )
+ {
+ static char hostname[1024];
+ static char nohostname[] = "unknown";
+ std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) );
+ return str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s",
+ now.c_str(), level_r,
+ ( gethostname( hostname, 1024 ) ? nohostname : hostname ),
+ getpid(),
+ group_r.c_str(),
+ file_r, func_r, line_r,
+ message_r.c_str() );
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ namespace logger
+ { /////////////////////////////////////////////////////////////////
+
+ inline 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 );
///////////////////////////////////////////////////////////////////
//
/** */
virtual int writeout( const char* s, std::streamsize n )
{
+ //logger::putStream( _group, _level, _file, _func, _line, _buffer );
+ //return n;
if ( s && n )
{
const char * c = s;
{
if ( *c == '\n' ) {
_buffer += std::string( s, c-s );
- logger::logFormat( _group, _level, _file, _func, _line, _buffer );
+ logger::putStream( _group, _level, _file, _func, _line, _buffer );
_buffer = std::string();
s = c+1;
}
//
// CLASS NAME : LogControlImpl
//
- /** LogControl implementation (Singleton). */
+ /** LogControl implementation (Singleton).
+ *
+ * \note There is a slight difference in using the _lineFormater and _lineWriter!
+ * \li \c _lineFormater must not be NULL (create default LogControl::LineFormater)
+ * \li \c _lineWriter is NULL if no logging is performed, this way we can pass
+ * _no_stream as logstream to the application, and avoid unnecessary formating
+ * of logliles, which would then be discarded when passed to some dummy
+ * LineWriter.
+ */
struct LogControlImpl
{
public:
+ bool isExcessive()
+ { return _excessive; }
+
void excessive( bool onOff_r )
{ _excessive = onOff_r; }
+ /** NULL _lineWriter indicates no loggin. */
void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
{ _lineWriter = writer_r; }
+ shared_ptr<LogControl::LineWriter> getLineWriter() const
+ { return _lineWriter; }
+
+ /** Assert \a _lineFormater is not NULL. */
+ void setLineFormater( const shared_ptr<LogControl::LineFormater> & format_r )
+ {
+ if ( format_r )
+ _lineFormater = format_r;
+ else
+ _lineFormater.reset( new LogControl::LineFormater );
+ }
+
+ void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 )
+ {
+ if ( logfile_r.empty() )
+ setLineWriter( shared_ptr<LogControl::LineWriter>() );
+ else if ( logfile_r == Pathname( "-" ) )
+ setLineWriter( shared_ptr<LogControl::LineWriter>(new log::StderrLineWriter) );
+ else
+ setLineWriter( shared_ptr<LogControl::LineWriter>(new log::FileLineWriter(logfile_r, mode_r)) );
+ }
+
private:
std::ostream _no_stream;
bool _excessive;
- shared_ptr<LogControl::LineWriter> _lineWriter;
+ shared_ptr<LogControl::LineFormater> _lineFormater;
+ shared_ptr<LogControl::LineWriter> _lineWriter;
public:
- /** Provide the stream to write (logger interface) */
+ /** Provide the log stream to write (logger interface) */
std::ostream & getStream( const std::string & group_r,
LogLevel level_r,
const char * file_r,
const char * func_r,
const int line_r )
{
+ if ( ! _lineWriter )
+ return _no_stream;
if ( level_r == E_XXX && !_excessive )
- {
- return _no_stream;
- }
+ return _no_stream;
if ( !_streamtable[group_r][level_r] )
{
return _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r );
}
- /** Write out formated line from Loglinebuf. */
- void writeLine( const std::string & formated_r )
+ /** Format and write out a logline from Loglinebuf. */
+ 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 )
{
if ( _lineWriter )
- _lineWriter->writeOut( formated_r );
+ _lineWriter->writeOut( _lineFormater->format( group_r, level_r,
+ file_r, func_r, line_r,
+ message_r ) );
}
private:
StreamTable _streamtable;
private:
- /** Singleton */
+ /** Singleton ctor.
+ * No logging per default, unless enabled via $ZYPP_LOGFILE.
+ */
LogControlImpl()
- : _no_stream( 0 )
+ : _no_stream( NULL )
, _excessive( getenv("ZYPP_FULLLOG") )
- , _lineWriter( getenv("ZYPP_NOLOG") ? NULL : new StdErrWriter )
- {}
+ , _lineFormater( new LogControl::LineFormater )
+ {
+ if ( getenv("ZYPP_LOGFILE") )
+ logfile( getenv("ZYPP_LOGFILE") );
+
+ if ( getenv("ZYPP_PROFILING") )
+ {
+ shared_ptr<LogControl::LineFormater> formater(new ProfilingFormater);
+ setLineFormater(formater);
+ }
+ }
+
+ ~LogControlImpl()
+ {
+ _lineWriter.reset();
+ }
public:
/** The LogControlImpl singleton
* destructed. At least destucted after all statics
* which log from their dtor.
*/
- static LogControlImpl instance;
+ static LogControlImpl & instance();
};
///////////////////////////////////////////////////////////////////
// 'THE' LogControlImpl singleton
- LogControlImpl LogControlImpl::instance;
+ inline LogControlImpl & LogControlImpl::instance()
+ {
+ static LogControlImpl _instance;
+ return _instance;
+ }
///////////////////////////////////////////////////////////////////
- /** \relates LogControl::Impl Stream output */
+ /** \relates LogControlImpl Stream output */
inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & obj )
{
return str << "LogControlImpl";
//
///////////////////////////////////////////////////////////////////
- /** That's what logger:: calls. */
std::ostream & getStream( const char * group_r,
LogLevel level_r,
const char * file_r,
const char * func_r,
const int line_r )
{
- return LogControlImpl::instance.getStream( group_r,
+ return LogControlImpl::instance().getStream( group_r,
level_r,
file_r,
func_r,
}
/** That's what Loglinebuf calls. */
- inline void logFormat( const std::string & group_r, LogLevel level_r,
+ inline 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 )
{
- LogControlImpl::instance.writeLine( str::form( "<%d> [%s] %s(%s):%d %s",
- level_r, group_r.c_str(),
- file_r, func_r, line_r,
- buffer_r.c_str() ) );
+ LogControlImpl::instance().putStream( group_r, level_r,
+ file_r, func_r, line_r,
+ buffer_r );
}
+ bool isExcessive()
+ { return LogControlImpl::instance().isExcessive(); }
+
/////////////////////////////////////////////////////////////////
} // namespace logger
///////////////////////////////////////////////////////////////////
using logger::LogControlImpl;
void LogControl::logfile( const Pathname & logfile_r )
- { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>( new logger::FileWriter(logfile_r) ) ); }
+ { LogControlImpl::instance().logfile( logfile_r ); }
+
+ void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r )
+ { LogControlImpl::instance().logfile( logfile_r, mode_r ); }
+
+ shared_ptr<LogControl::LineWriter> LogControl::getLineWriter() const
+ { return LogControlImpl::instance().getLineWriter(); }
void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
- { LogControlImpl::instance.setLineWriter( writer_r ); }
+ { LogControlImpl::instance().setLineWriter( writer_r ); }
+
+ void LogControl::setLineFormater( const shared_ptr<LineFormater> & formater_r )
+ { LogControlImpl::instance().setLineFormater( formater_r ); }
void LogControl::logNothing()
- { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>() ); }
+ { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>() ); }
void LogControl::logToStdErr()
- { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>( new logger::StdErrWriter ) ); }
+ { LogControlImpl::instance().setLineWriter( shared_ptr<LineWriter>( new log::StderrLineWriter ) ); }
///////////////////////////////////////////////////////////////////
//
//
///////////////////////////////////////////////////////////////////
LogControl::TmpExcessive::TmpExcessive()
- { LogControlImpl::instance.excessive( true ); }
+ { LogControlImpl::instance().excessive( true ); }
LogControl::TmpExcessive::~TmpExcessive()
- { LogControlImpl::instance.excessive( false ); }
+ { LogControlImpl::instance().excessive( false ); }
/******************************************************************
**
*/
std::ostream & operator<<( std::ostream & str, const LogControl & obj )
{
- return str << LogControlImpl::instance;
+ return str << LogControlImpl::instance();
}
/////////////////////////////////////////////////////////////////