最近由于接手了几个小的开发项目,一直苦于寻找一个调用简单,方便调试,占用资源小的日志库,因为我大部分的嵌入式开发项目都是C/C++的开发。就想着做一个小的日志调用接口C/C++库。最近有时间整理一下。
alog 由此而生,目前我几个项目中都用到了这个库,个人觉得非常简单,容易理解,使用简单,能马上融入到小型嵌入式项目中去。
首先看调用示例:
#include "alog_printf.h"
int main(void)
{
alog_printf(ALOG_LVL_DEBUG, TURE,"\n************TEST START**************\n");
int a = 0;
while (1)
{
alog_printf(ALOG_LVL_DEBUG, TURE, "test a=%d \n", a);
a++;
sleep(1);
}
return 0;
}
示例中可以看到,这个日志调用类似于打印函数(其实就是改造的),说是一个日志库文件,不如说就是一个头文件,(这里主要是为了简单-不用去引用其他东西)是不是很简单。
调用原型:
alog_printf(level, outputEnable, ...);
首先这个日志库具备这几个功能:
- 可以设置输出到指定路径下保存成文件-方便导出查看
- 日志文件以创建时间先后命名
- 日志文件的大小和个数可设置,当超出设置限制后根据创建时间循环覆盖
- 日志的保存等级可设置
- 可控制是否打印在终端
- 可输出打印时间、调用函数名和行数,方便定位打印
附一段核心实现:
/**
* @brief : Ari日志打印
* @param {unsigned char} level
* @param {_BOOL} outputEnable
* @param {const char} *func
* @param {const long} line
* @param {const char} *fmt
* @return {*}
* @author: LR
* @Date: 2021-06-25 12:11:49
*/
static void log_printf(unsigned char level, bool outputEnable, const char *file, const long line, const char *fmt, ...)
{
if (level < ALOG_LVL_SET)
return;
pthread_mutex_lock(&alogMutex); /* 日志部分上锁 */
char printf_buf[ALOG_BUF_MAX_SIZE]={0};
va_list args;
int printed;
va_start(args, fmt);
printed = vsnprintf(printf_buf, ALOG_BUF_MAX_SIZE, fmt, args);
va_end(args);
char buf[ALOG_BUF_MAX_SIZE + 200] = {0};
int g_Count = 0;
char temp[256];
char logFileName[50] = {0};
char logFileNameTemp[50] = {0};
char logFileNameLast[50] = {"1580-05-05_00-00-00.log"};
char logFileNameMix[50] = {"3000-05-05_00-00-00.log"};
int iMax = ALOG_MAX_SIZE;
FILE *fp = NULL;
time_t timep;
struct tm *p;
time(&timep);
p = localtime(&timep); //获取当前系统时间
//将要保存的日志信息和时间戳信息整合
memset(buf, 0, sizeof(buf));
sprintf(buf, "▶[%d-%02d-%02d %02d:%02d:%02d -> %s:%ld] : ", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday, (p->tm_hour + 8) % 24, p->tm_min, p->tm_sec, file, line); //星期p->tm_wday
strcat(buf, printf_buf);
//strcat(buf, "\0");
if (outputEnable == true)
puts(buf);
DIR *dir;
struct dirent *ptr;
if ((dir = opendir(ALOG_PATH)) == NULL) //打开日志的文件目录,如果没有则建立
{
sprintf(temp, "mkdir -p %s", ALOG_PATH);
system(temp);
dir = opendir(ALOG_PATH);
}
while ((ptr = readdir(dir)) != NULL) //循环读取当前目录下到所有文件
{
if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)
continue;
strcpy(logFileNameTemp, ptr->d_name);
if (strlen(logFileNameTemp) < 18)
{
//g_Count++; //统计符合要求的文件个数
continue;
}
if (strcmp(logFileNameTemp, logFileNameLast) > 0) //找到最新的文件
{
strcpy(logFileNameLast, logFileNameTemp); //将最新日期的文件名字保存在logFileNameLast
}
if (strcmp(logFileNameTemp, logFileNameMix) < 0) //找到最老的文件
{
strcpy(logFileNameMix, logFileNameTemp); //将最老日期的文件名字保存在logFileNameMix
}
g_Count++; //统计符合要求的文件个数
}
closedir(dir);
sprintf(logFileName, "%s%s", ALOG_PATH, logFileNameLast); //将最新的文件名字匹配到路径中去,如果没有用默认文件名
fp = fopen(logFileName, "r+");
if (fp == NULL)
{
//进入这个里面证明没有日志文件产生过,第一次创建+
sprintf(logFileName, "%s%d-%02d-%02d_%02d-%02d-%02d.log", ALOG_PATH, (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday, (p->tm_hour + 8) % 24, p->tm_min, p->tm_sec);
fp = fopen(logFileName, "w+");
}
else
{
fseek(fp, 0, 2); //SEEK_END值为2
if (ftell(fp) >= iMax) //如果大小已经超出限制
{
fclose(fp);
if (g_Count >= ALOG_MAX_NUM) //如果日志文件的个数达到路限制10个,则按日期进行循环覆盖
{
sprintf(logFileName, "%s%s", ALOG_PATH, logFileNameMix);
remove(logFileName); //删除最老的一个日志文件
sprintf(logFileName, "%s%d-%02d-%02d_%02d-%02d-%02d.log", ALOG_PATH, (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday, (p->tm_hour + 8) % 24, p->tm_min, p->tm_sec);
}
else
{
sprintf(logFileName, "%s%d-%02d-%02d_%02d-%02d-%02d.log", ALOG_PATH, (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday, (p->tm_hour + 8) % 24, p->tm_min, p->tm_sec);
}
fp = fopen(logFileName, "w+");
}
else
{
fclose(fp);
fp = fopen(logFileName, "a+"); //以追加的方式打开文件
}
}
fwrite(buf, 1, strlen(buf), fp);
fflush(fp); //立即刷新缓存区到指定文件流中
//fsync(fileno(fp)); //将缓存区数据写入磁盘,并等待操作结束
//fdatasync(fileno(fp));
fclose(fp);
pthread_mutex_unlock(&alogMutex); /*写日志部分解锁 */
}
这里面最关键的,个人认为根据设定来把时间段内的日志发片。然后根据时间来循环的覆盖日志,这样在我们有限的嵌入式资源中就能把握日志的占用大小。不用人为的去维护,在有需要的时候下载下来,方便记录调试定位问题。
当然这个只是项目需要写的一个东西,里面我现在想到的就还有很多可以优化增加的功能。现在只是记录一下,拿来用还是没问题的。大家有想法的也可以给我留言。
完整的实现+示例请下载:
优快云:alog_printf.h-C文档类资源-优快云下载
GitHub:GitHub - HelloAriLiu/alog: 一个简单的Linux 日志库适用于小型嵌入式
创作不易,您的点赞、评论、收藏是对我最大的支持!