crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Bregma logger, реализация логгера, заслуживающая рассмотрения
Andrew Selivanov
  опции профиля:
сообщение 7.4.2008, 14:49
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 249
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 3

Спасибо сказали: 15 раз(а)




Репутация:   6  


Реализация логгера, заслуживающая рассмотрения.
http://www.gamedev.net/community/forums/vi....asp?ID=2834700

На всякий случай помещу здесь код:
#include <streambuf>
#include <string>

namespace Bregma
{
    /**
     * The DebugStreambuf provides a concrete basic_streambuf that appends a
     * timestamp and process ID (or thread ID) at the start of each new line.
     *
     * This streambuf is an unbuffered streambuf.  It is not capable of input.
     */
    template<typename Char, typename Traits = std::char_traits<Char> >
        class DebugStreambuf
        : public std::basic_streambuf<Char, Traits>
        {
        public:
            typedef typename std::basic_streambuf<Char, Traits>::traits_type traits_type;
            typedef typename std::basic_streambuf<Char, Traits>::int_type    int_type;

        public:
            /**
             * Buffer construction.
             */
            DebugStreambuf(std::basic_streambuf<Char, Traits> *pRealBuf);

            void setLogLevel(const LogLevel &logLevel)
            { m_logLevel = logLevel; }

            void setFacility(const std::string &facility)
            { m_facility = facility; }

        protected:
            /**
             * Function called by an ostream when it's time to send something out.
             *
             * @param c The value to be written out (generally a single character).
             *
             * @returns A value equal to traits_type::eof() on failure,
             * traits_type::not_eof() on success.
             */
            int_type
            overflow(int_type c = traits_type::eof());

        private:
            DebugStreambuf(const DebugStreambuf&);
            DebugStreambuf& operator=(const DebugStreambuf&);

        private:
            std::basic_streambuf<Char, Traits> *m_pRealBuf;
            bool                                m_bAtBeginningOfLine;
            LogLevel                            m_logLevel;
            std::string                         m_facility;
        };
} // namespace Bregma


#include "debugstreambuf.h"
#include <sstream>

using namespace std;

/**
* Constructs a basic DebugStream.
*/
template<typename C, typename T>
    Bregma::DebugStreambuf<C,T>::
        DebugStreambuf(basic_streambuf<C,T>* pRealBuf)
        : m_pRealBuf(pRealBuf)
        , m_bAtBeginningOfLine(true)
        , m_logLevel(kLOG_INFO)
        {
        }



/**
* Actual function to move bytes to the logging stream if appropriate.
*/
template<typename C, typename T>
    typename Bregma::DebugStreambuf<C,T>::int_type Bregma::DebugStreambuf<C,T>::
    overflow(int_type c)
    {
        int_type retval = traits_type::not_eof(c);
        if (!traits_type::eq_int_type(c, traits_type::eof()))
        {

            if (m_bAtBeginningOfLine)
            {
                m_bAtBeginningOfLine = false;
                basic_ostringstream<C,T> ostr;

                // Format and display the level tag.
                char tag = '?';
                switch (m_logLevel)
                {
                    case kLOG_FATAL:
                        tag = 'F';
                        break;
                    case kLOG_ERROR:
                        tag = 'E';
                        break;
                    case kLOG_WARNING:
                        tag = 'W';
                        break;
                    case kLOG_INFO:
                        tag = 'I';
                        break;
                    case kLOG_VERBOSE:
                        tag = 'V';
                        break;
                    case kLOG_DEBUG:
                        tag = 'D';
                        break;
                    default:
                        tag = '?';
                }
                ostr << '-' << tag << '-';

                // Format and display the time stamp.
                time_t curTime = std::time(NULL);
                char timestamp[32];
                std::strftime(timestamp,
                          sizeof(timestamp),
                                              "%Y.%m.%dT%H:%M:%S",
                          localtime(&curTime));
                ostr << timestamp;

                // Format and display the facility.
                if (!m_facility.empty())
                {
                    ostr << '[' << m_facility << ']';
                }

                if (!ostr.str().empty())
                {
                    ostr << ": ";
                }

                // Send the prefix string out.
                const basic_string<C,T>& str = ostr.str();
                streamsize sz = m_pRealBuf->sputn(str.c_str(), str.length());
                if (sz != str.length())
                {
                    return traits_type::eof();
                }
            }

            // Send the real character out.
            retval =  m_pRealBuf->sputc(c);
        }

        // If the end-of-line was seen, reset the beginning-of-line indicator and
        // the default log level.
        if (traits_type::eq_int_type(c, traits_type::to_int_type('\n')))
        {
            m_bAtBeginningOfLine = true;
            m_logLevel = kLOG_INFO;
        }
        return retval;
    }


namespace Bregma
{
    enum LogLevel
    {
        kLOG_FATAL,
        kLOG_ERROR,
        kLOG_WARNING,
        kLOG_INFO,
        kLOG_VERBOSE,
        kLOG_DEBUG
    };

    /**
     * Convert an IOStream to a Bregma logging stream.
     *
     * This can be used to convert, for example, std::cerr into a Bregma logging
     * stream.
     *
     * @param ostr  [IN]  The IOStream to convert.
     * @param level [IN]  The default loglevel cutoff (default is INFO).
     * @param flags [IN]  Flags to toggle various output fields.
     */
    void convertToBregmaLogger(std::ostream   &ostr);

    /**
     * Setter for the log level cutoff.
     *
     * @param ostr  [IN]  The IOStream for which the log cutoff is to be set.
     * @param level [IN]  The new log level cutoff.
     */
    void setLogCutoff(std::ostream &ostr, const LogLevel &level);


    /**
     * Manipulator helper for setting the current log level on a debug stream.
     */
    class LogLevelSetting
    {
    public:
        LogLevel level() const { return m_level; }
    private:
        explicit LogLevelSetting(LogLevel level): m_level(level) {}
        friend const LogLevelSetting logLevel(LogLevel);
    private:
        LogLevel m_level;
    };

    /**
     * Ostream manipulator for setting the current log level.
     */
    inline const LogLevelSetting logLevel(LogLevel level)
    {
        return LogLevelSetting(level);
    }

    /**
     * Ostream inserter for the log level manipulator.
     *
     * @param ostr [IN] The output stream.
     * @param ls   [IN] The log level setting.
     */
    std::ostream& operator<<(std::ostream& ostr, const LogLevelSetting ls);


    /**
     * A manipulator helper for seeting the facility.
     */
    class LogFacilitySetter
    {
    public:
        const std::string &facility() const { return m_facility; }
    private:
        LogFacilitySetter(const std::string &facility): m_facility(facility) {}
        friend const LogFacilitySetter logFacility(const std::string &facility);
    private:
        const std::string& m_facility;
    };

    /**
     * An ostream manipulator for setting the current facility in the log stream.
     */
    inline const LogFacilitySetter logFacility(const std::string &facility)
    {
        return LogFacilitySetter(facility);
    }

    /**
     * Ostream inserter for the facility manipulator.
     *
     * @param ostr [IN] The output stream.
     * @param ls   [IN] The log facility setter manipulator helper..
     */
    std::ostream& operator<<(std::ostream& ostr, const LogFacilitySetter ls);

    /**
     * A handy stream to mark the entry and exit of a scope.
     *
     * @param ostr [IN] The output stream.
     * @param ls   [IN] A string.
     */
    class ScopeMarker
    {
    public:
        ScopeMarker(std::ostream &ostr, const std::string &what)
        : m_ostr(ostr)
        , m_what(what)
        {
            m_ostr << m_what << " begins\n";
        }

        ~ScopeMarker()
        {
            m_ostr << m_what << " ends\n";
        }

    private:
        std::ostream  &m_ostr;
        std::string    m_what;
    };
} // namespace Bregma


void Bregma::convertToBregmaLogger(ostream        &ostr)
{
    ostr.rdbuf(new DebugStreambuf<char>(ostr.rdbuf()));
}


ostream &Bregma::operator<<(ostream& ostr, const Bregma::LogLevelSetting ls)
{
    typedef DebugStreambuf<char> Dstr;
    Dstr *pDstr = dynamic_cast<Dstr*>(ostr.rdbuf());
    if (pDstr)
    {
        pDstr->setLogLevel(ls.level());
    }
    return ostr;
}


ostream &Bregma::operator<<(ostream& ostr, const Bregma::LogFacilitySetter ls)
{
    typedef DebugStreambuf<char> Dstr;
    Dstr *pDstr = dynamic_cast<Dstr*>(ostr.rdbuf());
    if (pDstr)
    {
        pDstr->setFacility(ls.facility());
    }
    return ostr;
}


Пример использования
#include "bregmalogger.h"
#include <iostream>

using namespace std;
using namespace Bregma;

int main(int, char*[])
{
  convertToBregmaLogger(cerr);
  cerr << logFacility("TEST") << logLevel(kLOG_WARNING) << "This is a demo.\n";
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 1.4.2020, 11:21