PHP框架中的日誌系統

 

 如今在一家公司作PHP後臺開發程序猿(咱們組沒有前端,作活動時會作前端的東西),剛開始到公司的時候花2個周趕出了一個前端加後臺的活動(記得當時作不出來週末加了兩天班、、、),到如今過去4個多月了,能夠用一下午秒掉一個不是很複雜的活動,固然瞭如今作的時候會考慮不少東西,好比說擴展性、可重用性,由於作的多了,會積累不少相似小插件的東西,因此會很快。。。。。。可是我發現成天「站在需求裏面作需求」不好勁,這樣不會學到系統的、框架類的東西,由於都被瑣碎的需求給困住了,沒有時間去作一些框架重要部分的東西,並且當你的同事、上司習慣了你去作那些事的時候,每次遇到那些沒技術含量的但又不得不作的東西都會堅決果斷的推給你(自私點的說,每一個程序猿都像我同樣吧,都想掌握一塊有技術含量的東西,這樣纔有程序猿的自豪感),長此以往你就會習慣、、、、、、這樣真的很慘,因此,我會抽出點時間來學習下框架中的東西,爭取不作一個簡單的碼農。php

引言

    接觸過php框架的朋友們可能都知道,日誌在項目中的重要做用了,他能夠幫助咱們定位錯誤的位置,讓程序更友好(處理得當的話不會直接拋出一大堆只有程序猿才真正動的英文),調試的時候也會很方便,還能夠記錄一些重要的操做等等,總之一個完整的項目要是沒了日誌系統,就已經開發的路上佈滿了荊棘、坑窪,確定會磕磕絆絆的。前端

 

簡介

    要掌握PHP日誌系統,必須先對這幾點東西瞭解透徹。git

1、php的幾個函數

 1 set_exception_handler(callback $exception_handler); //異常捕獲自定義處理函數註冊 github

 

 1 set_error_handler(callback $error_handler); //錯誤捕獲自定義處理函數註冊 bootstrap

 

 1 register_shutdown_function(callback $callback); //程序執行時異常終止錯誤捕獲處理函數註冊 數組

    這三個函數在錯誤處理控制中給開發者提供了很大的自主空間,在日誌系統中記錄日誌信息有他們的功勞。php框架

    在程序中出現異常(exception)問題時,php內核會拋出異常錯誤,而後將錯誤信息打印給使用者,若是註冊了exception處理函數,php拋出的異常會轉給自定義的註冊的異常捕獲函數,這個函數裏面包含了咱們要作的處理,記錄錯誤信息(包括錯誤詳細內容、錯誤位置),該函數處理完異常後,異常就會終止。app

    當程序中出現error時,咱們註冊的error處理函數會在函數中將錯誤信息轉化爲一個錯誤異常對象傳遞給異常處理函數,也就是第一步的$exception_handler函數。框架

    當成續重出現shutdown錯誤時,會執行咱們註冊的異常終止處理函數,該函數經過error_get_last()獲取到最後的shutdown時的錯誤對象,接着和上一部同樣,生成一個error exception對象,將該對象傳遞給咱們註冊的異常處理函數。函數

    能夠看到,其實不論是異常仍是錯誤,都是將本身的信息轉化爲異常處理函數認識的異常信息,而後交給異常處理函數處理,非異常信息就像化了妝的女人同樣,異常處理程序不認識這些非異常信息,只有將裝卸掉(非異常信息本身轉化爲異常信息,準確的說應該是拋出),異常處理才認識。

php日誌系統中的錯誤處理流程

    那麼如今問題來了,這幾個函數通常會配合一個異常處理類庫,加上一個錯誤日誌記錄類庫來進行工做,異常處理類庫中包含要註冊的3個函數,日誌記錄類庫在$exception_handler中調用,用來合理的記錄和放置日誌文件的位置,上面說到的幾個函數通常是在程序框架入口處進行加載註冊的,就像下面這樣:

這裏面用的是array(class,function)這種方式。

 

1 set_exception_handler(array("Myexception","exceptionHandler"));
2 set_error_handler(array("Myexception","errorHandler"));
3 register_shutdown_function(array("Myexception","shutdownHandler"));

 

 

 

2、日誌記錄相關類庫

    第一部分介紹到的東西只是對異常、錯誤、shutdown進行了捕獲,這只是第一步,接下來還要對捕獲到的信息進行合理的處理,好比說記錄這些日誌信息到本地文件系統中(這個操做是在array("Myexception","exceptionHandler")),這個地方就用到了日誌記錄類庫。(下面要說的類庫是借鑑了kohana日誌系統的設計)。

    日式日誌記錄也很簡單隻要作的將信息添加到文件末尾就行,這個很容易實現,相信你們均可以本身實現,可是要設計出一個便捷的、高效的、擴展的日誌記錄類庫就不那麼簡單了,要通過長時間的實踐總結優化才能夠,kohana框架中的日誌記錄類庫已經比較成熟了,所以這裏拿來借鑑。

    相信使用過kohana的用戶必定對kohana框架中的日誌記錄比較熟悉,不熟悉也不要緊,我下面會大概的說說,在kohana源碼中的application/bootstrap.php文件中的第109——112行能夠看到下面的代碼:

 

109 /**
110  * Attach the file write to logging. Multiple writers are supported.
111  */
112 Kohana::$log->attach(new Log_File(APPPATH.'logs'));

 

    這個就是添加一個日誌記錄對象日誌對象中,注意橄欖色打底的倆個,他們是不一樣的類庫實例,在kohana中,日誌記錄對象分爲兩部分,第一部分就是日誌對象,用來維護一個日誌記錄對象的列表,這個要怎麼理解呢,其實就像一個容器,裏面包含了一個或多個日誌記錄對象(這個就是第二部分,這些日誌記錄對象纔是真正來記錄日誌的),還有每一個對象要記錄的錯誤等級的數組,當知足錯誤等級的時候纔會去記錄,不知足就會略掉。下面是我本身簡化重命名後的日誌記錄方式:

1 self::$log = Log::instance();
2 self::$log->attach(new Logwriter("./data/debug"),Log::DEBUG);
3 self::$log->attach(new Logwriter("./data/notice"),Log::NOTICE);

    我這裏面爲了更好地理解,將「容器」命名爲Log,記錄的實例命名爲Logwriter,能夠看到我在程序入口處很容易的添加了兩不一樣的日誌種類,第一個是記錄全部錯誤號比Log::DEBUG小的錯誤(錯誤級別比他高),並按規則記錄在文件夾./data/debug下面,第二個是記錄級別等於或高於Log::NOTICE的錯誤,固然了你還能夠更詳細制定具體哪些錯誤好,傳遞數組就好了,這個就是我感受方便、快捷的地方,咱們能夠根據需求來添加錯誤日誌、分不一樣的日誌目錄,下面看一幅圖也許會有助於理解:

                                                                                                      log與logwriter的關係

    經過上面的圖你就會看到Log是一個容器,包含了具體的不一樣的logwriter對象,每一個對象可能要記錄不一樣的信息,當錯誤信息要刷到文件中的時候,會運行每個Logwriter實例,看看本身是否要記錄errormessage中的錯誤,errormessage中的level不包含在Logwriter內時忽略。

    這本分和第一部分怎麼合做的呢?其實很簡單,當exception捕獲的異常時會調用添加一條錯誤信息(包括錯誤位置、錯誤代號、錯誤信息等信息)到Log容器中的errormessage數組中,而後當程序結束以後在將這些信息寫入文件,這裏還要注意下,也許你在閱讀kohana代碼是發現沒有明顯的直接寫入到日誌中去,這裏面kohana優化的比較好,由於php的一次執行可能出現多個錯誤,若是來一個錯誤你就去記錄一次這樣會在程序返回以前佔用多餘的io和時間,因此kohana的作法是默認將全部的錯誤、異常、日誌存放在Log::$errormessage中,並在實例化的時候講Log中的writer操做註冊register_shutdown_function,這個函數的做用是在程序異常終止或者執行完成以後執行,前面第一部分也有使用到,這樣日誌記錄就不會對本次php的執行產生帶大的影響。

3、實例總結

    到這裏你應該已經瞭解了日誌系統的大概了,已經能夠本身編寫一個」日誌系統」來使用了,下面看看個人」日誌系統「的例子,這是github地址,裏面有代碼和例子,須要的話能夠看看。

https://github.com/AizuYan/phplog.git2014-12-13_163228

 

本文版權歸做者(luluyrt@163.com)和博客園共有,未經做者本人贊成禁止任何形式的轉載,轉載文章以後必須在文章頁面明顯位置給出做者和原文鏈接,不然保留追究法律責任的權利。

相關文章
相關標籤/搜索