c++ 日志系统 超轻量化

背景:

c++的大型开源日志系统有glog,log4cpp等,但是这些日志系统太庞大,在工程中应用还需专门学习。一些小型项目用不着那样的日志系统。本篇博客将从0开始,一步一步教你打造一款自己的c++日志系统。我们设计的初衷是超轻量化,所以严格控制代码量。

第一个日志系统

我们先写一个简单的日志系统,以同步方式记录日志,并且采用c++的流方式进行日志记录。在开始之前你需要了解c++的单例模式。

我们先写一个应用的demo,以此来设计。

/*
 *基本使用
 */
#include"sync_log.h"

int main()
{
    
    LOGINIT("app_log/log","demo1.log");
    for(int i=0;i<1e5;++i)
    { 
        ERROR<<"error"<<endl;
        INFO<<"info"<<endl;
        DEBUG<<"debug"<<endl;
    }
}

 

头文件如下,这里我们写出了日志系统的框架和主要实现。

/*
 * 同步日志系统
 * */
#include<iostream>
#include<fstream>
#include<sstream>
#include<unistd.h>
#include<sys/time.h>
#include<sys/stat.h>

#define LOGINIT(dir,file_name) \
do\
{\
    Log::inst()->init_path(dir,file_name);\
}while(0)

#define DEBUG Log::inst()->_file<<"[DEBUG]"<<__DATE__<<"|"<<__TIME__<<"|"<<__FILE__<<"|"<<__func__<<"|"<<__LINE__<<": " 
#define ERROR Log::inst()->_file<<"[ERROR]"<<__DATE__<<"|"<<__TIME__<<"|"<<__FILE__<<"|"<<__func__<<"|"<<__LINE__<<": " 
#define INFO Log::inst()->_file<<"[INFO]"<<__DATE__<<"|"<<__TIME__<<"|"<<__FILE__<<"|"<<__func__<<"|"<<__LINE__<<": " 

using namespace std;
class Log
{
private:
    string _dir;
    string _file_name;  
    static Log* _inst;//单例模式
    Log() {}
    ~Log() {}
public:
     ofstream _file;
     static Log* inst()
    {
         if(_inst == NULL)
        {
            //cout<<"inst is NULL , create "<<endl;
            _inst = new Log();
        }
        return _inst;
    }
   
    void init_path(const string& dir, const string& file_name);
    bool makedir(const std::string& dir);
    bool openfile(const string& file_name);
    string get_curr_time();//当前系统时间,形式:20190804|09:28:56
};

//数字转字符串
//demo: int a = str2num<int>(string("-01.23"));
template <class T>
T str2num(const string &str)
{
    stringstream ss;
    T num;
    ss << str;
    ss >> num;
    return num;
}

//demo: double num=-23.1; string str = num2str(num);
//也可以指定T的类型,str = num2str<int>(num);
template <class T>
string num2str(const T &num)
{
    stringstream ss;
    ss << num;
    string str;
    ss >> str;
    return str;
}

实现:

/*
 *
 * */
#include "sync_log.h"
#include <sys/time.h> //struct timeval
#include <time.h>     //struct tm

Log *Log::_inst = NULL;
void Log::init_path(const string &dir, const string &file_name)
{
    _dir = dir;
    if (file_name.size() < 4 || file_name.substr(file_name.size() - 4) != ".log")
    {
        _file_name = file_name + ".log";
    }
    else
    {
        _file_name = file_name;
    }
    
    _file_name = get_curr_time().substr(0, 14) + _file_name;//20180809logname.log,8
    makedir(_dir);
    openfile(_file_name);
}

bool Log::makedir(const std::string &dir)
{
    stringstream ss;
    ss << dir;
    string dir_c;
    string tmp;
    while (getline(ss, tmp, '/')) //getline第一个参数是流。
    {
        dir_c = dir_c + tmp + "/";
        if (access(dir_c.c_str(), F_OK | W_OK) == 0) //如果目录已经存在,可读可写,则跳过
        {
            //DEBUG<<"dir "<<dir_c<<" exists!"<<endl;
            continue;
        }
        if (mkdir(dir_c.c_str(), 0777) != 0) //返回0表示成功,失败则退出程序
        {
            //DEBUG<<"mkdir fail "<<dir_c<<endl;
            return false;
        }
    }
    return true;
}

bool Log::openfile(const string &file_name)
{
    string dir_file;
    if ((!_dir.empty()) && _dir[_dir.size() - 1] != '/')
    {
        dir_file = _dir + "/" + file_name;
    }
    else
        dir_file = _dir + file_name;
    cout<<file_name<<endl;
    _file.open(dir_file.c_str(), ios::app); //追加写入
    return true;
}

string Log::get_curr_time()
{
    struct timeval tv;
    gettimeofday(&tv, NULL); //step1
    uint64_t sys_sec = tv.tv_sec;
    //DEBUG<<"sys_sec="<<sys_sec<<endl;
    struct tm curr_time;
    localtime_r((time_t *)&sys_sec, &curr_time); //setp2
    string ret;
    string year, mon, mday, hour, min, sec;
    year = num2str<uint64_t>(curr_time.tm_year + 1900);
    mon = num2str<uint64_t>(curr_time.tm_mon + 1);
    mday = num2str<uint64_t>(curr_time.tm_mday);
    hour = num2str<uint64_t>(curr_time.tm_hour);
    min = num2str<uint64_t>(curr_time.tm_min);
    sec = num2str<uint64_t>(curr_time.tm_sec);
    if (mon.size() < 2)
        mon = "0" + mon;
    if (mday.size() < 2)
        mday = "0" + mday;
    if (hour.size() < 2)
        hour = "0" + hour;
    if (min.size() < 2)
        min = "0" + min;
    if (sec.size() < 2)
        sec = "0" + sec;
    ret = year + mon + mday + "|" + hour + "
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值