前言
c语言实现一下日志输出容易吗?
容易。
要多久?
10分钟。

一、准备工作
终端工具:
SecureCRT 8.7
https://download.youkuaiyun.com/download/m_pfly_fish/20056079
二、安装SecureCRT
1.根据压缩包中的安装教程进行安装
2.设置crt相关配置:

session options是指设置当前会话(当前连接的这个shell起效)的选项
global options是指设置全局会话(对以后连接的所有shell起效)的选项
选择 global options 进行全局设置

关闭 scroll to bottom on output ,这样不会每次有 log 时都跳到最低端

设置 terminal 为 linux 风格,设置 logical rows 为35(这个数据根据自己显示器分辨率来设置,我的35刚好),设置 logical columns 为128(这个数值够了),设置 Retain size and font。设置 scrollback buffer 大小为5000(这样可以缓存更多的 log )。

设置 line wrap 和 new line mode 两项,这两项比较重要,很多 log 水平显示不完全,log 换行未从头显示的问题都是因为这两个选项导致的。

基本配置这些够了,其他的可以根据自己的喜好设置。
三、创建串口
完成以上配置后,创建串口


根据相关参数配置。
四、代码编辑
1. log.h文件
在头文件中添加以下代码
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
typedef enum {
E_LOGV = 1,
E_LOGD,
E_LOGI,
E_LOGW,
E_LOGE,
} LOG_LEVEL_E;
typedef enum {
LOG_NONE, /*!< No log output */
LOG_ERROR, /*!< Critical errors, software module can not recover on its own */
LOG_WARN, /*!< Error conditions from which recovery measures have been taken */
LOG_INFO, /*!< Information messages which describe normal flow of events */
LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
} log_level_t;
void log_write(log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
uint32_t log_timestamp(void);
#define LOG_COLOR_BLACK "30"
#define LOG_COLOR_RED "31"
#define LOG_COLOR_GREEN "32"
#define LOG_COLOR_BROWN "33"
#define LOG_COLOR_BLUE "34"
#define LOG_COLOR_PURPLE "35"
#define LOG_COLOR_CYAN "36"
#define LOG_COLOR(COLOR) "\033[0;" COLOR "m"
#define LOG_BOLD(COLOR) "\033[1;" COLOR "m"
#define LOG_RESET_COLOR "\033[0m"
#define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED)
#define LOG_COLOR_W LOG_COLOR(LOG_COLOR_BROWN)
#define LOG_COLOR_I LOG_COLOR(LOG_COLOR_GREEN)
#define LOG_COLOR_D
#define LOG_COLOR_V
#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n"
#define LOG_LEVEL(level, tag, format, ...) do { \
if (level==LOG_ERROR ) { log_write(LOG_ERROR, tag, LOG_FORMAT(E, format), log_timestamp(), tag, ##__VA_ARGS__); } \
else if (level==LOG_WARN ) { log_write(LOG_WARN, tag, LOG_FORMAT(W, format), log_timestamp(), tag, ##__VA_ARGS__); } \
else if (level==LOG_DEBUG ) { log_write(LOG_DEBUG, tag, LOG_FORMAT(D, format), log_timestamp(), tag, ##__VA_ARGS__); } \
else if (level==LOG_VERBOSE ) { log_write(LOG_VERBOSE, tag, LOG_FORMAT(V, format), log_timestamp(), tag, ##__VA_ARGS__); } \
else { log_write(LOG_INFO, tag, LOG_FORMAT(I, format), log_timestamp(), tag, ##__VA_ARGS__); } \
} while(0)
#define LOGE( tag, format, ... ) LOG_LEVEL(LOG_ERROR, tag, format, ##__VA_ARGS__)
#define LOGW( tag, format, ... ) LOG_LEVEL(LOG_WARN, tag, format, ##__VA_ARGS__)
#define LOGI( tag, format, ... ) LOG_LEVEL(LOG_INFO, tag, format, ##__VA_ARGS__)
#define LOGD( tag, format, ... ) LOG_LEVEL(LOG_DEBUG, tag, format, ##__VA_ARGS__)
#define LOGV( tag, format, ... ) LOG_LEVEL(LOG_VERBOSE, tag, format, ##__VA_ARGS__)
#define DEF_LOG_DEFAULT_LEVEL E_LOGV
#define LOG(level, tag, format, ...) do { \
if(level >= DEF_LOG_DEFAULT_LEVEL){ \
switch(level) { \
case E_LOGV: LOGV( tag, "%d:%s:"format, __LINE__, __FUNCTION__, ##__VA_ARGS__);break; \
case E_LOGD: LOGD( tag, "%d:%s:"format, __LINE__, __FUNCTION__, ##__VA_ARGS__);break; \
case E_LOGI: LOGI( tag, "%d:%s:"format, __LINE__, __FUNCTION__, ##__VA_ARGS__);break; \
case E_LOGW: LOGW( tag, "%d:%s:"format, __LINE__, __FUNCTION__, ##__VA_ARGS__);break; \
case E_LOGE: LOGE( tag, "%d:%s:"format, __LINE__, __FUNCTION__, ##__VA_ARGS__);break; \
default: LOGI( tag, "%d:%s:"format, __LINE__, __FUNCTION__, ##__VA_ARGS__);break; \
} \
} \
} while(0);
#define ASSERT(expr) assert(expr)
2. log.c文件
在 .c 文件中添加以下代码
void log_write(log_level_t level,
const char *tag,
const char *format, ...)
{
va_list arg;
va_start(arg, format);
vprintf(format, arg);
va_end(arg);
}
uint32_t log_timestamp()
{
uint32_t time = OS_GetTicks();
return time;
}
之后就可以在应用代码中实现彩色日志输出了,例:
static const char *tag = "APP_MAIN";
LOG(E_LOGI, tag, "Hello world!");
备注:
OS_GetTicks() 此函数为 freertos 中获取系统时间 api,打印日志时如果不需要时间戳可以修改以下代码
#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " %s: " format LOG_RESET_COLOR "\n"
#define LOG_LEVEL(level, tag, format, ...) do { \
if (level==LOG_ERROR ) { log_write(LOG_ERROR, tag, LOG_FORMAT(E, format), tag, ##__VA_ARGS__); } \
else if (level==LOG_WARN ) { log_write(LOG_WARN, tag, LOG_FORMAT(W, format), tag, ##__VA_ARGS__); } \
else if (level==LOG_DEBUG ) { log_write(LOG_DEBUG, tag, LOG_FORMAT(D, format), tag, ##__VA_ARGS__); } \
else if (level==LOG_VERBOSE ) { log_write(LOG_VERBOSE, tag, LOG_FORMAT(V, format), tag, ##__VA_ARGS__); } \
else { log_write(LOG_INFO, tag, LOG_FORMAT(I, format), tag, ##__VA_ARGS__); } \
} while(0)
本文介绍了如何在C语言环境中快速实现日志输出功能,包括日志级别定义、宏定义以及彩色日志的输出。通过提供的log.h和log.c文件,开发者可以在10分钟内设置并使用彩色日志系统,便于调试和查看程序运行状态。
3万+

被折叠的 条评论
为什么被折叠?



