本身寫的日誌框架--linkinLog4j--日誌框架的必要性


OK,在開始研究Log4j的源碼以前,咱們先來本身模擬一個日誌工具,名字就叫linkinlog4j好了。html

在軟件開發過程當中,出現bug老是在所不免;事實上,以我我的經驗,即便在實際開發階段,fix bug時間要遠超過寫代碼的時間。在開發階段,比較有效的fix bug的方法固然是調試,然而若是代碼比較複雜,並且開始對代碼不是很熟悉,那麼咱們很容易在方法調用之間迷失方向;若是bug出如今多線程環境中,那麼不少時候調試就無能爲力了;另外當代碼部署到服務器上運行時,不論是在UAT測試環境仍是Production環境,此時要調試不少時候是不可能。相信有過幾年工做經驗的碼農在和運維,測試交流的時候常常說起的日誌級別了。java


爲了解決這些問題,咱們能夠在開發過程當中事先在一些關鍵點上打印出一些日誌信息(log),以利於在出問題後能知道當時運行的環境信息,特別是在production上,咱們能夠分析log以肯定問題所在,固然前提log信息足夠多。不過加入日誌信息後,不難想象,它會對程序的運行性能產生必定的影響,並且若是log過多會致使有用的信息不容易找到,若是過少又不具有很大的參考價值,這樣的日誌除了下降程序的性能,貌似對其餘方面沒有幫助。服務器


關於性能,Log4J號稱在這面作了不少優化,可是聽說logback作的更好(logback的源碼還沒來得及看,只是簡單的用過,因此還不是很瞭解);而關於如何寫log、在哪裏寫log、要把那些信息寫入log中,我的感受這是一門很大的學問,並且也是根據不一樣項目而不一樣,我以菜鳥身份在這裏也就很少作贅述了。多線程



OK,如今咱們先來本身寫一個測試類,而後經過System.out打印到控制檯。代碼以下:
package test.junit4test;


import org.junit.Test;


public class LinkinLogTest
{


	@Test
	public void testLog()
	{
		System.out.println("測試方法開始。。。");
		try
		{
			throw new NullPointerException("這裏人工拋出一個異常!");
		}
		catch (Exception e)
		{
			System.out.println("人工捕獲一個異常" + e.getMessage());
			e.printStackTrace(System.out);
		}
		System.out.println("測試方法結束。。。");
	}


}

運行下面的代碼,控制檯輸出以下:
測試方法開始。。。
人工捕獲一個異常這裏人工拋出一個異常!
java.lang.NullPointerException: 這裏人工拋出一個異常!
	at test.junit4test.LinkinTest.testLog(LinkinTest.java:14)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
測試方法結束。。。
OK,沒有問題。可是這段代碼有這很明顯的缺陷: 1,咱們這些日誌只能打印在控制檯。那麼若是咱們發佈了咱們的項目到咱們的服務器,咱們須要查看的是日誌文件而不是控制檯了。 2,這裏咱們本身寫的這個日誌類沒有提現等級,若是我想控制不一樣的級別來控制某些的內容的輸出和不輸出,即便咱們這裏加了一個flag旗標,也沒有從根本上解決問題。 3,如今咱們的日誌的內容都是比較簡單,若是咱們想要在控制檯顯示咱們的日誌的類名,方法運行的時間,所在的線程等等這些內容時,就要不停的重複的寫一堆代碼。 4,不少的時候咱們但願咱們的日誌按照某種約定來生成,好比說按照日期,按照文件的大小存檔,這個時候咱們上面的那段代碼根本實現不了。 OK,問題不少,那咱們來一步一步的解決吧。
相關文章
相關標籤/搜索