[C.C++] Linux-C 简单的C语言日志库

543 0
Honkers 2025-3-11 09:04:43 | 显示全部楼层 |阅读模式

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

一、简述

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

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

二、测试代码

clog.h文件

  1. /*
  2. * clog.h
  3. *
  4. * Created on: 2022-6-11
  5. * Author: liang
  6. */
  7. #ifndef _CLOG_H_
  8. #define _CLOG_H_
  9. #ifdef __cplusplus
  10. extern "C" {
  11. #endif
  12. #include <limits.h>
  13. typedef enum {
  14. CLOG_ACK_FAIL = -1, //操作失败
  15. CLOG_ACK_OK = 0, //操作成功
  16. } CLogAck_e;
  17. typedef struct {
  18. int fd;
  19. int fileCnt; //滚动记录多少个日志文件, 如5个日志文件 a.log(当前正在记录的文件) a.log.1 a.log.2 a.log.3 a.log.4 按时间排序, 最新-->最旧
  20. unsigned int currSize; //用户无需关心,当前日志文件大小
  21. unsigned int maxSize; //一个日志文件的大小,满了之后另记一个文件
  22. char path[PATH_MAX]; //用户无需关心,日志文件路径
  23. int bufSize; //每次写入日志数据最大的大小,
  24. void *buf; //用户无需关心, 每次写入日志数据的缓冲区
  25. } CLogger_t;
  26. /******************************************
  27. * 函数: CLogInitLogger
  28. * 功能: 初始化日志记录器
  29. * 参数: CLogger_t *logger:
  30. * const char* path:
  31. * 输入:
  32. * 输出:
  33. * 返回: int 成功返回:CLOG_ACK_OK;其它返回:
  34. * 说明: @xxx 2022.06.12 周日
  35. ******************************************/
  36. CLogAck_e CLogInitLogger(CLogger_t *logger, const char* path);
  37. /******************************************
  38. * 函数: CLogUninitLogger
  39. * 功能: 释放日志记录器
  40. * 参数: CLogger_t *logger:
  41. * 输入:
  42. * 输出:
  43. * 返回: void
  44. * 说明: @xxx 2022.06.12 周日
  45. ******************************************/
  46. void CLogUninitLogger(CLogger_t *logger);
  47. /******************************************
  48. * 函数: CLog
  49. * 功能: 记录日志信息接口
  50. * 参数: CLogger_t *logger:
  51. * const char *fmt:
  52. * ...:
  53. * 输入:
  54. * 输出:
  55. * 返回: int 成功返回:写入字节数;其它返回:
  56. * 说明: @xxx 2022.06.12 周日
  57. ******************************************/
  58. int CLog(CLogger_t *logger, const char *fmt, ...);
  59. #ifdef __cplusplus
  60. }
  61. #endif
  62. #endif /* _CLOG_H_ */
复制代码

clog.c文件

  1. /*
  2. * clog.c
  3. *
  4. * Created on: 2022-6-11
  5. * Author: liang
  6. */
  7. #include <fcntl.h>
  8. #include <sys/types.h>
  9. #include <stdarg.h>
  10. #include <string.h>
  11. #include <time.h>
  12. #include <unistd.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include "clog.h"
  16. #if 1
  17. #define LOGD(fmt, args...) printf("[%s-%s-%d] " fmt, __FILE__, __func__, __LINE__, ##args)
  18. #define LOGE(info) perror(info)
  19. #else
  20. #define LOGD(fmt, args...)
  21. #define LOGE(info)
  22. #endif
  23. //滚动日志文件,达到限制就另记一个日志文件
  24. static void RollLogFile(CLogger_t *logger)
  25. {
  26. int i;
  27. off_t size;
  28. if (logger->currSize >= logger->maxSize) {
  29. LOGD("currSize:%u, maxSize=%u\r\n", logger->currSize, logger->maxSize);
  30. //再次大小确认
  31. size = lseek(logger->fd, 0, SEEK_END);
  32. logger->currSize = (unsigned int)size>=0?size:0;
  33. if (logger->currSize < logger->maxSize) {
  34. return;
  35. }
  36. //开始滚动日志
  37. char file1[PATH_MAX] = {0};
  38. char file2[PATH_MAX] = {0};
  39. for (i = logger->fileCnt-2; 0 < i; i--) {
  40. snprintf(file1, sizeof(file1), "%s.%d", logger->path, i);
  41. snprintf(file2, sizeof(file2), "%s.%d", logger->path, i+1);
  42. if (F_OK == access(file2, F_OK)) {
  43. unlink(file2);
  44. LOGD("unlink %s\r\n", file2);
  45. }
  46. rename(file1, file2);//rename重命名不会更改文件的修改时间
  47. LOGD("rename %s %s\r\n", file1, file2);
  48. }
  49. snprintf(file2, sizeof(file2), "%s.1", logger->path);
  50. if (F_OK == access(file2, F_OK)) {
  51. unlink(file2);
  52. LOGD("unlink %s\r\n", file2);
  53. }
  54. if (0 <= logger->fd) {
  55. close(logger->fd);
  56. logger->fd = -1;
  57. }
  58. rename(logger->path, file2);
  59. LOGD("rename %s %s\r\n", logger->path, file2);
  60. logger->currSize = 0;
  61. logger->fd = open(logger->path, O_CREAT|O_RDWR|O_APPEND, 0666);
  62. }
  63. }
  64. //初始化日志记录器
  65. CLogAck_e CLogInitLogger(CLogger_t *logger, const char* path)
  66. {
  67. #define DEFAULT_LOG_FILE_COUNT 5
  68. #define DEFAULT_LOG_ONE_FILE_SIZE (2*1024*1024) //2M
  69. #define DEFAULT_LOG_BUF_MAX_LEN (2048)
  70. int fd;
  71. off_t size;
  72. fd = open(path, O_CREAT|O_RDWR|O_APPEND, 0666);
  73. if (0 > fd) {
  74. LOGE("open fail error:");
  75. return CLOG_ACK_FAIL;
  76. }
  77. logger->bufSize = (0 >= logger->bufSize)?DEFAULT_LOG_BUF_MAX_LEN:logger->bufSize;
  78. logger->buf = malloc(logger->bufSize);
  79. if (NULL == logger->buf) {
  80. LOGD("malloc fail\r\n");
  81. close(fd);
  82. return CLOG_ACK_FAIL;
  83. }
  84. size = lseek(fd, 0, SEEK_END);
  85. logger->fd = fd;
  86. logger->fileCnt = (0 >= logger->fileCnt)?DEFAULT_LOG_FILE_COUNT:logger->fileCnt;
  87. logger->maxSize = (0 >= logger->maxSize)?DEFAULT_LOG_ONE_FILE_SIZE:logger->maxSize;
  88. logger->currSize = (unsigned int)size>=0?size:0;
  89. memset(logger->path, 0x0, sizeof(logger->path));
  90. strncpy(logger->path, path, sizeof(logger->path));
  91. RollLogFile(logger);
  92. return CLOG_ACK_OK;
  93. }
  94. //释放日志记录器
  95. void CLogUninitLogger(CLogger_t *logger)
  96. {
  97. if (0 < logger->fd) {
  98. close(logger->fd);
  99. logger->fd = -1;
  100. }
  101. if (NULL != logger->buf) {
  102. free(logger->buf);
  103. }
  104. memset(logger, 0x0, sizeof(CLogger_t));
  105. }
  106. //记录日志信息接口
  107. int CLog(CLogger_t *logger, const char *fmt, ...)
  108. {
  109. int wLen;
  110. int buf_len;
  111. int tmp_len;
  112. time_t timep = {0};
  113. struct tm tmTime = {0};
  114. time(&timep);
  115. gmtime_r(&timep, &tmTime);
  116. snprintf(logger->buf, logger->bufSize, "#%02d-%02d-%02d %02d:%02d:%02d->",
  117. (1900+tmTime.tm_year), tmTime.tm_mon+1, tmTime.tm_mday,
  118. tmTime.tm_hour, tmTime.tm_min, tmTime.tm_sec);
  119. buf_len = strlen(logger->buf);
  120. va_list arglist;
  121. va_start(arglist, fmt);
  122. wLen = vsnprintf((char*)logger->buf+buf_len, logger->bufSize-buf_len, fmt, arglist);
  123. va_end(arglist);
  124. if (0 < wLen) {
  125. buf_len += wLen;
  126. } else {
  127. wLen = buf_len;
  128. }
  129. tmp_len = logger->maxSize - logger->currSize;//剩余空间, 可能会分两次写入
  130. if (0 < tmp_len && buf_len > tmp_len) {
  131. wLen = tmp_len;
  132. }
  133. wLen = write(logger->fd, logger->buf, wLen);
  134. if (0 < wLen) {
  135. logger->currSize += wLen;
  136. tmp_len = wLen;//记录已写入字节
  137. wLen = buf_len - wLen;
  138. RollLogFile(logger);
  139. if (0 < wLen) {//还有要写入的
  140. wLen = write(logger->fd, (char*)logger->buf+tmp_len, wLen);
  141. if (0 < wLen) {
  142. logger->currSize += wLen;
  143. wLen += tmp_len;
  144. }
  145. RollLogFile(logger);
  146. }
  147. } else {
  148. RollLogFile(logger);
  149. }
  150. return wLen;
  151. }
复制代码

demo.c文件

  1. #include <stdio.h>
  2. #include <time.h>
  3. #include "clog.h"
  4. int main(int argc, char *argv[])
  5. {
  6. int ret;
  7. int count = 50;
  8. //配置最多记录多少个日志文件,每个日志文件大小
  9. CLogger_t logger = {
  10. .fileCnt = 5, //5个日志文件
  11. .maxSize = 1024, //每个日志文件大小
  12. };
  13. //初始化日志记录器
  14. ret = CLogInitLogger(&logger, "test.log");
  15. if (CLOG_ACK_OK != ret) {
  16. printf("CLogInitLogger fail, ret:%d\r\n", ret);
  17. return -1;
  18. }
  19. //测试写日志
  20. while (count--) {
  21. CLog(&logger, "Hello CLog! time: %ld, count: %d\r\n", time(NULL), count);
  22. }
  23. //释放日志记录器
  24. CLogUninitLogger(&logger);
  25. return 0;
  26. }
复制代码

三、测试结果

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

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

 

 

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Honkers

荣誉红客

关注
  • 4009
    主题
  • 36
    粉丝
  • 0
    关注
这家伙很懒,什么都没留下!

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行