背景
開發中我們經常需要用到Log來調試問題,但我們也常常深受其害。開發新功能的時候,總是被一些亂七八糟的日誌所幹擾,找不到自己需要的日誌信息。這個時候你一定想快速的屏蔽掉那些暫時不需要關心的Log。日誌分級由此而生。
日誌分級
我們可以把日誌分爲不同的等級,通過一個開關來控制打印哪些日誌,從而屏蔽哪些暫時不關心的日誌,解放控制檯,讓真正需要的信息乾淨的展示在我們面前。
簡單實現
代碼裏有註釋,就不再贅述了,直接使用我這套的同學,只需要創建一個頭文件,按照順序吧下面代碼粘進去就行了。然後再適當的地方,調不同的打印方式。
- 劃分等級
按照自己的需求將日誌分爲幾個不同等級,大家可以自己定義,也可以直接使用我的分級模式。
typedef NS_ENUM(NSInteger,LGLogLevel) {
LGLogLevelNone = 0, // 不打印
LGLogLevelFatal = 1 << 0, // 打印嚴重、重要信息
LGLogLevelError = 1 << 1, // 打印錯誤
LGLogLevelDebug = 1 << 2, // 打印正常調試,如請求結果
LGLogLevelSimple = 1 << 3, // 打印次要信息,如日誌上報記錄
};
- 設置等級
#ifdef DEBUG
/* 根據自己需求設置日誌級別: LG_LOG_LEVEL_NONE, LG_LOG_LEVEL_FATAL, LG_LOG_LEVEL_ERROR, LG_LOG_LEVEL_DEBUG, LG_LOG_LEVEL_ALL*/
#define LG_LOG_LEVEL_DEBUG
#else
#define LG_LOG_LEVEL_NONE
#endif
- 判斷等級
// 根據設置的等級,判斷需要打印哪些等級的日誌
#ifdef LG_LOG_LEVEL_NONE
static const int LG_LOG_LEVEL = LGLogLevelNone;
#elif defined(LG_LOG_LEVEL_FATAL)
static const int LG_LOG_LEVEL = LGLogLevelFatal;
#elif defined(LG_LOG_LEVEL_ERROR)
static const int LG_LOG_LEVEL = (LGLogLevelFatal | LGLogLevelError);
#elif defined(LG_LOG_LEVEL_DEBUG)
static const int LG_LOG_LEVEL = (LGLogLevelFatal | LGLogLevelError | LGLogLevelDebug);
#elif defined(LG_LOG_LEVEL_ALL)
static const int LG_LOG_LEVEL = (LGLogLevelFatal | LGLogLevelError | LGLogLevelDebug | LGLogLevelSimple);
#endif
- 區分打印日誌
/**
* 期望在嚴重級別打印,調用LGLogFatal 重要信息,如可能引起崩潰的內容、當前最關係的信息
* 期望在錯誤級別打印,調用LGLogError 錯誤信息,如解析失敗、參數非法、錯誤回調
* 期望在調試級別打印,調用LGLogDebug 調試信息,如請求結果、參數內容
* 僅在打印所有信息時打印,調用LGLogSimple 次要信息,如日誌上報記錄、網絡狀態改變
*/
#define LGLogFatal(fmt, ...) \
if (LG_LOG_LEVEL & LGLogLevelFatal){LGLog(fmt, ##__VA_ARGS__);}
#define LGLogError(fmt, ...) \
if (LG_LOG_LEVEL & LGLogLevelError){LGLog(fmt, ##__VA_ARGS__);}
#define LGLogDebug(fmt, ...) \
if (LG_LOG_LEVEL & LGLogLevelDebug){LGLog(fmt, ##__VA_ARGS__);}
#define LGLogSimple(fmt, ...) \
if (LG_LOG_LEVEL & LGLogLevelSimple){LGLog(fmt, ##__VA_ARGS__);}
/** 解決日誌打印不全問題, 如果想總是打印日誌(包括線上環境),調用LGLog*/
#define LGLog(fmt, ...) do{ \
fprintf(stderr, "%s %s\n%s [Line %d]\n%s\n",\
[[NSDate date] description] UTF8String],\
[@"**********打印信息***********" UTF8String],\
__PRETTY_FUNCTION__, __LINE__,[[NSString stringWithFormat:(fmt), ##__VA_ARGS__] UTF8String]);\
}while(0)
注意:這裏打印的時間精確度不是很高,我自己是寫了一個時間格式化的分類方法,將時間精確到毫秒後6位:yyyy-MM-dd HH:mm:ss.SSSSSS
使用
我們只需要在設置等級的位置,根據需求設置對應的日誌等級。開發的過程中,在適當的地方調用適當的打印方法就行了,比如數據解析錯誤時,調用LGLogError()
;收到網絡請求的響應時,調用LGLogDebug()
。
- 屏蔽所有日誌,只打印正在開發的模塊的日誌
我們預留了重要日誌等級LG_LOG_LEVEL_FATAL
,開發新模塊時,可以把日誌等級設置成LG_LOG_LEVEL_FATAL
,然後該模塊中都使用LGLogFatal()
,開發完成後,全局搜索LGLogFatal()
並替換成適當的方法。 - 只打印某個類型的日誌
假如我們現在要關注LGLogLevelSimple
類型日誌,我們必須設置日誌等級爲LG_LOG_LEVEL_ALL
,但是怎麼屏蔽其他的日誌類型呢。其實很簡單,在判斷等級的位置做一些少許的改動,調試完之後再設置回去就好了。
注意設置的日誌等級一定要包含你想關注的那類日誌。
#ifdef LG_LOG_LEVEL_NONE
#elif defined(LG_LOG_LEVEL_ALL)
static const int LG_LOG_LEVEL = LGLogLevelSimple; // 暫時修改爲LGLogLevelSimple,只有調用LGLogSimple()的地方纔能打印日誌
#endif
- 舊項目折中方案
對於舊項目我們沒有必要每個位置都替換,先把一些廣泛使用的基類裏面的打印替換掉。選擇性的把一些打印內容很多,但不是很關心的日誌替換調。