轻量级c语言开源日志库log.c介绍 - 实现不同级别和参数化日志打印

前言

  • c语言没有现成的日志库,如果要记录日志,需要自己封装一个日志库。如果要实现日志级别和参数打印,还是比较麻烦的,正好在github找到了一个c语言开源日志库,可以实现日志级别打印,参数打印,而且还会记录日期和行号,最重要的是代码非常少,只有100多行,可以直接包含在我们自己的工程代码中,不需要任何依赖。

源码地址

  • github源码连接

使用介绍

  • 直接把工程目录下的log.c和log.h下载下来,包含到工程代码中即可,没有其他依赖。
  • 日志级别由低到高,分别为 LOG_TRACELOG_DEBUGLOG_INFOLOG_WARNLOG_ERRORLOG_FATAL
  • 如果设置日志级别为LOG_TRACE,则所有级别日志都会打印,如果设置日志级别为LOG_WARN,则只会打印LOG_WARN以及更高级别(即LOG_ERROR和LOG_FATAL)的日志

演示

  • 测试代码
    •   #include "log.h"#include <stdio.h>int main() {FILE *fp = fopen("log.txt", "a+");if(fp == NULL){printf("create log file failed.\n");return -1;}//设置日志级别(在终端打印)log_set_level(LOG_TRACE);//设置日志级别(在文件中打印)log_add_fp(fp, LOG_INFO);log_trace("start trace.");log_debug("start debug.");log_info("start info.");log_warn("start warn.");log_error("start error.");log_fatal("start fatal");// 支持参数打印log_info("number is %d, string is %s", 10010, "helloword");fclose(fp);}
      
  • 演示效果
    在这里插入图片描述

源码

  • 如果访问github有问题,我把源码贴到下面了。
  • log.h
    •   #ifndef LOG_H#define LOG_H#include <stdio.h>#include <stdarg.h>#include <stdbool.h>#include <time.h>#define LOG_VERSION "0.1.0"typedef struct {va_list ap;const char *fmt;const char *file;struct tm *time;void *udata;int line;int level;} log_Event;typedef void (*log_LogFn)(log_Event *ev);typedef void (*log_LockFn)(bool lock, void *udata);enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)#define log_info(...)  log_log(LOG_INFO,  __FILE__, __LINE__, __VA_ARGS__)#define log_warn(...)  log_log(LOG_WARN,  __FILE__, __LINE__, __VA_ARGS__)#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)const char* log_level_string(int level);void log_set_lock(log_LockFn fn, void *udata);void log_set_level(int level);void log_set_quiet(bool enable);int log_add_callback(log_LogFn fn, void *udata, int level);int log_add_fp(FILE *fp, int level);void log_log(int level, const char *file, int line, const char *fmt, ...);#endif
      
  • log.c
    •   #include "log.h"#define MAX_CALLBACKS 32typedef struct {log_LogFn fn;void *udata;int level;} Callback;static struct {void *udata;log_LockFn lock;int level;bool quiet;Callback callbacks[MAX_CALLBACKS];} L;static const char *level_strings[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"};#ifdef LOG_USE_COLORstatic const char *level_colors[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"};#endifstatic void stdout_callback(log_Event *ev) {char buf[16];buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0';#ifdef LOG_USE_COLORfprintf(ev->udata, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ", buf, level_colors[ev->level], level_strings[ev->level], ev->file, ev->line);#elsefprintf(ev->udata, "%s %-5s %s:%d: ", buf, level_strings[ev->level], ev->file, ev->line);#endifvfprintf(ev->udata, ev->fmt, ev->ap);fprintf(ev->udata, "\n");fflush(ev->udata);}static void file_callback(log_Event *ev) {char buf[64];buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0';fprintf(ev->udata, "%s %-5s %s:%d: ", buf, level_strings[ev->level], ev->file, ev->line);vfprintf(ev->udata, ev->fmt, ev->ap);fprintf(ev->udata, "\n");fflush(ev->udata);}static void lock(void)   { if (L.lock) { L.lock(true, L.udata); }}static void unlock(void) {if (L.lock) { L.lock(false, L.udata); }}const char* log_level_string(int level) { return level_strings[level];}void log_set_lock(log_LockFn fn, void *udata) {L.lock = fn;L.udata = udata;}void log_set_level(int level) {L.level = level;}void log_set_quiet(bool enable) {L.quiet = enable;}int log_add_callback(log_LogFn fn, void *udata, int level) {for (int i = 0; i < MAX_CALLBACKS; i++) {if (!L.callbacks[i].fn) {L.callbacks[i] = (Callback) { fn, udata, level };return 0;}}return -1;}int log_add_fp(FILE *fp, int level) {return log_add_callback(file_callback, fp, level);}static void init_event(log_Event *ev, void *udata) {if (!ev->time) {time_t t = time(NULL);ev->time = localtime(&t);}ev->udata = udata;}void log_log(int level, const char *file, int line, const char *fmt, ...) {log_Event ev = {.fmt   = fmt,.file  = file,.line  = line,.level = level,};lock();if (!L.quiet && level >= L.level) {init_event(&ev, stderr);va_start(ev.ap, fmt);stdout_callback(&ev);va_end(ev.ap);}for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) {Callback *cb = &L.callbacks[i];if (level >= cb->level) {init_event(&ev, cb->udata);va_start(ev.ap, fmt);cb->fn(&ev);va_end(ev.ap);}}unlock();}
      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/141091.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SAP PO运维(四):适配器消息监控

登录SAP PO系统,点击“Configuration and Monitoring Home”,使用PISUPER账号登录: 2、选择“适配器引擎->消息监控器”: 3、查看是否有报错消息: 双击报错的数字,筛选出报错的条目(可以根据状态、接口命名空间等来筛选):常见的报错消息有: 接口配置问题:字段为空值…

好题记录 Leetcode 394.字符串解码 中等难度

方法一&#xff1a;递归 思路很简单&#xff0c;比较好理解&#xff0c;注意细节处理&#xff01;&#xff01;&#xff01; class Solution { public:string decodeString(string s) {string ans;for(int i0;s[i]!0;i){if(s[i]>a&&s[i]<z)anss[i];if(s[i]>…

十四、流式编程(4)

本章概要 终端操作 数组循环集合组合匹配查找信息数字流信息 终端操作 以下操作将会获取流的最终结果。至此我们无法再继续往后传递流。可以说&#xff0c;终端操作&#xff08;Terminal Operations&#xff09;总是我们在流管道中所做的最后一件事。 数组 toArray()&…

实时更新进度条:JavaScript中的定时器和异步编程技巧

前言 在Web开发中&#xff0c;有许多场景需要实时地更新页面上的进度&#xff0c;例如上传文件、数据处理等。本文将介绍如何利用JavaScript中的定时器和异步编程技巧来实现实时更新进度&#xff0c;并探讨一些其他解决方案。 处理进度实时更新&#xff1a; 利用异步编程实现实…

速卖通商品详情数据接口

速卖通商品详情数据接口&#xff08;aliexpress商品详情API接口&#xff09;可以获取到速卖通商品的详细信息&#xff0c;如商品标题、价格、库存、详情描述、图片等。 速卖通商品详情API接口是速卖通提供的一种产品数据接口&#xff0c;可以帮助速卖通卖家快速地将产品分类、…

Mysql主从数据恢复随笔

目录 1.使用pt-table-checksum插件安装方式如下 2.在主节点执行检查数据同步情况 3.同步检查出现的问题 3.1没有sock文件 3.2 Authentication plugin ‘sha256_password’ cannot be loaded: /usr/lib64/mysql/plugin/sha256_password.so: 无法打开共享对象文件: 没有那个文…

【刷题笔记9.24】LeetCode:二叉树最大深度

LeetCode&#xff1a;二叉树最大深度 1、题目描述&#xff1a; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 二、思路与算法 如果我们知道了左子树和右子树的最大深度 lll 和 rrr&#xff0c;…

基于Spring Boot的IT技术交流和分享平台的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 我国科学技术的不断发展&#xff0c;计算机的应用日渐成熟&#xff0c;其强大的功能给人们留下深刻的印象&#xff0c;它已经应用到了人类社会的各个层次的领域&#x…

MongoDB索引

索引支持在MongoDB中高效执行查询。如果没有索引&#xff0c;MongoDB必须扫描集合中的每个文档才能返回查询结果。如果查询存在适当的索引&#xff0c;MongoDB将使用该索引来限制它必须扫描的文档数。 尽管索引提高了查询性能&#xff0c;但添加索引对写入操作的性能有负面影响…

怎么去营造地中海风格?进来来看看吧

什么是地中海风格&#xff1f; 地中海风格是一种受地中海沿岸住宅建筑和美学影响的装饰风格。西班牙、希腊和摩洛哥等国的文化对地中海风格产生了影响。 简约是地中海生活的主要部分。地中海气候宜人&#xff0c;人们的生活态度闲适&#xff0c;这一点在色彩、设计、材料和图案…

2023第十二届中国智能产业高峰论坛之文档大模型的探索与思考

文章目录 前言合合信息多模态大模型与文档图像智能理解文档图像分析识别与理解的技术难题文档图像分析与预处理文档解析与识别版面分析与还原文档信息抽取与理解AI安全知识化&存储检索和管理 文档图像的分析识别与理解和大模型的关系文档图像大模型的进展LayoutLMUDOPDonut…

东郊到家app小程序公众号软件开发预约同城服务系统成品源码部署

东郊到家app系统开发&#xff0c;东郊到家软件定制开发&#xff0c;东郊到家小程序APP开发&#xff0c;东郊到家源码定制开发&#xff0c;东郊到家模式系统定制开发 一、上门软件介绍 1、上门app是一家以推拿为主项&#xff0c;个人定制型的o2o平台&#xff0c;上门app平台提…

次时代摸鱼骚操作:人在办公室轻松观看家里电脑上的4k电影(移动端公网访问本地群辉存储视频文件)

如何使用iPhone15在办公室观看家里电脑上的4k电影&#xff1f; 文章目录 如何使用iPhone15在办公室观看家里电脑上的4k电影&#xff1f;1.使用环境要求&#xff1a;2.下载群晖videostation&#xff1a;3.公网访问本地群晖videostation中的电影&#xff1a;4.公网条件下使用电脑…

详解MySQL索引+面试题

前言: 📕作者简介:热爱编程的小七,致力于C、Java、Python等多编程语言,热爱编程和长板的运动少年! 📘相关专栏Java基础语法,JavaEE初阶,数据库,数据结构和算法系列等,大家有兴趣的可以看一看。 😇😇😇有兴趣的话关注博主一起学习,一起进步吧! 一、索引概述…

购物新时尚RFID自助结账

购物已经变得更加简单和方便了&#xff0c;归功于RFID自助结账。别再排队等收银员了&#xff0c;让我们来看看这个酷炫的新方式。 RFID是什么&#xff1f;RFID就是那些小电子标签&#xff0c;它们能够让物品自动被识别。每个商品都有一个这样的标签&#xff0c;而RFID读卡器就…

【Linux is not Unix】Linux前言

目录 二战军工的产物——第一台现代电子数字计算机ENIAC&#xff08;埃尼阿克&#xff09; Unix Linux Linux企业应用现状 如今计算机已经应用在我们生活的各个层面&#xff0c;像我们日常使用的笔记本是计算机的一类&#xff0c;可以解决我们生活中遇到的很多问题&#xff…

视频监控系统/视频汇聚平台EasyCVR有下级平台注册时出现断流情况该如何排查解决?

视频汇聚/视频云存储/集中存储/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;实现视频资源的鉴权管理、按需调阅、全网分发、云存储、智能分析等&#xff0c;视频智能分析平台EasyCVR融合性强、开放度…

论文阅读:AugGAN: Cross Domain Adaptation with GAN-based Data Augmentation

Abstract 基于GAN的图像转换方法存在两个缺陷&#xff1a;保留图像目标和保持图像转换前后的一致性&#xff0c;这导致不能用它生成大量不同域的训练数据。论文提出了一种结构感知(Structure-aware)的图像转换网络(image-to-image translation network)。 Proposed Framework…

【渗透攻防】千变万化的WebShell

前言 WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境&#xff0c;也可以将其称做为一种网页后门。本篇文章将带大家学习如何获取WebShell&#xff0c;如何隐藏WebShell&#xff0c;有攻必有防&#xff0c;最后带大家学习查杀WebShell。 目录 第一节…

Opencv cuda版本在ubuntu22.04中安装办法,解决Could NOT find CUDNN的办法

文章目录 概要下载cuda的runfile版本配置环境变量官网下载cudann安装Opencv依赖包下载opencv和opencv_contrib并解压准备编译安装anaconda环境执行编译命令安装OpenCV并检查是否安装成功 概要 解决以下安装问题&#xff1a; -- Could NOT find CUDNN: Found unsuitable versi…