日志系统——实用类设计,日志等级类设计,日志消息类设计

一,实用类设计

该类主要是提前完成一些后面会用到的零碎通用的功能接口,主要有下面几个

1.获取系统时间:这里我们直接用time()函数获取时间返回

2.判断文件是否存在:判断文件我们调用系统接口,stat(),如下所示,第一个为文件路径,第二个是一个结构体,创建传入指针即可,返回0说明存在,-1说明不存在或者错误。

 

 3.获取文件的所在目录路径:以''./abc/a.txt''为例,该文件路径其实就是最后一个'/'以前(包括'/'),这里我们可以直接用string提供的搜索接口即可

 4.创建目录:以"./abc/ad/a.txt"为例,创建目录要一个一个建,先创建/abc,再依次进行,创建目录我们可以调用系统接口mkdir(),如下所示,第一个参数是所建目录路径,第二个参数为该目录权限

代码如下,注意后面三个功能都是关于文件路径的,因此我们将后面三个放到了一个类中实现

#ifndef _M_UTIL_H_
#define _M_UTIL_H_

#include <iostream>
#include <ctime>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

namespace mjw
{
    namespace util
    {
        //设计两个类,时间一个类,后面的文件存在判断,文件目录路径,创建目录分为一个类
        class gettime
        {
            public:
                static size_t nowtime() 
                {
                    return (size_t)time(nullptr);
                }
        };

        class FileDirectory
        {
            public:
            //1.判断文件是否存在
            static bool exist(const std::string& filename)
            {
                struct stat sm;
                return stat(filename.c_str(),&sm)==0;
            }
            //2.获取文件路径
            static std::string getDirectory(const std::string& filename)
            {
                if(filename.empty()) return ".";
                int pos=filename.find_last_of("/\\");
                if(pos==std::string::npos)//pos==npos说明没有找到
                {
                    return ".";
                }

                return filename.substr(0,pos+1);
            }
            //3.创建目录
            static void createDirectory(const std::string& path)
            {
                // ./abc/ab/c.txt
                if(path.empty()) return;
                if(exist(path)) return;
                int pos=0,indox=0;

                while(indox<path.size())
                {
                    pos=path.find_first_of("/\\",indox);
                    //当pos==npos时,说明pos到indox已经没有/,说该创建最后一个文件,创建完break即可
                    if(pos==std::string::npos)
                    {
                        mkdir(path.c_str(),0777);
                        break;
                    }
                    if(!exist(path.substr(0,pos))) mkdir(path.substr(0,pos).c_str(),0777);
                    indox=pos+1;
                }
            }
        };
    }

}
#endif

二,日志等级类设计

 首先我们需要明确划分日志等级的目的,就是在输出时按照等级进行过滤输出,也就是说每一个项目都会设置一个默认的输出等级,只有输出的日志等级大于等于默认输出等级才会输出。

而日志等级类有下面两个功能

1.使用枚举类的方法定义出所有的输出等级

 

 等级如上所示,这里有一个问题为什么OFF可以关闭日志?当我们将默认输出等级设计成OFF时,此时只有等级大于等于OFF的信息可以输出,但是OFF等级是最大的,这样日志的输出就被关闭了。

2.提供一个接口,将对应的枚举等级转换成字符串

DEBUG ->"DEBUG"

模块代码如下

#ifndef _M_LEVEL_H_
#define _M_LEVEL_H_

#include <iostream>

namespace mjwlog
{
    class LogLevel
    {
        public:
        enum class level
        {
            UNKNOW=0, //未知
            DEBUG,    //调试
            INFO,     //提示
            WARN,     //警告
            ERROR,    //错误
            FATAL,    //致命
            OFF       //关闭日志
        };

        static const char* LeveltoString(LogLevel::level l)
        {
            switch(l)
            {
                case LogLevel::level::DEBUG:return "DEBUG";
                case LogLevel::level::INFO:return "INFO";
                case LogLevel::level::WARN:return "WARN";
                case LogLevel::level::ERROR:return "ERROR";
                case LogLevel::level::FATAL:return "FATAL";
                case LogLevel::level::OFF:return "OFF";
            }

            return "UNKNOW";
        }


    };
}
#endif

测试:

 三,日志消息类设计

意义:定义出一条日志存储时所需要的各项要素,同时完成该类构造

日志信息的关键要素
关键要素作用
时间用来过滤日志输出时间
等级过滤日志信息,多等级输出
源文件名称快速定位错误出现的位置
源代码行号快速定位错误出现的位置
线程ID快速定位错误出现的线程
日志器名称支持多日志器共同使用,因此日志器信息也需要过滤
实际日志主题信息主题信息

 代码如下:

#ifndef _M_MSG_H_
#define _M_MSG_H_

/* 
    时间	            用来过滤日志输出时间
    等级	            过滤日志信息,多等级输出
    源文件名称	        快速定位错误出现的位置
    源代码行号	        快速定位错误出现的位置
    线程ID	            快速定位错误出现的线程
    日志器名称	        支持多日志器共同使用,因此日志器信息也需要过滤
    实际日志主题信息	 主题信息
*/
#include <iostream>
#include <thread>
#include "level.hpp"
#include "util.hpp"


namespace mjwlog
{
    struct message//struct方便访问类内成员
    {
        size_t _time;   //时间
        size_t _line;   //行号
        LogLevel::level _level; //等级
        std::thread::id _id;    //线程id
        std::string _filename;  //文件名
        std::string _logger;    //日志器名称
        std::string _msg;       //主体信息

        //构造
        message(size_t line,
                LogLevel::level level,
                std::string filename,
                std::string logger,
                std::string msg,
                size_t time=util::gettime::nowtime())
                :_time(time),
                _line(line),
                _level(level),
                _id(std::this_thread::get_id()),
                _filename(filename),
                _logger(logger),
                _msg(msg)
        {}

    };
}
#endif

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值