1.log日志的作用

在软件开发周期中,不管是前台还是后台,系统一般会采用一个持久化的日志系统来记录运行情况。

在代码中嵌入log代码信息,主要记录下列信息:

(1)记录系统运行异常信息。

(2)记录系统运行状态信息。

(3)记录系统运行性能指标。

通过对上述信息分析和诊断,我们能采取正确的手段来提高系统质量和系统性能。由此可见log日志在系统中的重要地位和存在的必要性。

2.log日志的类型与级别

2.1日志的类型

主要分三大类:

安全类信息:记录系统边界交互行为和信息;

业务类信息:记录系统内部业务处理行为和信息;

性能类信息:记录系统硬件对业务处理的支撑能力。

2.2日志的级别

一般分五级:

ERROR(错误):此信息输出后,主体系统核心模块不能正常工作,需要修复才能正常工作。

WARN(警告):此信息输出后,系统一般模块存在问题,不影响系统运行。

INFO(通知):此信息输出后,主要是记录系统运行状态等关联信息。

DEBUG(调试):最细粒度的输出,除却上面各种情况后,你希望输出的相关信息,都可以在这里输出。

TRACE(跟踪):最细粒度的输出,除却上面各种情况后,你希望输出的相关信息,都可以在这里输出。

在本文实现的简单日志系统中不包括DEBUG和TRACE。DEBUG在编码过程中进行,TRACE不太需要。

2.3常见的开源log工具

         C/C++实现的开源log常见有:C++版的log4j 的log4cplus、快速的 C++ 日志库——spdlog、纯C日志函数库 ——zlog、C++日志框架——GoogleGlog等。

其中开源log工具log4cplus在项目中的使用较为常见,具体用法和源码请参考网络的资源,不再赘述。

3.自实现log工具

主要针对ERROR(错误)、WARN(警告)和INFO(通知)这三种日志类型实现了如下的C++简易log工具。由源文件(logger.cpp)和头文件(logger.h)组成。源码如下。

logger.h文件:

/**\logger.h*\brief 日记模块*/#ifndef  __logger__
#define  __logger__#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cstdlib>
#include <stdint.h>///
/// \brief 日志文件的类型
///
typedef enum log_rank {INFO,WARNING,ERROR,FATAL
}log_rank_t;///
/// \brief 初始化日志文件
/// \param info_log_filename 信息文件的名字
/// \param warn_log_filename 警告文件的名字
/// \param error_log_filename 错误文件的名字
void initLogger(const std::string&info_log_filename,const std::string&warn_log_filename,const std::string&error_log_filename);///
/// \brief 日志系统类
///
class Logger {friend void initLogger(const std::string& info_log_filename,conststd::string& warn_log_filename,conststd::string& erro_log_filename);public://构造函数Logger(log_rank_t log_rank) : m_log_rank(log_rank) {};~Logger();   ////// \brief 写入日志信息之前先写入的源代码文件名, 行号, 函数名/// \param log_rank 日志的等级/// \param line 日志发生的行号/// \param function 日志发生的函数static std::ostream& start(log_rank_t log_rank,const int32line,conststd::string& function);private:////// \brief 根据等级获取相应的日志输出流///static std::ostream& getStream(log_rank_t log_rank);static std::ofstream m_info_log_file;                   ///< 信息日子的输出流static std::ofstream m_warn_log_file;                  ///< 警告信息的输出流static std::ofstream m_error_log_file;                  ///< 错误信息的输出流log_rank_t m_log_rank;                             ///< 日志的信息的等级
};///
/// \brief 根据不同等级进行用不同的输出流进行读写
///
#define LOG(log_rank)   \
Logger(log_rank).start(log_rank, __LINE__,__FUNCTION__)///
/// \brief 利用日记进行检查的各种宏
///
#define CHECK(a)                                            \if(!(a)) {                                              \LOG(ERROR) << " CHECK failed " << endl              \<< #a << "= " << (a) << endl;          \abort();                                            \}                                                      \#define CHECK_NOTNULL(a)                                    \if( NULL == (a)) {                                      \LOG(ERROR) << " CHECK_NOTNULL failed "              \<< #a << "== NULL " << endl;           \abort();                                            \}#define CHECK_NULL(a)                                       \if( NULL != (a)) {                                      \LOG(ERROR) << " CHECK_NULL failed " << endl         \<< #a << "!= NULL " << endl;           \abort();                                            \}#define CHECK_EQ(a, b)                                      \if(!((a) == (b))) {                                     \LOG(ERROR) << " CHECK_EQ failed "  << endl          \<< #a << "= " << (a) << endl           \<< #b << "= " << (b) << endl;          \abort();                                            \}#define CHECK_NE(a, b)                                      \if(!((a) != (b))) {                                     \LOG(ERROR) << " CHECK_NE failed " << endl           \<< #a << "= " << (a) << endl           \<< #b << "= " << (b) << endl;          \abort();                                            \}#define CHECK_LT(a, b)                                      \if(!((a) < (b))) {                                      \LOG(ERROR) << " CHECK_LT failed "                   \<< #a << "= " << (a) << endl           \<< #b << "= " << (b) << endl;          \abort();                                            \}#define CHECK_GT(a, b)                                      \if(!((a) > (b))) {                                      \LOG(ERROR) << " CHECK_GT failed "  << endl          \<< #a <<" = " << (a) << endl            \<< #b << "= " << (b) << endl;          \abort();                                            \}#define CHECK_LE(a, b)                                      \if(!((a) <= (b))) {                                     \LOG(ERROR) << " CHECK_LE failed "  << endl          \<< #a << "= " << (a) << endl           \<< #b << "= " << (b) << endl;          \abort();                                            \}#define CHECK_GE(a, b)                                      \if(!((a) >= (b))) {                                     \LOG(ERROR) << " CHECK_GE failed "  << endl          \<< #a << " = "<< (a) << endl            \<< #b << "= " << (b) << endl;          \abort();                                            \}#define CHECK_DOUBLE_EQ(a, b)                               \do {                                                    \CHECK_LE((a), (b)+0.000000000000001L);              \CHECK_GE((a), (b)-0.000000000000001L);              \}while (0)#endif

logger.cpp文件源码:

#include "logger.h"
#include <cstdlib>
#include <ctime>std::ofstream Logger::m_error_log_file;
std::ofstream Logger::m_info_log_file;
std::ofstream Logger::m_warn_log_file;void initLogger(const std::string&info_log_filename,const std::string&warn_log_filename,const std::string&error_log_filename){Logger::m_info_log_file.open(info_log_filename.c_str());Logger::m_warn_log_file.open(warn_log_filename.c_str());Logger::m_error_log_file.open(error_log_filename.c_str());
}std::ostream& Logger::getStream(log_rank_tlog_rank){return (INFO == log_rank) ?(m_info_log_file.is_open() ?m_info_log_file : std::cout) :(WARNING == log_rank ?(m_warn_log_file.is_open()? m_warn_log_file : std::cerr) :(m_error_log_file.is_open()? m_error_log_file : std::cerr));
}std::ostream& Logger::start(log_rank_tlog_rank,const int32 line,const std::string&function) {time_t tm;time(&tm);char time_string[128];ctime_r(&tm, time_string);return getStream(log_rank) << time_string<< "function (" << function << ")"<< "line " << line<<std::flush;
}Logger::~Logger(){getStream(m_log_rank) << std::endl << std::flush;if (FATAL == m_log_rank) {m_info_log_file.close();m_info_log_file.close();m_info_log_file.close();abort();}
}

使用方法如下:

第一步,通过给定三个日志文件的路径,调用初始化函数initLogger进行日志文件的创建。

第二步,在需要插入日志的地方调用LOG(TYPE)<<”yourinfo”;即可。your info表示你要输入到日志文件中的信息。

以WARN日志为例,输出的信息大致如下:

Sun Jul  5 09:49:48 2015function (getNextTask) line 75 no task to berunSun Jul  5 09:49:53 2015function (getNextTask) line 75 no task to berunSun Jul  5 09:49:58 2015function (getNextTask) line 75 no task to berunSun Jul  5 09:50:03 2015function (getNextTask) line 75 no task to berun

C++ 实现简易 log 日志系统相关推荐

  1. 客户端log日志系统

    背景 我们在开发过程中出现了个别bug,而我们往往很难定位到问题所在,这个不仅仅局限于移动端,只是移动端不容易定位问题.我们常见的实现方式可能是, 1. 创建一个带队列的线程. 2. 把要上报的数据抛 ...

  2. FFmpeg源码分析:log日志系统

    FFmpeg的封装专有的log日志系统,支持设置日志等级log level,也支持日志回调log callback,方便开发者调试与排查问题. 1.日志等级 log日志位于libavutil模块,lo ...

  3. C++实现log日志系统

    1.log日志的作用 在软件开发周期中,不管是前台还是后台,系统一般会采用一个持久化的日志系统来记录运行情况. 在代码中嵌入log代码信息,主要记录下列信息: (1)记录系统运行异常信息. (2)记录 ...

  4. DPDK 18 log日志系统使用

    概述: DPDK 日志系统分为1-8个等级,在lib/librte_eal/common/include/rte_log.h文件中定义,每个DPDK模块都可以定义一个预设日志输出等级,只有日志输出语句 ...

  5. LVGL misc log日志系统(lv_log.h)

    更多源码分析请访问:LVGL 源码分析大全 LVGL misc log日志系统目录 1.概述 2.API 2.1.日志级别 2.2.日志输出宏 3.使用方法 1.概述 LVGL的日志系统实现比较简单, ...

  6. Android Log日志系统

    目录 0. 前言 1. Native的Log写过程解析 2. Socket的另一端Logd 0. 前言 Android中 logd 详解_私房菜的博客-CSDN博客_logd 里面讲了Java层Log ...

  7. 基于C/C++的log日志记录等级系统

    目录 log日志系统初始化 log日志输出 禁止log日志输出 log日志关闭 log日志测试 log日志系统初始化 int logger_init(int loglevel) {time_t now ...

  8. webserver之日志系统

    前言 此博客记录对于TinyWebServer项目的学习,并根据自己的理解做出些许更改. 原项目地址:https://github.com/qinguoyi/TinyWebServer Log 日志系 ...

  9. linux日志系统的实现,一个同步日志系统的简单实现 log for c (linux 平台)

    在一个项目中需要使用日志记录,网上也有很多开源代码,自己也尝试着写了一个!异步日志系统正在进行中. //mylog.h 头文件 #ifndef _MYLOG_HEADER_ #define _MYLO ...

最新文章

  1. Java中的记录类型
  2. 2.2 理解 mini-batch 梯度下降法
  3. Apache双机热备
  4. 计算机组成原理作业三
  5. USB接口定义详解(图)
  6. 人声歌姬语音合成器+拓展-Yamaha Vocaloid 5.0.3 + Libraries WiN 免安装版
  7. CentOS等保三级安全加固方案
  8. JAVA 启动JVM时,Xms和Xmx参数
  9. 电脑麦克风可以录音但总有沙沙的声音如何解决
  10. 【时间轴】推荐几款jQuery时间轴插件Timeline
  11. catkin_make问题: The build space at ‘/home/lufeng/Documents/test/catkin_ws/build’ was previously built
  12. WiFi处显示红叉的解决办法
  13. matlab中文论坛有手机版吗,MATLAB中文论坛常见问题归纳
  14. LORA技术---LoRa信号从数据流变为LoRa扩频信号,再从射频信号通过解调变为数据
  15. 【超详细】数据结构总结及思维导图(王道考研)
  16. html中购物车图标,纯CSS3实现单元素购物车图标
  17. 线性代数学习笔记——行列式的性质及拉普拉斯定理——4. 行列式的性质1~性质3
  18. ad走线打过孔_AD过孔开窗输出Gerber文件步骤!
  19. 数据库的一些操作(Sql)
  20. 怎么利用网络赚钱?三步赚钱法分享给你!

热门文章

  1. AttackerKB:免费的众筹漏洞评估知识库
  2. 清除n天以前的日志文件以及mysql-bin文件
  3. 蓝桥杯 算法训练 区间k大数查询(水题)
  4. sql返回刚添加的数据的自增id
  5. 手动同步OCS的通讯簿
  6. Ansi,UTF8,Unicode编码
  7. 服务器子系统设备结构图,设备集中管理的方法、服务端和系统
  8. 蓝桥杯 ADV-155 算法提高 上帝造题五分钟
  9. 圣地亚哥分校 计算机,加州大学圣地亚哥分校计算机怎么样?
  10. JSONObject put,accumulate,element的区别