zoukankan      html  css  js  c++  java
  • 一个小而美的C++日志类

    废话少说,先看东西。

    //log.h
    #pragma once
    
    #define LOG_BUFSIZE  1024
    
    enum LogLevel
    {
        LV_DEBUG = 1,
        LV_INFO = 2,
        LV_WARN = 4,
        LV_ERROR = 8,
        LV_ALL = 15
    };
    
    class Log
    {
    public:
        static bool CreateInst(const char * p_logdir = 0, const char * p_logname = 0, bool append = true, LogLevel level = LV_ALL);
        static void DestroyInst();
        static void DEBUG(const char * logformat, ...);
        static void INFO(const char * logformat, ...);
        static void WARN(const char * logformat, ...);
        static void Error(const char * logformat, ...);
        static void SetLoggerLevel(LogLevel level);
    private:
        Log(const char * filelocation);
        bool write(LogLevel level, const char * logformat, ...);
        ~Log();
    
    private:
        static int preMakeStr(LogLevel level, char * buffer);
    
    private:
        FILE * fp;
        char m_buffer[LOG_BUFSIZE];
        LogLevel m_level;
        static Log * p_instance;
    };
    
    #ifdef _DEBUG
    #define LOG_DEBUG(log_fmt, ...) do { Log::DEBUG(log_fmt, __VA_ARGS__); } while (0)
    #else
    #define LOG_DEBUG()
    #endif
    
    #define LOG_INFO(log_fmt, ...) do { Log::INFO(log_fmt, __VA_ARGS__); } while (0)
    //log.cpp
    #include "StdAfx.h"
    #include "log.h"#include <direct.h>
    #include <set>
    #include <map>
    bool Log::CreateInst(const char * p_logdir, const char * p_logname, bool append, LogLevel level)
    {
        if (p_instance)
            return true;
        std::string name;
        if (p_logname == 0) {
            time_t curTime;
            time(&curTime);
            tm tm1;
            localtime_s(&tm1, &curTime);
            char buffer[MAX_PATH];
            memset(buffer, 0, MAX_PATH);
            _snprintf(buffer, MAX_PATH, "%04d%02d%02d_%02d%02d%02d.log", tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm1.tm_sec);
            name = buffer;
        } else {
            name = p_logname;
        }
        std::string path;
        if (p_logdir == 0) {
            TCHAR tmpP[MAX_PATH];
            GetEnvironmentVariable(_T("APPDATA"), tmpP, MAX_PATH);
            path = String::ToString(tmpP);
            path += "\TSZ\log";
        } else {
            path = p_logdir;
        }
        if (*path.rbegin() != '\')
            path += '\';
        if (access(path.c_str(), 0) == -1) {
            if (mkdir(path.c_str()) < 0) {
                fprintf(stderr, "create folder failed
    ");
                return false;
            }
        }
        char buffer[MAX_PATH];
        memset(buffer, 0, MAX_PATH);
        _snprintf(buffer, MAX_PATH, "%s%s", path.c_str(), name.c_str());
        if (!append)
            DeleteFile(String::ToCString(buffer));
    
        p_instance = new Log(buffer);
        p_instance->SetLoggerLevel(level);
        return p_instance != 0;
    }
    
    void Log::DestroyInst()
    {
        delete p_instance;
        p_instance = 0;
    }
    
    void Log::DEBUG(const char * logformat, ...)
    {
        if (!p_instance)
            return;
        if ((p_instance->m_level & LV_DEBUG) == 0)
            return;
        va_list args;
        va_start(args, logformat);
        p_instance->write(LV_INFO, logformat, args);
        va_end(args);
    }
    
    void Log::INFO(const char * logformat, ...)
    {
        if (!p_instance)
            return;
        if ((p_instance->m_level & LV_INFO) == 0)
            return;
        va_list args;
        va_start(args, logformat);
        p_instance->write(LV_INFO, logformat, args);
        va_end(args);
    }
    
    void Log::WARN(const char * logformat, ...)
    {
        if (!p_instance)
            return;
        if ((p_instance->m_level & LV_WARN) == 0)
            return;
        va_list args;
        va_start(args, logformat);
        p_instance->write(LV_INFO, logformat, args);
        va_end(args);
    }
    
    void Log::Error(const char * logformat, ...)
    {
        if (!p_instance)
            return;
        if ((p_instance->m_level & LV_ERROR) == 0)
            return;
        va_list args;
        va_start(args, logformat);
        p_instance->write(LV_INFO, logformat, args);
        va_end(args);
    }
    
    void Log::SetLoggerLevel(LogLevel level)
    {
        if (!p_instance)
            return;
        p_instance->m_level = level;
    }
    
    Log::Log(const char * filelocation)
    {
        fp = _fsopen(filelocation, "a+", _SH_DENYNO);
        m_level = LV_ALL;
        memset(m_buffer, 0, LOG_BUFSIZE);
    }
    
    bool Log::write(LogLevel level, const char * logformat, ...)
    {
        if (fp == NULL) {
            return false;
        }
        memset(m_buffer, 0, LOG_BUFSIZE);
        int nsize = 0;
        int prestrlen = 0;
        char * str = m_buffer;
        prestrlen = preMakeStr(level, str);
        str += prestrlen;
    
        va_list args;
        va_start(args, logformat);
        nsize = _vsnprintf(str, LOG_BUFSIZE - prestrlen, logformat, args);
        va_end(args);
    
        if (level == LV_ERROR) {
            str += nsize;
            nsize = _snprintf(str, LOG_BUFSIZE - prestrlen - nsize, "[%s - %s - %d]", __FILE__, __FUNCTION__, __LINE__);
        }
    
        fprintf(fp, "%s
    ", m_buffer);
        fflush(fp);
        return true;
    }
    
    Log::~Log()
    {
        if (fp) {
            fclose(fp);
            fp = NULL;
        }
    }
    
    int Log::preMakeStr(LogLevel level, char * buffer)
    {
        const char * lv = 0;
        switch (level) {
        case LV_DEBUG:
            lv = "debug";
            break;
        case LV_INFO:
            lv = "info";
            break;
        case LV_WARN:
            lv = "warn";
            break;
        case LV_ERROR:
            lv = "error";
            break;
        default:
            lv = "info";
            break;
        }
        time_t now;
        now = time(&now);
        struct tm vtm = *localtime(&now);
        return _snprintf(buffer, LOG_BUFSIZE, "[%04d-%02d-%02d %02d:%02d:%02d][%s] ", vtm.tm_year + 1900,
            vtm.tm_mon + 1, vtm.tm_mday, vtm.tm_hour, vtm.tm_min, vtm.tm_sec, lv);
    }
    
    Log * Log::p_instance = 0;

    由于实现过程用了单例模式,所以在构造对象的时候需要调用类提供的相应函数。

    下面是使用用例:

    int main()
    {
        Log::CreateInst();
        Log::INFO("Everything is OK!");
        Log::DestroyInst();
    }
  • 相关阅读:
    第四节 哈希类型
    第三节 string类型
    第二节 redis的数据类型和一些通用的键命令
    第一节 Redis的安装配置
    第三十二节 定时器
    第三十一节 sed命令
    第三十节 awk命令
    第二十九节 cut命令
    第二十八节 函数和脚本调试
    Gartner 如何看 RASP 和 WAF?
  • 原文地址:https://www.cnblogs.com/tszdev/p/9447219.html
Copyright © 2011-2022 走看看