- Updated LogControl. setLineWriter allows to define a consumer
authorMichael Andres <ma@suse.de>
Mon, 13 Feb 2006 15:03:22 +0000 (15:03 +0000)
committerMichael Andres <ma@suse.de>
Mon, 13 Feb 2006 15:03:22 +0000 (15:03 +0000)
  for the formated loglines. That way zypp log can be merged into
  some other log.

zypp/base/LogControl.cc
zypp/base/LogControl.h

index 276d978..8dc5844 100644 (file)
@@ -10,6 +10,8 @@
  *
 */
 #include <iostream>
+#include <fstream>
+#include <string>
 
 #include "zypp/base/Logger.h"
 #include "zypp/base/LogControl.h"
@@ -27,6 +29,141 @@ namespace zypp
     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 );
+
+      ///////////////////////////////////////////////////////////////////
+      struct StdErrWriter : public LogControl::LineWriter
+      {
+        virtual void writeOut( const std::string & formated_r )
+        {
+          std::cerr << formated_r << endl;
+        }
+      };
+      ///////////////////////////////////////////////////////////////////
+      struct FileWriter : public LogControl::LineWriter
+      {
+        FileWriter( const Pathname & logfile_r )
+        : _logfile( logfile_r )
+        {}
+        Pathname _logfile;
+
+        virtual void writeOut( const std::string & formated_r )
+        {
+          std::ofstream outs( _logfile.asString().c_str(), std::ios_base::app );
+          outs << formated_r << endl;
+        }
+      };
+
+      ///////////////////////////////////////////////////////////////////
+      //
+      //       CLASS NAME : Loglinebuf
+      //
+      class Loglinebuf : public std::streambuf {
+
+      public:
+        /** */
+        Loglinebuf( const std::string & group_r, LogLevel level_r )
+        : _group( group_r )
+        , _level( level_r )
+        , _file( "" )
+        , _func( "" )
+        , _line( -1 )
+        {}
+        /** */
+        ~Loglinebuf()
+        {
+          if ( !_buffer.empty() )
+            writeout( "\n", 1 );
+        }
+
+        /** */
+        void tagSet( const char * fil_r, const char * fnc_r, int lne_r )
+        {
+          _file = fil_r;
+          _func = fnc_r;
+          _line = lne_r;
+        }
+
+      private:
+        /** */
+        virtual std::streamsize xsputn( const char * s, std::streamsize n )
+        { return writeout( s, n ); }
+        /** */
+        virtual int overflow( int ch = EOF )
+        {
+          if ( ch != EOF )
+            {
+              char tmp = ch;
+              writeout( &tmp, 1 );
+            }
+          return 0;
+        }
+        /** */
+        virtual int writeout( const char* s, std::streamsize n )
+        {
+          if ( s && n )
+            {
+              const char * c = s;
+              for ( int i = 0; i < n; ++i, ++c )
+                {
+                  if ( *c == '\n' ) {
+                    _buffer += std::string( s, c-s );
+                    logger::logFormat( _group, _level, _file, _func, _line, _buffer );
+                    _buffer = std::string();
+                    s = c+1;
+                  }
+                }
+              if ( s < c )
+                {
+                  _buffer += std::string( s, c-s );
+                }
+            }
+          return n;
+        }
+
+      private:
+        std::string  _group;
+        LogLevel     _level;
+        const char * _file;
+        const char * _func;
+        int          _line;
+        std::string  _buffer;
+      };
+
+      ///////////////////////////////////////////////////////////////////
+
+      ///////////////////////////////////////////////////////////////////
+      //
+      //       CLASS NAME : Loglinestream
+      //
+      class Loglinestream {
+
+      public:
+        /** */
+        Loglinestream( const std::string & group_r, LogLevel level_r )
+        : _mybuf( group_r, level_r )
+        , _mystream( &_mybuf )
+        {}
+        /** */
+        ~Loglinestream()
+        { _mystream.flush(); }
+
+      public:
+        /** */
+        std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r )
+        {
+          _mybuf.tagSet( fil_r, fnc_r, lne_r );
+          return _mystream;
+        }
+
+      private:
+        Loglinebuf   _mybuf;
+        std::ostream _mystream;
+      };
+      ///////////////////////////////////////////////////////////////////
+
       ///////////////////////////////////////////////////////////////////
       //
       //       CLASS NAME : LogControlImpl
@@ -35,47 +172,58 @@ namespace zypp
       struct LogControlImpl
       {
       public:
-        const Pathname & logfile() const
-        { return _logfile; }
-
-        /** \todo IMPEMENT it */
-        void logfile( const Pathname & logfile_r )
-        {}
-
         void excessive( bool onOff_r )
         { _excessive = onOff_r; }
 
-      public:
-        /** Provide the stream to write (logger interface) */
-        std::ostream & getStream( const char * group_r,
-                                  LogLevel     level_r,
-                                  const char * file_r,
-                                  const char * func_r,
-                                  const int    line_r );
-      private:
-        /** Current output stream. */
-        std::ostream & outStr()
-        { return *_outStrPtr; }
-
-        /** Output stream for level XXX */
-        std::ostream & fullStr()
-        { return _excessive ? outStr() : _no_stream; }
+        void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r )
+        { _lineWriter = writer_r; }
 
       private:
         std::ostream _no_stream;
+        bool         _excessive;
 
-        /** must pont to the current outpot stream or _no_stream! */
-        std::ostream *_outStrPtr;
+        shared_ptr<LogControl::LineWriter> _lineWriter;
 
-        Pathname     _logfile;
-        bool         _excessive;
+      public:
+        /** Provide the 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 ( level_r == E_XXX && !_excessive )
+            {
+              return _no_stream;
+            }
+
+          if ( !_streamtable[group_r][level_r] )
+            {
+              _streamtable[group_r][level_r].reset( new Loglinestream( 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 )
+        {
+          if ( _lineWriter )
+            _lineWriter->writeOut( formated_r );
+        }
+
+      private:
+        typedef shared_ptr<Loglinestream>        StreamPtr;
+        typedef std::map<LogLevel,StreamPtr>     StreamSet;
+        typedef std::map<std::string,StreamSet>  StreamTable;
+        /** one streambuffer per group and level */
+        StreamTable _streamtable;
 
       private:
         /** Singleton */
         LogControlImpl()
         : _no_stream( 0 )
-        , _outStrPtr( getenv("ZYPP_NOLOG") ? &_no_stream : &std::cerr )
         , _excessive( getenv("ZYPP_FULLLOG") )
+        , _lineWriter( getenv("ZYPP_NOLOG") ? NULL : new StdErrWriter )
         {}
 
       public:
@@ -120,22 +268,15 @@ namespace zypp
                                                    line_r );
       }
 
-      ///////////////////////////////////////////////////////////////////
-      //
-      // CLASS NAME : LogControlImpl
-      //
-      ///////////////////////////////////////////////////////////////////
-
-      std::ostream & LogControlImpl::getStream( const char * group_r,
-                                                LogLevel     level_r,
-                                                const char * file_r,
-                                                const char * func_r,
-                                                const int    line_r )
+      /** That's what Loglinebuf calls.  */
+      inline 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 )
       {
-        return (level_r != E_XXX ? outStr() : fullStr() )
-        << str::form( "<%d> [%s] %s(%s):%d ",
-                      level_r, group_r,
-                      file_r, func_r, line_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() ) );
       }
 
       /////////////////////////////////////////////////////////////////
@@ -151,11 +292,17 @@ namespace zypp
 
     using logger::LogControlImpl;
 
-    const Pathname & LogControl::logfile() const
-    { return LogControlImpl::instance.logfile(); }
-
     void LogControl::logfile( const Pathname & logfile_r )
-    { LogControlImpl::instance.logfile( logfile_r ); }
+    { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>( new logger::FileWriter(logfile_r) ) ); }
+
+    void LogControl::setLineWriter( const shared_ptr<LineWriter> & writer_r )
+    { LogControlImpl::instance.setLineWriter( writer_r ); }
+
+    void LogControl::logNothing()
+    { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>() ); }
+
+    void LogControl::logToStdErr()
+    { LogControlImpl::instance.setLineWriter( shared_ptr<LineWriter>( new logger::StdErrWriter ) ); }
 
     ///////////////////////////////////////////////////////////////////
     //
index 8b302fa..09d0518 100644 (file)
@@ -41,18 +41,32 @@ namespace zypp
       static LogControl instance()
       { return LogControl(); }
 
-    public:
-      /** Return path to the logfile.
-       * An emty pathname for std::err.
-      */
-      const Pathname & logfile() const;
 
+      /** If you want to log the (formated) loglines by yourself,
+       * derive from this, and overload \c writeOut. */
+      struct LineWriter
+      {
+        virtual void writeOut( const std::string & /*formated_r*/ )
+        {}
+
+        virtual ~LineWriter() {}
+      };
+
+    public:
       /** Set path for the logfile.
        * An emty pathname for std::err.
        * \throw if \a logfile_r is not usable.
       */
       void logfile( const Pathname & logfile_r );
 
+      void logNothing();
+
+      void logToStdErr();
+
+      /** Assign a LineWriter.
+       * If you want to log the (formated) loglines by yourself. */
+      void setLineWriter( const shared_ptr<LogControl::LineWriter> & writer_r );
+
     public:
       /** Turn on excessive logging for the lifetime of this object.*/
       struct TmpExcessive