一个简单的日志类的开发

前段时间,由于工作需要,需开发一个新的日志类,要求将服务端所处理的有关同一个请求的所有日志全部记录在一个json中,以方便日志收集与查询、分析。像以前那样处理到某一步打印一条日志的方式便不再可行了。

一个请求由于中间有好多处理过程,而且不尽相同,要求将这些处理产生的日志都打印在一起,最先想到的自然就是设计一个新的日志类,里边有一个buffer,在收到请求时创建一个该类的对象,然后所有的请求日志都通过该类写入buffer,而实际写入日志文件则是在该类的析构函数中进行,也就达到了一次性写入的目的。

  

//请求日志记录类,每条请求添加一条日志记录的对象
class RequestLogger
{
public:
    enum LogLevel
    {
        TRACE = 0,
        DEBUG,
        INFO,
        WARN,
        ERROR,
        NUM_LOG_LEVELS
    };
    
    ~RequestLogger()
    {
        Json::FastWriter writer;
        std::string &&s = writer.write(m_value);
        LoggerWriter::getLoggerWriter().write(s);
    }

    RequestLogger& operator <<(std::string s)
    {
        if(s.size() != 0)
            m_buf.append(s);
        return *this;
    }
    RequestLogger& operator <<(int i)
    {
        try
        {
            std::string tmp = boost::lexical_cast<std::string>(i);
            return *this << tmp;
        }catch(boost::bad_lexical_cast& e)
        {
            return *this;
        }
        
    }

    void addLog(LogLevel level, const char* filename, const int line)
    {
        Json::Value tmp;
        const char* slash = strrchr(filename, '/');
        if(!slash)
            slash = filename;
        else
            slash++;
        tmp["file"] = slash;
        tmp["line"] = line;
        struct timeval tv;
        gettimeofday(&tv, NULL);
        int64_t seconds = tv.tv_sec + 8*3600; //    UTC + 8.0
        char buf[32] = {0};
        struct tm tm_time;
        gmtime_r(&seconds,&tm_time);
        snprintf(buf, sizeof(buf), "%4d-%02d-%02d %02d:%02d:%02d.%06d",
             tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
             tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec,
             tv.tv_usec);
        tmp["time"] = std::string(buf);
        tmp["content"] = m_buf;
        switch(level)
        {
            case TRACE:
                tmp["level"] = "TRACE";
                break;
            case DEBUG:
                tmp["level"] = "DEBUG";
                break;
            case INFO:
                tmp["level"] = "INFO";
                break;
            case WARN:
                tmp["level"] = "WARN";
                break;
            case ERROR:
                tmp["level"] = "ERROR";
                break;
        }
        m_value["processlog"].append(tmp);
        m_buf = "";
        
    }
    
private:
    std::string m_buf;
    Json::Value m_value;
};

 

通过重载operator << 操作符,对日志写入进行了方便对日志进行写入,然后,再定义addLog函数,将buf中的内容转换到json变量中,最后在析构时调用LoggerWriter单例类去写入日志文件。为方便使用,定义以下宏来使用。

#define REQUEST_TRACE(logger_ptr, logstream) ((*logger_ptr) << logstream).addLog(RequestLogger::LogLevel::TRACE, __FILE__, __LINE__);
#define REQUEST_DEBUG(logger_ptr, logstream) ((*logger_ptr) << logstream).addLog(RequestLogger::LogLevel::DEBUG, __FILE__, __LINE__);
#define REQUEST_INFO(logger_ptr, logstream) ((*logger_ptr) << logstream).addLog(RequestLogger::LogLevel::INFO, __FILE__, __LINE__);
#define REQUEST_WARN(logger_ptr, logstream) ((*logger_ptr) << logstream).addLog(RequestLogger::LogLevel::WARN, __FILE__, __LINE__);
#define REQUEST_ERROR(logger_ptr, logstream) ((*logger_ptr) << logstream).addLog(RequestLogger::LogLevel::ERROR, __FILE__, __LINE__);

记录日志使用如下:

std::shared_ptr<RequestLogger> ptr_logger(new RequestLogger());
REQUEST_INFO(ptr_logger, "基本预处理后: " << tmp_query);

还是蛮方便的。

posted @ 2017-04-05 09:03  重复啦  阅读(324)  评论(0编辑  收藏  举报