iOS關(guān)于日志模式及日志級別

需求

在開發(fā)中我們經(jīng)常要通過Log(日志)來調(diào)試問題, 而上線后不需要打印Log,而且平常開發(fā)每做一個模塊如果可以將log按照級別打印出來,對分析問題幫助很大.


實現(xiàn)原理

通過導(dǎo)入一個頭文件以實現(xiàn)開啟或關(guān)閉Log模式,實現(xiàn)選擇Log級別.通過導(dǎo)入#include <syslog.h>以實現(xiàn)打印不同級別的Log.

為什么使用syslog ? 因為它不僅可以在Xcode控制臺打印信息,還可能在Mac終端中打印出日志信息,這樣的好處是比如我們有一個app store的app出了問題,我們可以在app中調(diào)節(jié)log level到debug模式,然后使用數(shù)據(jù)線連接設(shè)備, 這樣再復(fù)現(xiàn)問題可以將相關(guān)的Log即時打印出來.對分析問題幫助很大.


簡要分析

1. Log模式

為什么設(shè)置log模式,很簡單,因為上線后的app不必打印log, 而且如果開發(fā)中想取消所有相關(guān)打印也可以直接通過該宏定義決定.

本例中如果在代碼中定義了kXDXDebugMode則啟用打印log模式,否則關(guān)閉.

2. Log級別

本例中通過五個函數(shù)來打印不同級別log,如下

#define kModuleName "Hello"
...
    int i = 1; int j = 2;
    log4cplus_fatal(kModuleName, "world1 , %d,%d",i,j);
    log4cplus_error(kModuleName, "world2");
    log4cplus_warn(kModuleName, "world3");
    log4cplus_info(kModuleName, "world4");
    log4cplus_debug(kModuleName, "world5");

比如我們在開發(fā)中可能獨立承擔(dān)一個模塊,而此模塊單單做完如果出現(xiàn)問題就需要調(diào)試,但是如果我們的Log足夠清晰是可以迅速幫助我們找到問題所在,這里將Log分為5個級別

以下是個人對于打印Log的一些建議,并不是說一定要按照如下.

  • XDX_IOS_FLAG_FATAL : 嚴(yán)重級別

此類錯誤出現(xiàn)時,表明程序因為某某問題已經(jīng)徹底無法運行下去,我們在使用此log時可以附加說明當(dāng)前碰到的重大問題及產(chǎn)生原因,以便調(diào)試.

  • XDX_IOS_FLAG_ERROR : 出錯級別

此類打印可用于出現(xiàn)一般錯誤,比如某個方法調(diào)用返回失敗, 因為一般而言代碼預(yù)期是正確的, 所以此類Log不會打印的太頻繁, 打開此級別后我們可以清晰看到程序哪些地方出現(xiàn)問題.

  • XDX_IOS_FLAG_WARN : 警告級別

此類錯誤一般較低于error級別,即在一些可能出錯的地方, 但實際并沒有出錯, 比如當(dāng)視頻幀數(shù)量小于0表示出錯情況,我們?yōu)榱祟A(yù)防,可以在視頻幀數(shù)量小于5時使用此類添加一條預(yù)防的Log.

  • XDX_IOS_FLAG_INFO : 重要信息級別

此類級別一般用于打印模塊中一些重要的點, 比如我們可以在某個類初始化完成時打印此類中初始化好的一些重要信息,或者在使用某個功能前做一個打印,這樣對于追蹤代碼十分有效.

  • XDX_IOS_FLAG_DEBUG : 調(diào)試級別

此類級別表明我們當(dāng)前正在臨時打印一些log為了去調(diào)試程序, 或者說我們?yōu)榱擞^察某個現(xiàn)象但是需要頻繁打印, 比如相機(jī)回調(diào)中打印時間戳,因為相機(jī)每秒鐘出來幾十幀數(shù)據(jù),所以打印十分頻繁,我們可以使用此級別在開發(fā)中作為調(diào)試信息,一般不建議在正常使用中開啟此級別.

綜上所述,即log級別越高,log數(shù)量應(yīng)該是越少,這樣我們可以在開發(fā)中根據(jù)如上所述的情況合理選擇使用哪個級別的log. Log級別是有包含關(guān)系的, 即低的log級別可以包含比自身高的log級別.

3. 模塊名

這里封裝的格式如下,即一條log分為兩部分,前面是模塊名,后面是具體log內(nèi)容,使用這種格式可以幫助我們通過過濾某個模塊中的Log, 十分直觀清晰

#define log4cplus_fatal(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_FATAL) \
syslog(LOG_CRIT, "%s:" logFmt, category,##__VA_ARGS__); \

舉例如下:

#define kModuleName "Hello"

...


- (void)test {
    int i = 0;
    log4cplus_debug(kModuleName, "Hello World - %d",i);
}

4. 注意

因為我們使用的syslog,所以O(shè)C中的格式符%@是不可用的.但是任何OC中的字符串都可通過UTF8String轉(zhuǎn)為C語言字符串,所以并不影響我們的使用.

5. 使用方式

  • 每次編譯前設(shè)置log級別

如果不需要在項目中通過UI動態(tài)更改log級別,則可以直接使用如下方式將頭文件拖入項目,然后在需要使用log的地方將其導(dǎo)入.這種方式簡單方便,僅僅通過每次運行前更改宏定義即可轉(zhuǎn)變log級別.

  • 在運行后通過UI更改

那么需要將頭文件的XDX_IOS_LOG_LEVEL全局靜態(tài)變量換為外部變量,然后取消下面這段代碼,最后在控制UI的類中定義并通過交互更改此值即可.

#ifdef XDXLogLevelFatal
static const int XDX_IOS_LOG_LEVEL = XDX_IOS_FLAG_FATAL;
#elif defined(XDXLogLevelError)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR);
#elif defined(XDXLogLevelWarn)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN);
#elif defined(XDXLogLevelInfo)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN | XDX_IOS_FLAG_INFO);
#elif defined(XDXLogLevelDebug)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN | XDX_IOS_FLAG_INFO | XDX_IOS_FLAG_DEBUG);
#endif

具體實現(xiàn)


#include <syslog.h>
#ifndef XDX_IOS
#define XDX_IOS
#endif

#pragma - Please select your log mode and log level

// Note: Only debug mode will print log. You could also set mode for log level.
#define kXDXDebugMode
// XDXLogLevelFatal , XDXLogLevelError , XDXLogLevelWarn , XDXLogLevelInfo , XDXLogLevelDebug
#define XDXLogLevelDebug

#pragma ----------------------------------

#ifdef kXDXDebugMode

static const int XDX_IOS_FLAG_FATAL = 0x10;
static const int XDX_IOS_FLAG_ERROR = 0x08;
static const int XDX_IOS_FLAG_WARN  = 0x04;
static const int XDX_IOS_FLAG_INFO  = 0x02;
static const int XDX_IOS_FLAG_DEBUG = 0x01;

#ifdef XDXLogLevelFatal
static const int XDX_IOS_LOG_LEVEL = XDX_IOS_FLAG_FATAL;
#elif defined(XDXLogLevelError)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR);
#elif defined(XDXLogLevelWarn)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN);
#elif defined(XDXLogLevelInfo)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN | XDX_IOS_FLAG_INFO);
#elif defined(XDXLogLevelDebug)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN | XDX_IOS_FLAG_INFO | XDX_IOS_FLAG_DEBUG);
#endif



#define log4cplus_fatal(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_FATAL) \
syslog(LOG_CRIT, "%s:" logFmt, category,##__VA_ARGS__); \

#define log4cplus_error(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_ERROR) \
syslog(LOG_ERR, "%s:" logFmt, category,##__VA_ARGS__); \

#define log4cplus_warn(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_WARN) \
syslog(LOG_WARNING, "%s:" logFmt, category,##__VA_ARGS__); \

#define log4cplus_info(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_INFO) \
syslog(LOG_WARNING, "%s:" logFmt, category,##__VA_ARGS__); \

#define log4cplus_debug(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_DEBUG) \
syslog(LOG_WARNING, "%s:" logFmt, category,##__VA_ARGS__); \


#else

#define log4cplus_fatal(category, logFmt, ...); \

#define log4cplus_error(category, logFmt, ...); \

#define log4cplus_warn(category, logFmt, ...); \

#define log4cplus_info(category, logFmt, ...); \

#define log4cplus_debug(category, logFmt, ...); \

#endif


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末岂膳,一起剝皮案震驚了整個濱河市洲劣,隨后出現(xiàn)的幾起案子觉至,更是在濱河造成了極大的恐慌柄粹,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件状原,死亡現(xiàn)場離奇詭異侨嘀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門絮爷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來趴酣,“玉大人,你說我怎么就攤上這事坑夯♂” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵柜蜈,是天一觀的道長仗谆。 經(jīng)常有香客問我,道長淑履,這世上最難降的妖魔是什么隶垮? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮秘噪,結(jié)果婚禮上狸吞,老公的妹妹穿的比我還像新娘。我一直安慰自己指煎,他們只是感情好蹋偏,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著至壤,像睡著了一般威始。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上像街,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天黎棠,我揣著相機(jī)與錄音,去河邊找鬼镰绎。 笑死脓斩,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的跟狱。 我是一名探鬼主播俭厚,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼驶臊!你這毒婦竟也來了挪挤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤关翎,失蹤者是張志新(化名)和其女友劉穎扛门,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纵寝,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡论寨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葬凳。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡绰垂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出火焰,到底是詐尸還是另有隱情劲装,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布昌简,位于F島的核電站占业,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏纯赎。R本人自食惡果不足惜谦疾,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望犬金。 院中可真熱鬧念恍,春花似錦、人聲如沸佑附。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽音同。三九已至,卻和暖如春秃嗜,著一層夾襖步出監(jiān)牢的瞬間权均,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工锅锨, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留叽赊,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓必搞,卻偏偏與公主長得像必指,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子恕洲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 用兩個棧來實現(xiàn)一個隊列塔橡,完成隊列的Push和Pop操作。 隊列中的元素為int類型霜第。 java 思路:stack先...
    亮濤閱讀 176評論 0 0
  • 【知識餓死論泌类!】 知識好像錢幣癞谒,有知識不一定活的好,就好像錢幣不能叫我們飽一樣。行動就好像你用錢購買食物弹砚,然后吃下...
    恩典99閱讀 215評論 0 0
  • 今天注冊簡書双仍,帶給我力量,快樂桌吃,自由吧J庑!!读存!
    流落人間的悟空閱讀 119評論 0 0
  • 英語 light comes from a light source and either enters ours...
    encoreMiao閱讀 287評論 0 0