Логгинг
От: Константин Ленин Франция  
Дата: 29.03.06 16:06
Оценка:
Решил тут логгинг переделать.Старый был неудобен и основывался на макросах.

Кое-что получилось . Хочу послушать мнения по поводу пригодности.


#pragma once
#include <Windows.h>
#include <atlstr.h>
#include <iosfwd>
#include <string>
#include <memory>

namespace Logging
{
    enum LogLevel
    {
        LogAll = 0,
        LogInfo,
        LogWarning,
        LogError,
        LogNo
    };

    std::ostream& operator<<( std::ostream& stream, LogLevel level )
    {
        LPCTSTR lpszPrefix = NULL;

        switch( level )
        {
            case LogAll:
                        lpszPrefix = _T("Debug: ");
                        break;

            case LogInfo:
                        lpszPrefix = _T("Info: ");
                        break;

            case LogWarning:
                        lpszPrefix = _T("Warning: ");
                        break;

            case LogError:
                        lpszPrefix = _T("Error: ");
                        break;

            default:
                return stream;
        }

        return stream<<lpszPrefix;
    }

    class ILogger
    {
    protected:

        virtual void WriteEntry_( LogLevel level, LPCTSTR lpszMessage ) = 0;

        ~ILogger(){}

    public:

        void WriteEntry(LogLevel level, LPCTSTR lpszMessage )
        {
            WriteEntry_(level, lpszMessage);
        }
    };    
    
    class LogEntry
    {
    protected:

        typedef ATL::CString String;

        ILogger*                pLogger_;
        std::auto_ptr<String>    pBuffer_;
        LogLevel                Level_;

    protected:

        LogEntry( LogLevel level, ILogger* pLogger )
            : Level_(level), pLogger_(pLogger), pBuffer_( new String() )
        {}        

        LogEntry& operator =( const LogEntry& );        

        template <typename T>
        void AppendRecord( const T& record )
        {
            pBuffer_->Append(record);
            pBuffer_->Append(_T(". "));
        }

    public:

        LogEntry( LogEntry& entry )
        {
            Level_ = entry.Level_;
            pLogger_ = entry.pLogger_;
            pBuffer_ = entry.pBuffer_;
        }

        virtual ~LogEntry()
        {
            try
            {
                if( !pBuffer_->IsEmpty() ) pLogger_->WriteEntry( Level_, (*pBuffer_) );
            }
            catch(...){}
        }

        static LogEntry Instance( LogLevel level, ILogger* pLogger )
        {
            return LogEntry( level, pLogger );
        }

        LogEntry operator <<( int value )
        {
            String tmp;
            tmp.Format("%d", value);
            AppendRecord(tmp);
            return *this;
        }

        LogEntry operator <<( HRESULT value )
        {
            String tmp;
            tmp.Format("Error 0x%08x", value);
            AppendRecord(tmp);
            return *this;
        }

        template <typename T>
        LogEntry operator <<( const T& value )
        {            
            AppendRecord(value);
            return *this;
        }
    };    

    class ConsoleLogger : public ILogger
    {
    protected:

        void WriteEntry_( LogLevel level, LPCTSTR lpszMessage )
        {
//            if( level > LogInfo )
            {
                std::cout<<level<<lpszMessage<<endl;
            }            
        };

    public:

        static ConsoleLogger& Instance()
        {
            static ConsoleLogger logger;
            return logger;
        }        
        
        static LogEntry log( LogLevel level )
        {
            return LogEntry::Instance(level, &ConsoleLogger::Instance());
        }
    };

    template <typename T>
    LogEntry operator <<( LogLevel level, const T& value )
    {
        return LogEntry::Instance(level, &ConsoleLogger::Instance())<<value;
    }

    int main()
    {
        LogWarning<<_T("wow")<<10<<E_FAIL<<-10000;//красиво, но не позволяет выбирать тип логгера
        ConsoleLogger::log(LogInfo)<<_T("xaxaxaxxaxaxxax..")<<_T("suxx...");//некрасиво, но позволяет...
    }
}


Набросал за час, так что пинать не сильно
Из достоинств — неограниченное добавление записей в строку, можно прикрутить манипуляторы.
Идея взята здесь
Автор: Шахтер
Дата: 16.02.06



03.04.06 20:29: Перенесено из 'C/C++'
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.