為什么說(shuō)這么一個(gè)標(biāo)題,其實(shí)還是有點(diǎn)故事的锡垄,其實(shí)說(shuō)是故事還不如說(shuō)是事故沦零,慶幸的是還好沒(méi)有造成什么大的問(wèn)題,既然說(shuō)刪了兩臺(tái)服務(wù)器货岭,上個(gè)月確實(shí)是操作刪了兩臺(tái)服務(wù)器路操。由于測(cè)試環(huán)境有問(wèn)題疾渴,客戶就一直讓我們?cè)谡江h(huán)境上開發(fā),所以有時(shí)候就會(huì)造成一些問(wèn)題屯仗,總之很刺激搞坝,也很危險(xiǎn)。
簡(jiǎn)單說(shuō)一下是怎么個(gè)情況吧魁袜,上個(gè)月客戶讓我測(cè)一個(gè)接口瞄沙,但是那個(gè)接口只能在線上測(cè),所以我就點(diǎn)了一個(gè)釋放資源慌核,那個(gè)資源里面就是下發(fā)下去的兩臺(tái)服務(wù)器距境,由于沒(méi)有很好的日志記錄所以當(dāng)時(shí)也不知道到底是誰(shuí)釋放的,當(dāng)然了垮卓,不是我死不承認(rèn)垫桂,而是我也不知道,然后他們查出來(lái)我的電腦IP粟按,直接找過(guò)來(lái)了诬滩,可嚇壞我了,還好人家那兩臺(tái)服務(wù)器沒(méi)有投入使用灭将,讓我以后操作小心一點(diǎn)疼鸟。是不是很刺激。
看了這個(gè)問(wèn)題庙曙,其實(shí)我想說(shuō)一個(gè)問(wèn)題空镜,就是我們的項(xiàng)目當(dāng)時(shí)沒(méi)有很好的日志管理,以至于誰(shuí)刪了服務(wù)器都不知道捌朴,還要去追查一周才能定位到是誰(shuí)干的吴攒,很慢,那么如果有良好的日志記錄砂蔽,誰(shuí)干了什么翻翻日志洼怔,是不是就可以很清楚的知道是誰(shuí)操作的,所以我們今天來(lái)聊聊日志左驾。
一镣隶、日志級(jí)別
在了解日志之前我們首先要知道有哪些日志級(jí)別,開發(fā)中我們使用哪個(gè)級(jí)別诡右,正式的線上環(huán)境我們又使用哪個(gè)級(jí)別安岂。
off ?最高等級(jí),用于關(guān)閉所有的日志記錄稻爬;
fatal ?具有嚴(yán)重的錯(cuò)誤時(shí)間嗜闻,可能導(dǎo)致程序退出;
error ?可能存在錯(cuò)誤時(shí)間的發(fā)生桅锄,但是不會(huì)影響程序的運(yùn)行琉雳;
warn ?存在潛在的錯(cuò)誤样眠;
info ?記錄程序運(yùn)行的過(guò)程;
debug ?會(huì)記錄所有的日志信息翠肘,比info打印的東西更為全面檐束,一般做調(diào)試非常好用;
all ?等級(jí)最低束倍,用于打開所有的日志記錄被丧;
這就是我們?nèi)罩镜募?jí)別,分別從高到低绪妹,日志級(jí)別越高甥桂,記錄的日志信息就越詳細(xì),那么在實(shí)際的開發(fā)中邮旷,我們一般使用debug級(jí)別黄选, 因?yàn)槲覀円春芏嗟娜罩拘畔ⅲ驗(yàn)榭赡艽嬖谝恍〇|西婶肩,我們要通過(guò)日志去進(jìn)行查看办陷,那么在線上的話,我們就一般使用error級(jí)別律歼,因?yàn)槲覀冎恍枰ビ涗浺恍╁e(cuò)誤的東西民镜,一些其他沒(méi)用的信息沒(méi)必要記錄下來(lái),記錄下來(lái)會(huì)比較影響我們的系統(tǒng)的性能险毁。
二制圈、簡(jiǎn)單的配置
接下來(lái)我們介紹一下,如果配置我們的log4j日志信息辱揭,我們輸出的那些東西离唐,究竟是如何進(jìn)行配置的。
首先我們說(shuō)一下文件追加器:
org.apache.log4j.ConsoleAppender?(控制臺(tái));
org.apache.log4j.FileAppender?(文件);
org.apache.log4j.DailyRollingFileAppender?(每天產(chǎn)生一個(gè)日志文件);
其實(shí)文件追加器不止這3種问窃,但是我們這里只說(shuō)常用的集中,通過(guò)追加器我們就可以把日志輸出在控制臺(tái)上完沪,但是輸出在控制臺(tái)上當(dāng)我們清掉控制臺(tái)后域庇,日志就不見(jiàn)了,所以我們可以通過(guò)配置文件追加器把日志寫進(jìn)文件中覆积,方便以后的查閱听皿。
日志如何輸出到文件:
上面已經(jīng)寫過(guò)了,這里我就寫一個(gè)實(shí)例宽档;
log4j.appender.I.File = logs/info/info_
這是我項(xiàng)目中配置的尉姨,那么這個(gè)日志的輸出位置就是在我項(xiàng)目下面的logs文件夾下面有個(gè)info文件夾,就在info_這個(gè)文件中記錄著吗冤。
還有一個(gè)輸出控制臺(tái)的配置又厉,通過(guò)這個(gè)配置九府,我們就可以把日志輸出到控制臺(tái)上
log4j.appender.C.Target = System.out
再就是布局方式,其實(shí)有好集中覆致,但是在開發(fā)中我們常規(guī)的是使用下面這種
log4j.appender.C.layout = org.apache.log4j.PatternLayout
這個(gè)配置的意思就是侄旬,我們的日志是追加到原有的日志文件中去的,如果不設(shè)置為true煌妈,那么每次產(chǎn)生的日志文件都會(huì)覆蓋原來(lái)的日志文件
log4g.appender.I.Append =?true
其實(shí)所有的日志記錄在一個(gè)文件中也不是一個(gè)特別好的辦法儡羔,如果日志很多,找起來(lái)特別麻煩璧诵,也很影響系統(tǒng)的性能汰蜘,所以我們可以通過(guò)配置,讓他一天生成一個(gè)日志文件
log4j.appender.I.DatePattern=yyyy-MM-dd'.log '
這個(gè)其實(shí)就是你打印在控制臺(tái)和記錄在文件中的日志格式
log4j.appender.I.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd-HH-mm}?method:%l\%n%m%n
看個(gè)例子:
這個(gè)是控制臺(tái)打印的信息
這個(gè)是日志文件記錄的信息
這樣你就可以比較清晰的看到我們的日志信息是什么級(jí)別的日志之宿,什么時(shí)間鉴扫,哪個(gè)類,多少行澈缺,你還可以配置你想要的日志格式坪创,我把一些參數(shù)放在下面。
log4j.appender.C.layout.ConversionPattern = %d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n
%m ? 輸出代碼中指定的消息
%p ? 輸出優(yōu)先級(jí)姐赡,即DEBUG莱预,INFO,WARN项滑,ERROR依沮,F(xiàn)ATAL
%r ? 輸出自應(yīng)用啟動(dòng)到輸出該log信息耗費(fèi)的毫秒數(shù)
%c ? 輸出所屬的類目,通常就是所在類的全名
%t ? 輸出產(chǎn)生該日志事件的線程名
%n ? 輸出一個(gè)回車換行符枪狂,Windows平臺(tái)為“/r/n”危喉,Unix平臺(tái)為“/n”
%d ? 輸出日志時(shí)間點(diǎn)的日期或時(shí)間。默認(rèn)格式為ISO8601州疾,也可以在其后指定格式辜限。比如:%d{yyy MMM dd HH:mm:ss , SSS},輸出類似:2002年10月18日 22:10:28, 921
%l ? 輸出日志事件的發(fā)生位置严蓖,包括類目名薄嫡、發(fā)生的線程,以及在代碼中的行數(shù)
還有一點(diǎn)就是下面這個(gè)配置颗胡,上面的有些C I E D可能大家不知道是什么意思毫深,其實(shí)它就是一個(gè)變量,變量前面的debug就是我們?nèi)罩据敵龅募?jí)別毒姨。
log4j.rootLogger =?debug,C,I,E,D
所謂變量其實(shí)就是通過(guò)它配置我們的日志信息哑蔫,下面分別定義了兩個(gè)變量I和E,下面有個(gè)log4j.append.E.Threshold = error這樣一個(gè)配置,其實(shí)就是通過(guò)E這個(gè)變量去定義E闸迷,這個(gè)變量記錄的是error級(jí)別的日志嵌纲,那么有關(guān)error的信息,那么都會(huì)寫進(jìn)這個(gè)對(duì)應(yīng)的文件中
最后把我寫的日志文件信息完整版放在最后稿黍,歡迎大家參考交流:
# C 變量
log4j.rootLogger = debug,C,I,E,D
log4j.appender.C = org.apache.log4j.ConsoleAppender
# 日志輸出位置疹瘦,也可以指定為文件
log4j.appender.C.Target = System.out?
# 布局方式,一般選擇自由方式布局
log4j.appender.C.layout = org.apache.log4j.PatternLayout
# 日志輸出格式
log4j.appender.C.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd-HH-mm}?method:%l\%n%m%n
log4j.appender.I = org.apache.log4j.DailyRollingFileAppender
log4j.appender.I.DatePattern=yyyy-MM-dd-HH'.log '
log4j.appender.I.File = logs/info/info_
log4g.appender.I.Append =?true
log4j.appender.I.Threshold = info
log4j.appender.I.layout = org.apache.log4j.PatternLayout
log4j.appender.I.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd-HH-mm}?method:%l\%n%m%n
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.DatePattern=yyyy-MM-dd-HH'.log '
log4j.appender.E.File = logs/error/error_
log4g.appender.E.Append =?true
log4j.appender.E.Threshold = error
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd-HH-mm}?method:%l\%n%m%n
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.DatePattern=yyyy-MM-dd-HH'.log '
log4j.appender.D.File = logs/debug/debug_
log4g.appender.D.Append =?true
log4j.appender.D.Threshold = debug
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd-HH-mm}?method:%l\%n%m%n