Program Listing for File ULogger.h

Return to documentation for file (/tmp/ws/src/find_object_2d/include/find_object/utilite/ULogger.h)

/*
*  utilite is a cross-platform library with
*  useful utilities for fast and small developing.
*  Copyright (C) 2010  Mathieu Labbe
*
*  utilite is free library: you can redistribute it and/or modify
*  it under the terms of the GNU Lesser General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  utilite is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef ULOGGER_H
#define ULOGGER_H

#include "find_object/FindObjectExp.h" // DLL export/import defines

#include "find_object/utilite/UMutex.h"
#include "find_object/utilite/UDestroyer.h"

#include <stdio.h>
#include <time.h>
#include <string>
#include <vector>

#include <stdarg.h>

#if _MSC_VER
    #undef min
    #undef max
#endif

/*
 * Convenient macros for logging...
 */
#define ULOGGER_LOG(level, ...) ULogger::write(level, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)

#define ULOGGER_DEBUG(...)   ULOGGER_LOG(ULogger::kDebug,   __VA_ARGS__)
#define ULOGGER_INFO(...)    ULOGGER_LOG(ULogger::kInfo,    __VA_ARGS__)
#define ULOGGER_WARN(...)    ULOGGER_LOG(ULogger::kWarning, __VA_ARGS__)
#define ULOGGER_ERROR(...)   ULOGGER_LOG(ULogger::kError,   __VA_ARGS__)
#define ULOGGER_FATAL(...)   ULOGGER_LOG(ULogger::kFatal,   __VA_ARGS__)

#define UDEBUG(...)   ULOGGER_DEBUG(__VA_ARGS__)
#define UINFO(...)    ULOGGER_INFO(__VA_ARGS__)
#define UWARN(...)    ULOGGER_WARN(__VA_ARGS__)
#define UERROR(...)   ULOGGER_ERROR(__VA_ARGS__)
#define UFATAL(...)   ULOGGER_FATAL(__VA_ARGS__)

#define UASSERT(condition) if(!(condition)) ULogger::write(ULogger::kFatal, __FILE__, __LINE__, __FUNCTION__, "Condition (%s) not met!", #condition)
#define UASSERT_MSG(condition, msg_str) if(!(condition)) ULogger::write(ULogger::kFatal, __FILE__, __LINE__, __FUNCTION__, "Condition (%s) not met! [%s]", #condition, msg_str)

class FINDOBJECT_EXP ULogger
{

public:
    static const std::string kDefaultLogFileName;

    enum Type{kTypeNoLog, kTypeConsole, kTypeFile};

    enum Level{kDebug, kInfo, kWarning, kError, kFatal};

    static void setType(Type type, const std::string &fileName = kDefaultLogFileName, bool append = true);
    static Type type() {return type_;}

    // Setters
    static void setPrintTime(bool printTime) {printTime_ = printTime;}
    static bool isPrintTime() {return printTime_;}

    static void setPrintLevel(bool printLevel) {printLevel_ = printLevel;}
    static bool isPrintLevel() {return printLevel_;}

    static void setPrintEndline(bool printEndline) {printEndline_ = printEndline;}
    static bool isPrintEndLine() {return printEndline_;}

    static void setPrintColored(bool printColored) {printColored_ = printColored;}
    static bool isPrintColored() {return printColored_;}

    static void setPrintWhere(bool printWhere) {printWhere_ = printWhere;}
    static bool isPrintWhere() {return printWhere_;}

    static void setPrintWhereFullPath(bool printWhereFullPath) {printWhereFullPath_ = printWhereFullPath;}
    static bool isPrintWhereFullPath() {return printWhereFullPath_;}

    static void setBuffered(bool buffered);
    static bool isBuffered() {return buffered_;}

    static void setLevel(ULogger::Level level) {level_ = level;}
    static ULogger::Level level() {return level_;}

    static void setExitLevel(ULogger::Level exitLevel) {exitLevel_ = exitLevel;}
    static ULogger::Level exitLevel() {return exitLevel_;}

    static void setEventLevel(ULogger::Level eventSentLevel) {eventLevel_ = eventSentLevel;}
    static ULogger::Level eventLevel() {return eventLevel_;}

    static void reset();

    static void flush();

    static void write(const char* msg, ...);

    /*
     * Write a message to logger: use UDEBUG(), UINFO(), UWARN(), UERROR() or UFATAL() instead.
     * @param level the log level of this message
     * @param file the file path
     * @param line the line in the file
     * @param function the function name in which the message is logged
     * @param msg the message to write
     * @param ... the variable arguments
     */
    static void write(ULogger::Level level,
            const char * file,
            int line,
            const char *function,
            const char* msg,
            ...);

    static int getTime(std::string &timeStr);

protected:
    /*
     * This method is used to have a reference on the
     * Logger. When no Logger exists, one is
     * created. There is only one instance in the application.
     * Must be protected by loggerMutex_.
     * See the Singleton pattern for further explanation.
     *
     * @return the reference on the Logger
     */
    static ULogger* getInstance();

    /*
     * Called only once in getInstance(). It can't be instanciated
     * by the user.
     *
     * @see getInstance()
     */
    ULogger() {}

    /*
     * Only called by a Destroyer.
     * @see Destroyer
     */
    virtual ~ULogger();

    /*
     * Flush buffered messages
     */
    void _flush();

    /*
     * A Destroyer is used to remove a dynamicaly created
     * Singleton. It is friend here to have access to the
     * destructor.
     *
     * @see Destroyer
     */
    friend class UDestroyer<ULogger>;

    /*
     * The log file name.
     */
    static std::string logFileName_;

    /*
     * Default true, it doesn't overwrite the file.
     */
    static bool append_;

private:
    /*
     * Create an instance according to type. See the Abstract factory
     * pattern for further explanation.
     * @see type_
     * @return the reference on the new logger
     */
    static ULogger* createInstance();

    /*
     * Write a message on the output with the format :
     * "A message". Inherited class
     * must override this method to output the message. It
     * does nothing by default.
     * @param msg the message to write.
     * @param arg the variable arguments
     */
    virtual void _write(const char* msg, va_list arg) {} // Do nothing by default
    virtual void _writeStr(const char* msg) {} // Do nothing by default

private:
    /*
     * The Logger instance pointer.
     */
    static ULogger* instance_;

    /*
     * The Logger's destroyer
     */
    static UDestroyer<ULogger> destroyer_;

    /*
     * If the logger prints the time for each message.
     * Default is true.
     */
    static bool printTime_;

    /*
     * If the logger prints the level for each message.
     * Default is true.
     */
    static bool printLevel_;

    /*
     * If the logger prints the end line for each message.
     * Default is true.
     */
    static bool printEndline_;

    /*
     * If the logger prints text with color.
     * Default is true.
     */
    static bool printColored_;

    /*
     * If the logger prints where the message is logged (fileName::function():line).
     * Default is true.
     */
    static bool printWhere_;

    /*
     * If the logger prints the full path of the source file
     * where the message is written. Only works when
     * "printWhere_" is true.
     * Default is false.
     */
    static bool printWhereFullPath_;

    /*
     * If the logger limit the size of the "where" path to
     * characters. If the path is over 8 characters, a "~"
     * is added. Only works when "printWhereFullPath_" is false.
     * Default is false.
     */
    static bool limitWhereLength_;

    /*
     * The type of the logger.
     */
    static Type type_;

    /*
     * The severity of the log.
     */
    static Level level_;

    /*
     * The severity at which the application exits.
     * Note : A FATAL level will always exit whatever the level specified here.
     */
    static Level exitLevel_;

    /*
     * The severity at which the message is also sent in a ULogEvent.
     */
    static Level eventLevel_;

    static const char * levelName_[5];

    /*
     * Mutex used when accessing public functions.
     */
    static UMutex loggerMutex_;

    /*
     * If the logger prints messages only when ULogger::flush() is called.
     * Default is false.
     */
    static bool buffered_;

    static std::string bufferedMsgs_;

    /*
     * State attribute. This state happens when an exit level
     * message is received.
     * Messages received during this state are not logged.
     * @see exitLevel_
     */
    static bool exitingState_;
};

#endif // ULOGGER_H