概述
在現(xiàn)代軟件開發(fā)中,日志記錄系統(tǒng)是不可或缺的一部分。它不僅可以幫助開發(fā)人員在應(yīng)用程序中定位和解決問題,還可以用于監(jiān)控、性能分析、安全審計(jì)等方面。本文將介紹日志記錄系統(tǒng)的基本概念、重要性以及如何構(gòu)建一個(gè)高效的日志記錄系統(tǒng)。
為什么需要日志記錄系統(tǒng)?
日志是應(yīng)用程序在運(yùn)行時(shí)生成的文本消息,用于記錄關(guān)鍵事件、錯(cuò)誤信息、警告以及其他有價(jià)值的信息。日志記錄系統(tǒng)的作用如下:
故障排除與問題定位:當(dāng)應(yīng)用程序出現(xiàn)問題時(shí),日志可以提供關(guān)于發(fā)生了什么、在哪里發(fā)生以及為什么發(fā)生的關(guān)鍵信息,幫助開發(fā)人員快速定位和解決問題。
性能分析:通過記錄關(guān)鍵操作的時(shí)間戳和執(zhí)行時(shí)間,開發(fā)人員可以分析應(yīng)用程序的性能瓶頸,并進(jìn)行優(yōu)化。
監(jiān)控與報(bào)警:監(jiān)控系統(tǒng)可以分析日志,實(shí)時(shí)監(jiān)控應(yīng)用程序的健康狀態(tài)。當(dāng)出現(xiàn)異常情況時(shí),可以觸發(fā)報(bào)警機(jī)制,使團(tuán)隊(duì)可以及時(shí)采取措施。
安全審計(jì):記錄安全相關(guān)事件和訪問,以便進(jìn)行后續(xù)的審計(jì)和分析。
構(gòu)建日志記錄系統(tǒng)的關(guān)鍵步驟
日志級(jí)別與分類:日志級(jí)別包括調(diào)試(Debug)、信息(Info)、警告(Warning)、錯(cuò)誤(Error)等。不同級(jí)別的日志用于不同目的,例如調(diào)試時(shí)使用調(diào)試日志來追蹤代碼執(zhí)行,而錯(cuò)誤日志用于記錄嚴(yán)重的問題。選擇合適的日志級(jí)別可以避免日志信息過于冗雜或過于稀少。
日志格式與結(jié)構(gòu):一個(gè)良好的日志格式應(yīng)包括時(shí)間戳、日志級(jí)別、模塊/組件名以及具體的日志消息。統(tǒng)一的格式使得日志易于閱讀和分析。例如:[時(shí)間戳] [日志級(jí)別] [模塊名] - 日志消息
異步日志寫入:為避免阻塞應(yīng)用程序的正常執(zhí)行,可以采用異步日志寫入方式。日志消息被緩沖并在適當(dāng)?shù)臅r(shí)機(jī)寫入磁盤,從而提高應(yīng)用程序的性能。
日志存儲(chǔ)與滾動(dòng):考慮使用滾動(dòng)策略,定期歸檔或刪除舊的日志文件,以免日志文件無限增大。選擇適當(dāng)?shù)拇鎯?chǔ)方式,如本地文件、數(shù)據(jù)庫(kù)或云存儲(chǔ)。
上下文信息:除了基本的日志信息外,還可以在日志中添加上下文信息,如用戶ID、請(qǐng)求ID、會(huì)話ID等。這些信息有助于在復(fù)雜的分布式系統(tǒng)中跟蹤請(qǐng)求流程。
敏感信息與安全:避免將敏感信息(如密碼、API密鑰)寫入日志。同時(shí),實(shí)施權(quán)限控制,限制對(duì)日志文件的訪問,確保敏感信息不被濫用。
日志分析與可視化:利用日志分析工具或平臺(tái),對(duì)日志進(jìn)行聚合、搜索和可視化分析。這有助于發(fā)現(xiàn)模式、趨勢(shì)以及潛在問題。
Rlog組件
Rlog作為一款高性能的純C語言日志組件,為開發(fā)人員提供了一種輕松、靈活且可定制的日志記錄解決方案。其簡(jiǎn)單的接口和插件擴(kuò)展功能使得它適用于各種不同規(guī)模和類型的項(xiàng)目。無論是小型應(yīng)用程序還是大型系統(tǒng),Rlog都能為您提供高效的日志記錄支持,幫助您更好地理解和管理應(yīng)用程序的運(yùn)行狀態(tài)。
純C語言開發(fā):Rlog完全由C語言編寫,因此具有廣泛的可移植性和兼容性。它可以輕松地集成到各種C語言項(xiàng)目中。
簡(jiǎn)單的接口:Rlog提供了簡(jiǎn)單、直觀的接口,使開發(fā)人員可以輕松地在代碼中插入日志記錄語句。這使得調(diào)試和問題定位變得更加容易。
靈活可配置:Rlog允許開發(fā)人員根據(jù)項(xiàng)目需求進(jìn)行高度自定義的配置。您可以定義日志級(jí)別、格式、輸出位置等,以滿足不同應(yīng)用場(chǎng)景的需求。
插件擴(kuò)展:一個(gè)突出的特點(diǎn)是Rlog的插件式擴(kuò)展輸出端點(diǎn)的能力。這意味著您可以將日志消息輸出到各種不同的地方,如文件、終端、遠(yuǎn)程服務(wù)器等,以適應(yīng)多樣化的需求。
Rlog特性
支持用戶自定義輸出端點(diǎn)(例如:串口終端、網(wǎng)絡(luò)中斷、Flash...),輸出端點(diǎn)以插件形式自定義擴(kuò)展。
日志內(nèi)容可包含日志等級(jí)、時(shí)間戳、行號(hào),函數(shù)信息,文件信息;
支持多種操作系統(tǒng)(RT-Thread、Linux...),也支持裸機(jī)平臺(tái);
日志輸出支持:printf原始格式,日志等級(jí)輸出,hexdump輸出;
Rlog目錄結(jié)構(gòu)
. ├──example │├──rlog_linux_adapter.c/*linux環(huán)境下的適配接口*/ │└──rlog_rtt_adapter.c/*rt-thread環(huán)境下的適配接口*/ ├──include/ │├──rlog_adapter.h/*rlog適配描述*/ │└──rlog.h/*rlog對(duì)外接口*/ ├──main.c/*rlog的測(cè)試樣例*/ ├──Makefile/*linux環(huán)境rlog構(gòu)建Makefile*/ ├──plug-in/*輸出端點(diǎn)插件的存放路徑*/ ├──SConscript/*rt-thread環(huán)境rlog構(gòu)建腳本*/ └──src ├──rlog.c/*rlog核心代碼*/ ├──rlog_def.h/*rlog核心代碼使用的定義*/ └──rlog_utils.c/*rlog使用的C庫(kù)接口*/
Rlog靈活配置
靜態(tài)配置:
靜態(tài)配置采用宏定義的方式,用戶可直接修改rlog_adapter.h頭文件的宏定義,就可以修正相關(guān)配置;
靜態(tài)配置的管控權(quán)限比動(dòng)態(tài)配置的高,例如:靜態(tài)配置設(shè)置日志輸出總開關(guān)為關(guān)閉,動(dòng)態(tài)配置設(shè)置日志輸出使能,日志已經(jīng)無法輸出。
配置描述如下:
/*Enablelogoutput*/ #defineRLOG_OUTPUT_ENABLE1 /*Setlogoutputlevel,rang:fromRLOG_LEVEL_ASSERTtoRLOG_LEVEL_VERBOSE*/ #defineRLOG_OUTPUT_LEVELRLOG_LEVEL_VERBOSE /*Enablelogcolor*/ #defineRLOG_COLOUR_ENABLE1 /*Enablelogcolor*/ #defineRLOG_TIME_ENABLE1 /*Supportlogincludedirectory*/ #defineRLOG_DIRECTORY_ENABLE1 /*Supportlogincludefuntiongname*/ #defineRLOG_FUNCTION_ENABLE1 /*Supportlogincludelinenumber*/ #defineRLOG_LINE_ENABLE1 /*Buffersizeforeveryline'slog*/ #defineRLOG_LINE_BUFF_LEN128 /*Outputlinenumbermaxlength*/ #defineRLOG_LINE_NUM_SIZE5 /*Outputnewlinesign*/ #defineRLOG_NEWLINE_SIGN"rn" /*Enableassertcheck*/ #defineRLOG_ASSERT_ENABLE1 /*Logfunction.defaultFDB_PRINTmacroisprintf()*/ #defineRLOG_PRINT(...)printf(__VA_ARGS__)
宏 | 描述 |
---|---|
RLOG_OUTPUT_ENABLE | rlog日志輸出總開關(guān) |
RLOG_OUTPUT_LEVEL | rlog日志輸出等級(jí)總開關(guān) |
RLOG_COLOUR_ENABLE | rlog日志等級(jí)輸出帶顏色開關(guān) |
RLOG_TIME_ENABLE | rlog日志等級(jí)輸出帶時(shí)間開關(guān) |
RLOG_DIRECTORY_ENABLE | rlog日志等級(jí)輸出帶文件路徑開關(guān) |
RLOG_FUNCTION_ENABLE | rlog日志等級(jí)輸出帶函數(shù)名開關(guān) |
RLOG_LINE_ENABLE | rlog日志等級(jí)輸出帶行號(hào)開關(guān) |
RLOG_LINE_BUFF_LEN | rlog每一條日志最大長(zhǎng)度 |
RLOG_LINE_NUM_SIZE | rlog日志等級(jí)輸出行號(hào)的最大長(zhǎng)度 |
RLOG_NEWLINE_SIGN | rlog日志換行符格式 |
RLOG_ASSERT_ENABLE | rlog使用assert功能 |
RLOG_PRINT(...) | rlog中斷輸出設(shè)置,如rt-thread采用rt_kprintf, linux采用printf |
動(dòng)態(tài)配置:
動(dòng)態(tài)配置采用接口的方式,用戶通過調(diào)用rlog.h頭文件提供的接口設(shè)置;
動(dòng)態(tài)配置的管控權(quán)限比靜態(tài)配置的低,例如:靜態(tài)配置設(shè)置日志輸出總開關(guān)為關(guān)閉,動(dòng)態(tài)配置設(shè)置日志輸出使能,日志已經(jīng)無法輸出。
/** *RLogoutputenable * *@paramenabletrue:enableoutput,false:disableoutput */ voidrlog_enable(boolenable); /** *RLogoutputcolorenable * *@paramenabletrue:enableoutputcolor,false:disableoutputcolor */ voidrlog_color_enable(boolenable); /** *RLogleveloutputformatsetting * *@paramlevelloglevel *@paramformatlogformat */ voidrlog_level_fmt_set(rlog_lvl_tlevel,intformat); /** *RLogleveloutputformatsetting * *@paramlevelloglevel *@paramformatlogformat * *@returnresulttrue:supportedformat,false:unsupportedformat */ boolrlog_level_fmt_get(rlog_lvl_tlevel,intformat); /** *RLogfilterthecontentoftheloglevel * *@paramlevelloglevel */ voidrlog_level_filter_set(rlog_lvl_tlevel);
配置函數(shù) | 描述 |
---|---|
rlog_enable | rlog日志輸出使能開光 |
rlog_color_enable | rlog日志等級(jí)輸出帶顏色開關(guān) |
rlog_level_fmt_set | rlog日志等級(jí)輸出格式設(shè)置,RLOG_FMT_LVL/RLOG_FMT_TAG/RLOG_FMT_TIME/RLOG_FMT_DIR/RLOG_FMT_FUNC/RLOG_FMT_LINE |
rlog_level_fmt_get | rlog日志等級(jí)輸出格式獲取 |
rlog_level_filter_set | rlog日志等級(jí)輸出過濾設(shè)置 |
Rlog適配
不同平臺(tái)的適配方式不同,所以為rlog核心層提供了統(tǒng)一的接口,適配接口如下:
voidrlog_adapter_init(void); voidrlog_adapter_deinit(void); voidrlog_lock(void); voidrlog_unlock(void); char*rlog_get_time(void); voidrlog_output(constchar*log,uint16_tlen);
適配函數(shù) | 描述 |
---|---|
rlog_adapter_init | rlog適配層初始化,如端點(diǎn)插件初始化 |
rlog_adapter_deinit | rlog適配層去初始化,如端點(diǎn)插件去初始化 |
rlog_lock | rlog日志鎖,為rlog提供線程安全 |
rlog_unlock | rlog日志解鎖,為rlog提供線程安全 |
rlog_get_time | rlog日志提供時(shí)間 |
rlog_output | rlog日志輸出適配接口 |
linux下的適配方式:
staticpthread_mutex_tmutex; voidrlog_lock(void) { pthread_mutex_lock(&mutex); } voidrlog_unlock(void) { pthread_mutex_unlock(&mutex); } char*rlog_get_time(void) { #defineTIME_STR_SIZE32 staticchartime_str[TIME_STR_SIZE]={0}; time_ttmp; structtm*timp; time(&tmp); timp=localtime(&tmp); memset(time_str,0,TIME_STR_SIZE); rlog_snprintf(time_str,TIME_STR_SIZE,"%04d-%02d-%02d%02d:%02d:%02d", (1900+timp->tm_year),(1+timp->tm_mon),timp->tm_mday, timp->tm_hour,timp->tm_min,timp->tm_sec); returntime_str; } voidrlog_output(constchar*log,uint16_tlen) { RLOG_PRINT("%.*s",len,log); } voidrlog_adapter_init(void) { pthread_mutex_init(&mutex,NULL); } voidrlog_adapter_deinit(void) { pthread_mutex_destroy(&mutex); }
Rlog驗(yàn)證
rlog驗(yàn)證以linux環(huán)境為例,Rlog開源路徑:https://gitee.com/RiceChen0/rlog
rlog驗(yàn)證操作流程:
youyeetoo@youyeetoo:~$gitclonehttps://gitee.com/RiceChen0/rlog.git youyeetoo@youyeetoo:~/rlog$make youyeetoo@youyeetoo:~/rlog$./output/rlog_1.0.0 RLogVersion:v1.0.0 RLogAuthor:RiceChen RLogContact:https://gitee.com/RiceChen0/rlog Youyeetoo (2023-08-1518:53:27)[main.cmain:12]I/RLOG:Youyeetoo RLOGHexDump--Title:RLOG,len:9 00000000:596F75796565746F6FYouyeetoo
rlog驗(yàn)證效果:
Rlog總結(jié)
rlog提供了簡(jiǎn)單易用的日志系統(tǒng),采用插件方式,提供靈活的輸出端點(diǎn)的設(shè)置。
rlog的原型參考了開源項(xiàng)目:https://gitee.com/RT-Thread-Mirror/EasyLogger。
rlog不依賴C庫(kù),rlog_utils.c中,重新定義了用到C庫(kù)接口。接口參考了開源項(xiàng)目:https://gitee.com/RT-Thread-Mirror/rt_vsnprintf_full。
下一步計(jì)劃:
rlog提供不同場(chǎng)景下的插件,網(wǎng)絡(luò)中斷,文件存儲(chǔ),異步操作。
rlog將提供對(duì)應(yīng)的上位機(jī),上位機(jī)功能將集成到RTOOLS中,RTOOLS開源路徑:https://gitee.com/RiceChen0/rtools。
審核編輯 黃宇
-
接口
+關(guān)注
關(guān)注
33文章
8639瀏覽量
151385 -
監(jiān)控
+關(guān)注
關(guān)注
6文章
2216瀏覽量
55254 -
C語言
+關(guān)注
關(guān)注
180文章
7608瀏覽量
137110
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論