昨天有個朋友在評論的時候問我如下代碼在web開發中有什么問題
public void Log(string msg) { System.IO.File.AppendAllText(Server.MapPath("~/log.txt"), msg); }
這里能說的點太多了....只好新開一個文章來說,而且也只是選重點的說
功能
1.線程不安全
asp.net是原生的多線程的框架,那么日志類必須是多線程安全的, 該類庫內部使用了File類來附加日志,而這個部分不是線程安全的,這里有一個BUG (windows資源.例如網絡 文件 在asp.net中都要注意多線程同步)
改進方案:最最簡單的辦法是加lock,(其他的改進方案之后再提)
2.方法未做輸入檢查
所有public的輸入參數 要做輸入值檢查,如果是null或者是empty,那么就不要再調用File類寫日志, 這樣會有性能和健壯性上的提高(最常見的問題就是未將對象引用到設置對象的實例)
解決方案:做輸入值檢查
3. IIS默認帳號對於 Server.MapPath("~/log.txt") 這個路徑是沒有寫入/修改權限的 (可能在生產環境你才會發現這個問題)
解決方案:配置IIS帳號權限,或者是配置一個有權限的目錄 (推薦后者)
4.未做try catch( 是否需要try catch,要考慮實際情況)
一般來說寫日志的方法是不會拋出異常的,如果沒有catch( 可以在內部 也可以在外部catch,我個人推薦外部) 會導致程序/邏輯中止
絕對要避免日志這樣的非核心邏輯 導致業務邏輯的中止
安全性
1.將日志寫入網站根目錄是一種高風險的行為,第一是需要額外的權限,第二是有可能存在寫入程序文件(例如有些人寫入aspx文件)
解決方案:配置一個網站根目錄外的日志目錄
性能
1.采用異步寫入的方式提高性能
即 寫入隊列,定時刷新隊列到數據文件; 由於寫入的瓶頸一般在IO上,這樣的話性能會好很多;當然,如果忽然斷電,就有可能丟失數據 (小概率事件,我們考慮性能多過這一點小瑕疵)
這也是我最喜歡的方式,但是該方式需要開發人員有較高的水平,而且方案復雜,開發時間長...唯一的好處就是性能高....寫日志響應時間短
2.采用其他的寫日志的方式
例如CLFS windows2008開始支持common log file system,
如果不是windows 2008 直接打開一個FileStream 然后保存在本地變量中會更好, 不要每寫一條日志都打開文件又關閉
3.將實例方法替換為靜態方法(或者至少使用call而不是callvirt來調用方法) [具體使用具體分析]
擴展性和可維護性
1.日志路徑不應該是寫死的Server.MapPath("~/log.txt") 這樣這個日志只能被web程序使用,而不能被windows form 或者服務器應用程序等其他應用程序使用
2.日志路徑不應該寫死,而是應該可配置,至少應該有一個獨立的成員存儲(可預期寫日志的方法必然有非常多的重載)
3.日志類這種基本類庫一般使用靜態方法, 好歹不要每次使用都new一個 [具體使用具體分析]
4.有可能的話,第三方類庫,例如log4net是一個比較好的方案
5.如果是生產環境的代碼,這個命名還有注釋都是完全不合格的..
6.不推薦使用完整的命名空間 (文本太多...煩 哈哈)
就一個寫日志的方法,我們做設計的時候,總是要考慮:(優先級和項目類型有關)
1.團隊能否有足夠的能力完成
2.開發時間
3.復雜程度 (導致維護成本上升)
4.程序穩定性
5.性能
6.目前已經存在的技術體系和類庫. (復用性啊什么的...)
7.其他的和一時想不起來的因素(例如大老板說要這么做......好吧 你是老板你說了算 哈哈 just kidding)
可能考慮的還不夠全面,畢竟時間有限...最近太忙了
如有遺漏 還請各位幫忙補充下
具體的代碼就不提供了, 一般我們做日志都是公司級的日志, 所有的服務器會通過網絡傳輸到日志集群服務器, 這和簡單的文件日志是完全不一樣的體系
簡單的文件日志,我們也會用很簡單方式來寫入.....(在某些項目中,最簡單就是最適合,)
項目類型和開發時間需要, 稍微復雜點的我們會用log4net之類的第三方日志庫來做
最簡單的日志也許幾分鍾就寫好了, 最復雜的日志做了幾個月才是一個架子.......