Linux-C 简单的C语言日志库

一、简述

        记--C语言实现的简单的日志库,可循环覆盖滚动记录日志文件,达到限制就另记一个日志文件,可控制日志文件个数,可控制日志文件大小。

打包下载:外链:https://wwm.lanzouv.com/b0cazvkwb 密码:de1r

二、测试代码

clog.h文件

/** clog.h**  Created on: 2022-6-11*      Author: liang*/#ifndef _CLOG_H_
#define _CLOG_H_#ifdef __cplusplus
extern "C" {
#endif#include <limits.h>typedef enum {CLOG_ACK_FAIL = -1,       //操作失败CLOG_ACK_OK = 0,     //操作成功
} CLogAck_e;typedef struct {int fd;int fileCnt;         //滚动记录多少个日志文件, 如5个日志文件 a.log(当前正在记录的文件) a.log.1 a.log.2 a.log.3 a.log.4 按时间排序, 最新-->最旧unsigned int currSize;  //用户无需关心,当前日志文件大小unsigned int maxSize;   //一个日志文件的大小,满了之后另记一个文件char path[PATH_MAX];   //用户无需关心,日志文件路径int bufSize;          //每次写入日志数据最大的大小,void *buf;               //用户无需关心, 每次写入日志数据的缓冲区
} CLogger_t;/******************************************
* 函数: CLogInitLogger
* 功能: 初始化日志记录器
* 参数: CLogger_t *logger:
*       const char* path:
* 输入:
* 输出:
* 返回: int 成功返回:CLOG_ACK_OK;其它返回:
* 说明: @xxx 2022.06.12 周日
******************************************/
CLogAck_e CLogInitLogger(CLogger_t *logger, const char* path);/******************************************
* 函数: CLogUninitLogger
* 功能: 释放日志记录器
* 参数: CLogger_t *logger:
* 输入:
* 输出:
* 返回: void
* 说明: @xxx 2022.06.12 周日
******************************************/
void CLogUninitLogger(CLogger_t *logger);/******************************************
* 函数: CLog
* 功能: 记录日志信息接口
* 参数: CLogger_t *logger:
*       const char *fmt:
*       ...:
* 输入:
* 输出:
* 返回: int 成功返回:写入字节数;其它返回:
* 说明: @xxx 2022.06.12 周日
******************************************/
int CLog(CLogger_t *logger, const char *fmt, ...);#ifdef __cplusplus
}
#endif#endif /* _CLOG_H_ */

clog.c文件

/** clog.c**  Created on: 2022-6-11*      Author: liang*/#include <fcntl.h>
#include <sys/types.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include "clog.h"#if 1
#define LOGD(fmt, args...)   printf("[%s-%s-%d] " fmt, __FILE__, __func__, __LINE__, ##args)
#define LOGE(info) perror(info)
#else
#define LOGD(fmt, args...)
#define LOGE(info)
#endif//滚动日志文件,达到限制就另记一个日志文件
static void RollLogFile(CLogger_t *logger)
{int i;off_t size;if (logger->currSize >= logger->maxSize) {LOGD("currSize:%u, maxSize=%u\r\n", logger->currSize, logger->maxSize);//再次大小确认size = lseek(logger->fd, 0, SEEK_END);logger->currSize = (unsigned int)size>=0?size:0;if (logger->currSize < logger->maxSize) {return;}//开始滚动日志char file1[PATH_MAX] = {0};char file2[PATH_MAX] = {0};for (i = logger->fileCnt-2; 0 < i; i--) {snprintf(file1, sizeof(file1), "%s.%d", logger->path, i);snprintf(file2, sizeof(file2), "%s.%d", logger->path, i+1);if (F_OK == access(file2, F_OK)) {unlink(file2);LOGD("unlink %s\r\n", file2);}rename(file1, file2);//rename重命名不会更改文件的修改时间LOGD("rename %s %s\r\n", file1, file2);}snprintf(file2, sizeof(file2), "%s.1", logger->path);if (F_OK == access(file2, F_OK)) {unlink(file2);LOGD("unlink %s\r\n", file2);}if (0 <= logger->fd) {close(logger->fd);logger->fd = -1;}rename(logger->path, file2);LOGD("rename %s %s\r\n", logger->path, file2);logger->currSize = 0;logger->fd = open(logger->path, O_CREAT|O_RDWR|O_APPEND, 0666);}
}//初始化日志记录器
CLogAck_e CLogInitLogger(CLogger_t *logger, const char* path)
{
#define DEFAULT_LOG_FILE_COUNT      5
#define DEFAULT_LOG_ONE_FILE_SIZE   (2*1024*1024)   //2M
#define DEFAULT_LOG_BUF_MAX_LEN     (2048)int fd;off_t size;fd = open(path, O_CREAT|O_RDWR|O_APPEND, 0666);if (0 > fd) {LOGE("open fail error:");return CLOG_ACK_FAIL;}logger->bufSize = (0 >= logger->bufSize)?DEFAULT_LOG_BUF_MAX_LEN:logger->bufSize;logger->buf = malloc(logger->bufSize);if (NULL == logger->buf) {LOGD("malloc fail\r\n");close(fd);return CLOG_ACK_FAIL;}size = lseek(fd, 0, SEEK_END);logger->fd = fd;logger->fileCnt = (0 >= logger->fileCnt)?DEFAULT_LOG_FILE_COUNT:logger->fileCnt;logger->maxSize = (0 >= logger->maxSize)?DEFAULT_LOG_ONE_FILE_SIZE:logger->maxSize;logger->currSize = (unsigned int)size>=0?size:0;memset(logger->path, 0x0, sizeof(logger->path));strncpy(logger->path, path, sizeof(logger->path));RollLogFile(logger);return CLOG_ACK_OK;
}//释放日志记录器
void CLogUninitLogger(CLogger_t *logger)
{if (0 < logger->fd) {close(logger->fd);logger->fd = -1;}if (NULL != logger->buf) {free(logger->buf);}memset(logger, 0x0, sizeof(CLogger_t));
}//记录日志信息接口
int CLog(CLogger_t *logger, const char *fmt, ...)
{int wLen;int buf_len;int tmp_len;time_t timep = {0};struct tm tmTime = {0};time(&timep);gmtime_r(&timep, &tmTime);snprintf(logger->buf, logger->bufSize, "#%02d-%02d-%02d %02d:%02d:%02d->",(1900+tmTime.tm_year), tmTime.tm_mon+1, tmTime.tm_mday,tmTime.tm_hour, tmTime.tm_min, tmTime.tm_sec);buf_len = strlen(logger->buf);va_list arglist;va_start(arglist, fmt);wLen = vsnprintf((char*)logger->buf+buf_len, logger->bufSize-buf_len, fmt, arglist);va_end(arglist);if (0 < wLen) {buf_len += wLen;} else {wLen = buf_len;}tmp_len = logger->maxSize - logger->currSize;//剩余空间, 可能会分两次写入if (0 < tmp_len && buf_len > tmp_len) {wLen = tmp_len;}wLen = write(logger->fd, logger->buf, wLen);if (0 < wLen) {logger->currSize += wLen;tmp_len = wLen;//记录已写入字节wLen = buf_len - wLen;RollLogFile(logger);if (0 < wLen) {//还有要写入的wLen = write(logger->fd, (char*)logger->buf+tmp_len, wLen);if (0 < wLen) {logger->currSize += wLen;wLen += tmp_len;}RollLogFile(logger);}} else {RollLogFile(logger);}return wLen;
}

demo.c文件

#include <stdio.h>
#include <time.h>
#include "clog.h"int main(int argc, char *argv[])
{int ret;int count = 50;//配置最多记录多少个日志文件,每个日志文件大小CLogger_t logger = {.fileCnt = 5,     //5个日志文件.maxSize = 1024,   //每个日志文件大小};//初始化日志记录器ret = CLogInitLogger(&logger, "test.log");if (CLOG_ACK_OK != ret) {printf("CLogInitLogger fail, ret:%d\r\n", ret);return -1;}//测试写日志    while (count--) {CLog(&logger, "Hello CLog! time: %ld, count: %d\r\n", time(NULL), count);}//释放日志记录器CLogUninitLogger(&logger);return 0;
}

三、测试结果

编译:gcc demo.c clog.c -o demo -Wall

测试例子:最多记录5个日志文件,每个日志文件1024字节。test.log日志为当前正在记录的日志。

Linux-C 简单的C语言日志库相关推荐

  1. 【C/C++开源库】单片机/嵌入式中的C语言日志库

    日志系统在系统开发和调整过程中的重要性,大家应该都清楚,特别是项目出问题之后,却没有日志可以帮忙定位问题,就非常令人痛苦. 因为我们不可能一直通过调试器去单步调试程序,所以设备的运行日志显得尤为重要. ...

  2. 【CC++开源库】单片机嵌入式中的C语言日志库

    日志系统在系统开发和调整过程中的重要性,大家应该都清楚,特别是项目出问题之后,却没有日志可以帮忙定位问题,就非常令人痛苦. 因为我们不可能一直通过调试器去单步调试程序,所以设备的运行日志显得尤为重要. ...

  3. Go语言日志库zerolog

    Go语言日志库zerolog 在开发大型项目时,将日志进行结构化以提高可读性.可查询性和速度是非常重要的. 为什么你选择不使用其他结构化日志库,如logrus或zap? Zerolog 是一款高性能且 ...

  4. linux 系统常用的C语言函数库

    2019独角兽企业重金招聘Python工程师标准>>> pkg-config --list-all  查看系统己安装库(yum install pkgconfig   sudo ap ...

  5. 日志库 winston 的学习笔记 - 创建一个使用 winston 的 Node.js 应用

    winston 被设计为一个简单且通用的日志库,支持多种传输. 传输本质上是日志的存储设备. 每个 winston 记录器都可以在不同级别配置多个存储渠道.例如,人们可能希望将错误日志存储在持久的远程 ...

  6. Rust应用调用C语言动态库

    外部功能接口FFI 虽然高级(脚本)编程语言的功能丰富,表达能力强,但对底层的一些特殊操作的支持并不完善,就需要以其他编程语言来实现.调用其他编程语言的接口,被称为Foreign Function I ...

  7. go 日志库 zap

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.zap是什么? 二.使用步骤 1.基本使用 2.写入文件 前言 zap日志 Zap提供了两种类型的日志记录器-Su ...

  8. 基于Linux C的简单日志库

    最近由于接手了几个小的开发项目,一直苦于寻找一个调用简单,方便调试,占用资源小的日志库,因为我大部分的嵌入式开发项目都是C/C++的开发.就想着做一个小的日志调用接口C/C++库.最近有时间整理一下. ...

  9. 基于C语言Ncurse库和链表的简单贪吃蛇小游戏

    参考:基于C语言Ncurse库和链表的简单贪吃蛇小游戏 作者:三速何时sub20 发布时间:2020-09-29 10:23:51 网址:https://blog.csdn.net/weixin_44 ...

最新文章

  1. 2个月精通Python爬虫——3大爬虫框架+6场实战+分布式爬虫,包教包会
  2. python爬虫简单实例-最简单的Python爬虫案例,看得懂说明你已入门,附赠教程
  3. 【Python基础】Python 面向对象编程(上篇)
  4. MT6580启动流程
  5. (转)字典树原理+实现
  6. Java IO7:管道流、对象流
  7. SizeOf相关代码
  8. 面料经纬向、正反面判别方法
  9. 少年,别再收藏文章了!
  10. js,jquery的数字型字符串变量比较大小
  11. 【c语言课程设计】C语言校园卡管理系统
  12. 基于Systemview的巴克码识别器设计
  13. 系统建模与仿真 - 电子书下载(高清版PDF格式+EPUB格式)
  14. 扩展有限元程序matlab,Abaqus中扩展有限元(XFEM)功能简介
  15. 取整函数access_ACCESS常用函数总结
  16. Visual Studio Code安装及设置
  17. Javascript前端模块化
  18. 【UE4】WebUI插件实现HTML透明区域事件穿透响应
  19. 为马来西亚航空失联飞机祈福~~
  20. 一种计算标准差的高效方法:Welford迭代法

热门文章

  1. 一键批量PDF转换成图片文件
  2. 计算机操作系统学习笔记 第一章、操作系统概论
  3. MSDC 4.3 接口规范(5)
  4. WIN10 x64搭建OLLVM4.0 android NDK 编译环境跨坑指南
  5. 【demo记录】百度地图获取当前所在城市
  6. DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver File List
  7. Java将汉字转为拼音
  8. 2021南昌市地区高考成绩排名查询,2021南昌中小学国编成绩排名/分数线
  9. STM32怎样实现延时?
  10. html背景斜线,巧妙的实现 CSS 斜线