1.系统简介

该C风格简易log日志系统,适合与Linux平台系统,主要用于格式化输出日志到本地指定的文件中,可指定log文件数目、最大大小、行数、按时间切换等功能,可满足基本的log日志功能。从项目中提炼出来,附上使用的demo,简单易懂,能快速上手。具体接口说明,参见源码。

源文件也可以到github下载,地址:CEasyLocalLog。

2.源码

2.1头文件localLog.h

#ifndef _LOCALLOG_H_
#define _LOCALLOG_H_#include <stdio.h>
#include <time.h>typedef struct
{FILE *pLogFile;char sBaseFileName[80]; //log文件名前缀char sLogFileName[80];  //log文件名int iShiftType;         //0 -> 大小,  1 -> 文件数, 2 -> shift by interval, 3 ->天, 4 -> 小时, 5 ->分钟int iMaxLogNum;         //log文件最大个数int lMaxSize;           //单个log文件最大大小,单位Byteint lMaxCount;          //单个log文件最大行数,单位lineint lLogCount;          //当前log文件行数,单位linetime_t lLastShiftTime;  //上一次切换时间,单位s
}OI_LogFile;// @brief   OI_InitLogFile: 初始化log
// @param   pstLogFile: log结构指针
// @param   sLogBaseName: Log文件名的前缀字符串
// @param   iShiftType: log文件切换类型,
//      0->shift by size, when size > iMAX bytes
//      1->shift by LogCount, when logcount > iMAX lines
//      2->shift by interval, when elapse seconds > iMAX sec.
//      3->shift by day,
//      4->shift by hour
//      5->shift by minute
//      6->shift by day, log filename append with date.
//
// @param   iMaxLogNum: 切换log文件的最大个数. 当iShiftType=6时无意义。
// @param   iMAX: 如果iShiftType为0/1/2,那么表示当前log文件单位到达iMAX时进行切换,否则无意义。
// @return  成功返回0,失败 < 0
int OI_InitLogFile(OI_LogFile * pstLogFile, char *sLogBaseName, int iShiftType, int iMaxLogNum, int iMAX);//
//@brief:   Log string to logfile.
//@param:   pstLogFile:log结构指针
//          iLogTime:0 = do not log time, 1 = log simple time, 2 = log detail time
//          sFormat:C string pointed by format to the logfile,format may include format specifiers
//          ...:可变参数
//@return:  <0 means failure
//@ps:__attribute__ ((format (printf, 3, 4))):提示编译器,对这个函数的调用需要像printf一样,用对应的format字符串来check可变参数的数据类型。3和4对应函数第3和第4个形参
int OI_Log(OI_LogFile * pstLogFile, int iLogTime, const char *sFormat, ...) __attribute__ ((format (printf, 3, 4)));#endif

2.2源文件localLog.cpp

#include "localLog.h"#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/time.h>#include <string.h>
#include <errno.h>
#include <stdarg.h>//
//获取时间相关函数
//
char * OI_GetShortDateStr(const time_t * mytime)
{static char s[50];struct tm curr = *localtime(mytime);if(curr.tm_year > 50)snprintf(s, sizeof(s), "%04d%02d%02d", curr.tm_year + 1900, curr.tm_mon + 1, curr.tm_mday);elsesnprintf(s, sizeof(s), "%04d%02d%02d", curr.tm_year + 2000, curr.tm_mon + 1, curr.tm_mday);return s;
}static char* OI_GetDateTimeStr(const time_t * mytime)
{static char s[50];struct tm curr = *localtime(mytime);if(curr.tm_year > 50)snprintf(s, sizeof(s), "%04d-%02d-%02d %02d:%02d:%02d", curr.tm_year + 1900, curr.tm_mon + 1, curr.tm_mday, curr.tm_hour, curr.tm_min, curr.tm_sec);elsesnprintf(s, sizeof(s), "%04d-%02d-%02d %02d:%02d:%02d", curr.tm_year + 2000, curr.tm_mon + 1, curr.tm_mday, curr.tm_hour, curr.tm_min, curr.tm_sec);return s;
}static char * OI_GetCurShortDateStr(void)
{time_t mytime = time(NULL);return OI_GetShortDateStr(&mytime);
}static char * OI_GetCurDateTimeStr(void)
{time_t mytime = time(NULL);return OI_GetDateTimeStr(&mytime);
}static int ShiftFiles(OI_LogFile * pstLogFile)
{struct stat stStat;char sLogFileName[300];char sNewLogFileName[300];int i;struct tm stLogTm, stShiftTm;if (pstLogFile->iShiftType == 6)return 0;snprintf(sLogFileName,sizeof(sLogFileName),"%s.log", pstLogFile->sBaseFileName);if(stat(sLogFileName, &stStat) < 0) {if (errno == ENOENT) {FILE *pfile;if ((pfile = fopen(sLogFileName, "a+")) == NULL) return -1;fclose(pfile);if (stat(sLogFileName, &stStat) < 0)return -1;} else {return -1;}}switch (pstLogFile->iShiftType){case 0:if(stStat.st_size < pstLogFile->lMaxSize)return 0;break;case 2:if(stStat.st_mtime - pstLogFile->lLastShiftTime < pstLogFile->lMaxCount)return 0;break;case 3:if(pstLogFile->lLastShiftTime - stStat.st_mtime > 86400)break;memcpy(&stLogTm, localtime(&stStat.st_mtime), sizeof(stLogTm));memcpy(&stShiftTm, localtime(&pstLogFile->lLastShiftTime), sizeof(stShiftTm));if(stLogTm.tm_mday == stShiftTm.tm_mday)return 0;break;case 4:if(pstLogFile->lLastShiftTime - stStat.st_mtime > 3600)break;memcpy(&stLogTm, localtime(&stStat.st_mtime), sizeof(stLogTm));memcpy(&stShiftTm, localtime(&pstLogFile->lLastShiftTime), sizeof(stShiftTm));if(stLogTm.tm_hour == stShiftTm.tm_hour)return 0;break;case 5:if(pstLogFile->lLastShiftTime - stStat.st_mtime > 60)break;memcpy(&stLogTm, localtime(&stStat.st_mtime), sizeof(stLogTm));memcpy(&stShiftTm, localtime(&pstLogFile->lLastShiftTime), sizeof(stShiftTm));if(stLogTm.tm_min == stShiftTm.tm_min)return 0;break;default:if(pstLogFile->lLogCount < pstLogFile->lMaxCount)return 0;pstLogFile->lLogCount = 0;}for(i = pstLogFile->iMaxLogNum - 2; i >= 0; i--){if(i == 0)snprintf(sLogFileName,sizeof(sLogFileName),"%s.log", pstLogFile->sBaseFileName);elsesnprintf(sLogFileName,sizeof(sLogFileName),"%s%d.log", pstLogFile->sBaseFileName, i);if(access(sLogFileName, F_OK) == 0){snprintf(sNewLogFileName,sizeof(sNewLogFileName),"%s%d.log", pstLogFile->sBaseFileName, i + 1);if(rename(sLogFileName, sNewLogFileName) < 0){return -1;}}}time(&pstLogFile->lLastShiftTime);return 0;
}//@brief:初始化LOG对象
int OI_InitLogFile(OI_LogFile* pstLogFile, char *sLogBaseName, int iShiftType, int iMaxLogNum, int iMAX)
{memset(pstLogFile, 0, sizeof(OI_LogFile));strncat(pstLogFile->sLogFileName, sLogBaseName, sizeof(pstLogFile->sLogFileName) - 10);strcat(pstLogFile->sLogFileName, ".log");strncpy(pstLogFile->sBaseFileName, sLogBaseName, sizeof(pstLogFile->sBaseFileName) - 15);pstLogFile->iShiftType = iShiftType;pstLogFile->iMaxLogNum = iMaxLogNum;pstLogFile->lMaxSize = iMAX;pstLogFile->lMaxCount = iMAX;pstLogFile->lLogCount = iMAX;time(&pstLogFile->lLastShiftTime);return ShiftFiles(pstLogFile);
}int OI_Log(OI_LogFile * pstLogFile, int iLogTime,const char *sFormat, ...)
{va_list ap;struct timeval stLogTv;if (pstLogFile->iShiftType == 6) {snprintf(pstLogFile->sLogFileName, sizeof(pstLogFile->sLogFileName), "%s_%s.log", pstLogFile->sBaseFileName, OI_GetCurShortDateStr());}if((pstLogFile->pLogFile = fopen(pstLogFile->sLogFileName, "a+")) == NULL)return -1;va_start(ap, sFormat);if(iLogTime == 1){fprintf(pstLogFile->pLogFile, "[%s] ", OI_GetCurDateTimeStr());}else if(iLogTime == 2){gettimeofday(&stLogTv, NULL);fprintf(pstLogFile->pLogFile, "[%s.%.6d] ", OI_GetDateTimeStr((const time_t *) &(stLogTv.tv_sec)), (int) stLogTv.tv_usec);}vfprintf(pstLogFile->pLogFile, sFormat, ap);fprintf(pstLogFile->pLogFile, "\n");va_end(ap);pstLogFile->lLogCount++;fclose(pstLogFile->pLogFile);return ShiftFiles(pstLogFile);
}

2.3使用示例demo.cpp

/*
*@brief:C风格简易log系统使用demo
*@author:dablelv,1589276509@qq.com
*@date:20171207
*/#include "localLog.h"//定义三个级别LOG
OI_LogFile stErrorLog;      //错误日志
OI_LogFile stDebugLog;      //调试日志
OI_LogFile stEventLog;      //流水日志//宏定义调用log函数
//ps:_args_...:GCC支持的可变参数名;"##对符号进行连接,如果_args_为空,则不进行连接,使函数宏可省略可变参数
#define ErrorLog(_fmt_, _args_...) do{ OI_Log(&stErrorLog, 2, _fmt_, ##_args_); } while (0)
#define DebugLog(_fmt_, _args_...) do{ OI_Log(&stDebugLog, 2, _fmt_, ##_args_); } while (0)
#define EventLog(_fmt_, _args_...) do{ OI_Log(&stEventLog, 2, _fmt_, ##_args_); } while (0)int main(int argc,char* argv[])
{//初始化logFile//保留最多10个log文件,每个最大大小约为100MBOI_InitLogFile(&stErrorLog,"/home/dablelv/test/logSys/log/error",0,10,100000000);OI_InitLogFile(&stDebugLog,"/home/dablelv/test/logSys/log/debug",0,10,100000000);OI_InitLogFile(&stEventLog,"/home/dablelv/test/logSys/log/event",0,10,100000000);//向log文件写日志ErrorLog("this is error log");ErrorLog("this is error log whith %s","argument");DebugLog("this is debug log");DebugLog("this is debug log whith %s","argument");EventLog("this is event log");EventLog("this is event log whith %s","argument");
}

3.C++风格的简易log系统

除了上面C风格的log系统,还有一款C++风格的log系统可供使用,参见本人的另一篇博文:C++实现简易log日志系统。

后续将总结提炼出一款远程log系统分享给大家,支持将日志输出到指定的远程主机。

C风格简易本地log系统相关推荐

  1. WebRTC 的 log 系统实现分析

    WebRTC 有多套 log 输出系统,一套位于 webrtc/src/base 下,包括 webrtc/src/base/logging.h 和 webrtc/src/base/logging.cc ...

  2. 利用 CocoaLumberjack 搭建自己的 Log 系统

    2019独角兽企业重金招聘Python工程师标准>>> 先说下需求,我理想中的 Log 系统需要: 可以设定 Log 等级 可以积攒到一定量的 log 后,一次性发送给服务器,绝对不 ...

  3. netty 基于 protobuf 协议 实现 websocket 版本的简易客服系统

    https://segmentfault.com/a/1190000017464313 netty 基于 protobuf 协议 实现 websocket 版本的简易客服系统 结构 netty 作为服 ...

  4. Android_8.1 Log 系统源码分析

    文章目录 0x01 [Android Log框架推荐](https://www.jianshu.com/p/64b63e51fd4c) 1. [logger](https://github.com/o ...

  5. AndroidT(13) Log 系统 -- C 语言格式的LOG输出(一)

    1.概览   c语言中的printf我想大家都非常的熟悉了,他的基本格式如下 int printf(const char *format, ...);   前半部分 format 指向的字符串用于描述 ...

  6. AndroidT(13) Log 系统 -- C plus plus 语言格式的LOG输出(二)

    1.概览   上一章提到的是在Android系统中,以C语言格式方式进行log输出.本章就来讲讲c++语言格式的. std::cout<<"This is a c++ log&q ...

  7. 搭建一个简易的发布系统

    为了解决 博客 写作环境限制的问题,尝试搭建了一个简易的发布系统.Git 仓库只是托管 md 文件,通过 Webhook 通知服务器更新 md 文件,然后执行构建静态文件操作,完成一个发布过程. 需求 ...

  8. 用dedecms自定义表单创建简易自助预约系统

    建站往往需要根据客户的需求来增加相应的功能,比如预约.平时用比较多的是织梦系统,那么如何用dedecms自定义表单创建简易自助预约系统呢? 进入dedecms后台,左侧菜单中依次点击"核心& ...

  9. 简易的CRM系统案例之SpringMVC+JSP+MySQL+hibernate框架版本

    继续对上一版本进行改版,变成SpringMVC框架 简易的CRM系统案例之易的CRM系统案例之JSP+MySQL+SSH框架版本 src/spring.xml <?xml version=&qu ...

最新文章

  1. es mysql 预处理_数据库选型之MySQL vs ElasticSearch
  2. Java基础班学习笔记(15)GUI图形界面编程
  3. 你的项目应该如何正确分层?
  4. JDBC数据源(DataSource)的简单实现
  5. Android tombstone文件是如何生成的
  6. 数据结构实验C语言实现版
  7. 上市融资计划书PPT模板
  8. WordPress文章/页面浏览量计数器插件Post Views Counter
  9. c/c++实现带图形界面的扫雷游戏
  10. python首字母大写
  11. c++ zlib加密压缩文件详细介绍与代码演示
  12. 【论文精读】TACRED Revisited: A Thorough Evaluation of the TACRED Relation Extraction Task
  13. WHQL认证如何给驱动程序做数字签名
  14. 100% 解决 VMware Workstation 与 Hyper-V 不兼容。请先从系统中移除 Hyper-V 角色
  15. linux搭建网站教程详解
  16. Django-APIView
  17. Flink及Storm、Spark主流流框架比较-实时框架比较
  18. vba传值调用_VBA 过程和函数:传递参数教程和实例
  19. HMAC-SHA1签名认证算法
  20. php文件上传限制后缀,input file上传文件扩展名限制

热门文章

  1. 开源自动化服务器软件 Jenkins 被曝严重漏洞,可泄露敏感信息
  2. 利用VisualVm和JMX远程监控K8S里的Java进程
  3. vue-cli 使用Mint-UI
  4. linux下对进程按照内存使用情况进行排序
  5. 10. 我的第一个Java应用程序
  6. 开机后系统时间被恶意修改
  7. 开源日志系统log4cplus(三)
  8. 理解一个名词:用户代理(user agent)
  9. 用vlc搭建简单流媒体服务器(UDP和TCP方式)-转 rtsp很慢才能显示
  10. windows-sock-简单例子-转