iOS關於日誌模式及日誌級別

需求

在開發中咱們常常要經過Log(日誌)來調試問題, 而上線後不須要打印Log,並且日常開發每作一個模塊若是能夠將log按照級別打印出來,對分析問題幫助很大.bash


實現原理

經過導入一個頭文件以實現開啓或關閉Log模式,實現選擇Log級別.經過導入#include <syslog.h>以實現打印不一樣級別的Log.app

爲何使用syslog ? 由於它不只能夠在Xcode控制檯打印信息,還可能在Mac終端中打印出日誌信息,這樣的好處是好比咱們有一個app store的app出了問題,咱們能夠在app中調節log level到debug模式,而後使用數據線鏈接設備, 這樣再復現問題能夠將相關的Log即時打印出來.對分析問題幫助很大.函數


簡要分析

1. Log模式

爲何設置log模式,很簡單,由於上線後的app沒必要打印log, 並且若是開發中想取消全部相關打印也能夠直接經過該宏定義決定.ui

本例中若是在代碼中定義了kXDXDebugMode則啓用打印log模式,不然關閉.spa

2. Log級別

本例中經過五個函數來打印不一樣級別log,以下debug

#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");
複製代碼

好比咱們在開發中可能獨立承擔一個模塊,而此模塊單單作完若是出現問題就須要調試,可是若是咱們的Log足夠清晰是能夠迅速幫助咱們找到問題所在,這裏將Log分爲5個級別調試

如下是我的對於打印Log的一些建議,並非說必定要按照以下.日誌

  • XDX_IOS_FLAG_FATAL : 嚴重級別

此類錯誤出現時,代表程序由於某某問題已經完全沒法運行下去,咱們在使用此log時能夠附加說明當前碰到的重大問題及產生緣由,以便調試.code

  • XDX_IOS_FLAG_ERROR : 出錯級別

此類打印可用於出現通常錯誤,好比某個方法調用返回失敗, 由於通常而言代碼預期是正確的, 因此此類Log不會打印的太頻繁, 打開此級別後咱們能夠清晰看到程序哪些地方出現問題.視頻

  • XDX_IOS_FLAG_WARN : 警告級別

此類錯誤通常較低於error級別,即在一些可能出錯的地方, 但實際並無出錯, 好比當視頻幀數量小於0表示出錯狀況,咱們爲了預防,能夠在視頻幀數量小於5時使用此類添加一條預防的Log.

  • XDX_IOS_FLAG_INFO : 重要信息級別

此類級別通常用於打印模塊中一些重要的點, 好比咱們能夠在某個類初始化完成時打印此類中初始化好的一些重要信息,或者在使用某個功能前作一個打印,這樣對於追蹤代碼十分有效.

  • XDX_IOS_FLAG_DEBUG : 調試級別

此類級別代表咱們當前正在臨時打印一些log爲了去調試程序, 或者說咱們爲了觀察某個現象可是須要頻繁打印, 好比相機回調中打印時間戳,由於相機每秒鐘出來幾十幀數據,因此打印十分頻繁,咱們可使用此級別在開發中做爲調試信息,通常不建議在正常使用中開啓此級別.

綜上所述,即log級別越高,log數量應該是越少,這樣咱們能夠在開發中根據如上所述的狀況合理選擇使用哪一個級別的log. Log級別是有包含關係的, 即低的log級別能夠包含比自身高的log級別.

3. 模塊名

這裏封裝的格式以下,即一條log分爲兩部分,前面是模塊名,後面是具體log內容,使用這種格式能夠幫助咱們經過過濾某個模塊中的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,因此OC中的格式符%@是不可用的.可是任何OC中的字符串均可經過UTF8String轉爲C語言字符串,因此並不影響咱們的使用.

5. 使用方式

  • 每次編譯前設置log級別

若是不須要在項目中經過UI動態更改log級別,則能夠直接使用以下方式將頭文件拖入項目,而後在須要使用log的地方將其導入.這種方式簡單方便,僅僅經過每次運行前更改宏定義便可轉變log級別.

  • 在運行後經過UI更改

那麼須要將頭文件的XDX_IOS_LOG_LEVEL全局靜態變量換爲外部變量,而後取消下面這段代碼,最後在控制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

複製代碼

具體實現

#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


複製代碼
相關文章
相關標籤/搜索