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日志为当前正在记录的日志。
|