媒介
- c语言没有现成的日记库,如果要记载日记,必要自己封装一个日记库。如果要实现日记级别和参数打印,照旧比力贫苦的,正好在github找到了一个c语言开源日记库,可以实现日记级别打印,参数打印,而且还会记载日期和行号,最重要的是代码非常少,只有100多行,可以直接包罗在我们自己的工程代码中,不必要任何依赖。
源码地点
使用先容
- 直接把工程目录下的log.c和log.h下载下来,包罗到工程代码中即可,没有其他依赖。
- 日记级别由低到高,分别为 LOG_TRACE、LOG_DEBUG、LOG_INFO、LOG_WARN、LOG_ERROR、LOG_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 32
- typedef 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_COLOR
- static const char *level_colors[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"};
- #endif
- static void stdout_callback(log_Event *ev) {
- char buf[16];
- buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0';
- #ifdef LOG_USE_COLOR
- fprintf(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);
- #else
- fprintf(ev->udata, "%s %-5s %s:%d: ", buf, level_strings[ev->level], ev->file, ev->line);
- #endif
- vfprintf(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();
- }
复制代码
- windows平台编译时有报错,结构体赋值语法不支持,我做了修改。
- 修改后的 log.c
- #include "log.h"
- #define MAX_CALLBACKS 32
-
- typedef 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_COLOR
- static const char *level_colors[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"};
- #endif
-
- static void stdout_callback(log_Event *ev) {
- char buf[100] = {0};
- time_t timep;
- time(&timep);
- struct tm *pt = gmtime(&timep);
- sprintf(buf, "%d-%02d-%02d %02d:%02d:%02d", 1900 + pt->tm_year, 1 + pt->tm_mon, pt->tm_mday, (8 + pt->tm_hour) % 24, pt->tm_min, pt->tm_sec);
- #ifdef LOG_USE_COLOR
- fprintf((FILE *)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);
- #else
- fprintf((FILE *)ev->udata, "%s %-5s %s:%d: ", buf, level_strings[ev->level], ev->file, ev->line);
- #endif
- vfprintf((FILE *)ev->udata, ev->fmt, ev->ap);
- fprintf((FILE *)ev->udata, "\n");
- fflush((FILE *)ev->udata);
- }
-
- static void file_callback(log_Event *ev) {
- char buf[100] = {0};
- time_t timep;
- time(&timep);
- struct tm *pt = gmtime(&timep);
- sprintf(buf, "%d-%02d-%02d %02d:%02d:%02d", 1900 + pt->tm_year, 1 + pt->tm_mon, pt->tm_mday, (8 + pt->tm_hour) % 24, pt->tm_min, pt->tm_sec);
- fprintf((FILE *)ev->udata, "%s %-5s %s:%d: ", buf, level_strings[ev->level], ev->file, ev->line);
- vfprintf((FILE *)ev->udata, ev->fmt, ev->ap);
- fprintf((FILE *)ev->udata, "\n");
- fflush((FILE *)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].fn = fn;
- L.callbacks[i].udata = udata;
- L.callbacks[i].level = 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 = gmtime(&t);
- }
- ev->udata = udata;
- }
-
- void log_log(int level, const char *file, int line, const char *fmt, ...) {
- log_Event ev;
- ev.fmt = fmt;
- ev.file = file;
- ev.line = line;
- ev.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();
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |