寫代碼總免不了要看日志。就C++而言,不少程序員只是簡單地用printf來輸出日志,或者臨時寫個日志類,log4cpp等比較“重型”的日志庫的使用率反而並不怎麼高(至少從我經歷的項目而言)。也許是不想為不需要的功能付出額外的學習成本,但無論如何,對於通用類別的工具采取臨時手寫的方式來應付,從長遠考慮,在功能性和健壯性方面是得不償失的。寫這個日志類(yaolog)的最初的想法只是為了實現“輸出到文件的帶有時間信息的printf”,後來歷經不同項目需求的“拷問”,借鑒和引用了很多開源代碼(在此對那些作者表示感謝),就成了現在這個樣子。yaolog的主要特點如下: # printf風格的接口,包括LOGA__, LOGW__, LOG__, LOGBIN__ # 日志附加信息包括時間,源代碼文件,函數,行號 # 每個日志對象都有單獨的行為 # 在程序運行時通過配置ini文件動態改變日志行為 # 可以輸出到控制台窗口,文件,http服務器 # 線程安全 # 跨平台(windows, linux) 這裡有一個重點就是盡可能的簡單,我對接口修改過多次,為了盡量做到簡單易用和自解釋。而上述功能都是從實際項目的需求中提煉出來的,比如為什麼每個日志對象需要有單獨的行為?看日志文件最大的煩惱就是內容太多太雜不容易找到需要的,那麼yaolog給出一種解決方法是設置不同的日志對象,如果想專門查看socket日志,可以只啟用socket日志對象,或者將socket日志專門輸出到一個文件,而這些都是可以在程序運行時動態配置的。又比如發送日志到http服務器,起因於某次有個用戶在QQ上報了一個bug,這個bug如果在有日志的debug版本下應該能很快確定原因,但是release版本是沒有日志的。當然,也可以給用戶一個帶日志的dll去替換,但是這種方法至少存在兩個問題:版本控制(新的dll和用戶原來的dll一致嗎)和日志查看(用戶怎樣將日志提交給開發人員,不要高估了小白)。於是就想到要在服務器端控制日志的啟用,以及將日志內容發送到服務器進行分析。 yaolog v1.3的代碼和demo在這裡 另外我在codeproject上發了一篇詳細說明,地址在這裡 如果你覺得這個工具好用請回帖支持一下。本人畢竟水平有限,如果你發現bug或其他不足之處,也請回帖多多指教哈! 下面貼一段簡單的測試代碼: [cpp] #include <iostream> #include "yaolog.h" // 日志對象的ID,可以自定義,不能雷同 #define LOGID_I "info" #define LOGID_C "custom" #define LOGID_B "bin" int main() { // 初始化,在程序入口點調用 YaoUtil::LogFactory::Init(); // 創建日志對象 YaoUtil::LogFactory::Create(LOGID_I, true); YaoUtil::LogFactory::Create(LOGID_C, true); YaoUtil::LogFactory::Create(LOGID_B, true, false); LOGA__(LOGID_I, "My name is %s! I'm %d!", "neil", 29); // 設置日志對象的屬性:輸出日志到控制台窗口和文件 YaoUtil::LogFactory::SetAttr(LOGID_I, true, YaoUtil::LOGOUT_FLAG_STDOUT | YaoUtil::LOGOUT_FLAG_FILE, true, false, true, true); LOGW__(LOGID_I, L"My name is %s! I'm %d!", L"neil", 29); // 設置日志對象的屬性:輸出日志到文件和http服務器 YaoUtil::LogFactory::SetAttr(LOGID_I, true, YaoUtil::LOGOUT_FLAG_FILE | YaoUtil::LOGOUT_FLAG_REMOTE, true, true, true, true, false, "c:\\", "tt.log", "http://192.168.1.200/default.aspx"); LOG__(LOGID_I, _T("My name is %s! I'm %d!"), _T("neil"), 29); // 設置日志對象的屬性:使用ini文件 YaoUtil::LogFactory::SetAttrFromConfigFile(LOGID_C, "logconfig.ini"); for (int i = 0; i < 100; i++) { LOGA__(LOGID_C, "You can modify the ini file and view effect(%d)!", i); Sleep(500); } // 二進制日志 YaoUtil::LogFactory::SetAttrFromConfigFile(LOGID_B, "logconfig.ini"); char buf[10] = { 0,1,2,3,4,5,6,7,8,9 }; LOGBIN__(LOGID_B, buf, 10); std::cin.get(); // 清理,在程序退出前調用 YaoUtil::LogFactory::Exit(); return 0; }