引言:
日志大家都再熟悉不過了,日常開發中經常要用到,甲方介面人最喜歡對我說的話就是“趕緊去查一下日志,快點!”,說話的同時瞪著個銅鈴大的眼睛,

就你介面人知道日志嗎?還要你指揮啊,我心里可真來勁,但是沒辦法誰叫我是乙方的,我想大口喘氣,也得拿手捂著,兄弟們都指著我好好說話呢,我這話一出口,我這一眾兄弟這個月的績效恐怕就打水漂了,

就在我進行心里斗爭的時候,介面人又說了“什么時候能定位到問題,啥時候能解決?”,(甲方規定:超1小時通報、超過2小時扣分、超4小時約談領導、24小時沒搞定打包回家),
下面恭迎今天的主角“日志”大神出場,
什么是日志
日志:記錄程式的運行軌跡,列印一下設定的資訊,比如錯誤,很方便查找關鍵資訊,快速定位解決問題,
Java程式員在開發專案時都是依賴debug來除錯錯誤、跟蹤代碼來解決bug,比如我們開發工具Eclipse/MyEclipse就有很強大錯誤除錯功能,比如我自己就有4個版本的:
(我懷疑你在做廣告)
當然在開發環境下,要除錯這些錯誤很容易,打好斷點跟蹤代碼就行了,但專案發布到了測驗、生產環境怎么辦?不好意思你除錯不了,甲方會斷了一切你可以這么做的念想,所以日志就派上用場了,日志列印的好,就能根據日志的軌跡快速定位并解決線上問題,反之你光憑分析代碼、分析資料,腦細胞胡亂打架是沒法快速解決問題的,日志記錄的資訊能夠很好的幫助開發人家快速定位到問題,并且解決,
記錄日志的方式
有很多記錄日志的方式,比如 log4j、Logging、commons-logging、slf4j 等等,這里呢我就說說我們做專案經常用到的幾種,
log4j
配置文章可以看我的文章 Log4j配置詳解
我用的是 log4j-1.2.15.jar 這個包,將其放在lib下
輸出到控制臺
log4j.properties配置
# DEBUG 日志優先級,stdout(自定義名字) 代表日志輸出到那個地方
log4j.rootLogger= ERROR, stdout
# 設定日志輸出型別 appender負責控制日志記錄操作的輸出 ConsoleAppender:日志資訊輸出到控制臺
log4j.appender.stdout= org.apache.log4j.ConsoleAppender
# 日志自定義格式
log4j.appender.stdout.layout= org.apache.log4j.PatternLayout
# 日志輸出格式為 優先級、 [產生日志事件的執行緒名]、日志資訊、換行
log4j.appender.stdout.layout.ConversionPattern= %5p [%t] %m%n
測驗代碼
package com.log;
import org.apache.log4j.Logger;
public class Log4jTest
{
Logger logger = Logger.getLogger(this.getClass());
public void test()
{
logger.debug("debug print");
logger.info("info print");
logger.warn("warn print");
logger.error("error print");
}
/**
* @param args
*/
public static void main(String[] args)
{
new Log4jTest().test();
}
}
因配置的是ERROR,所以只輸出error的資訊

輸出到日志檔案
log4j.properties配置
# DEBUG 日志優先級,stdout(自定義名字) 代表日志輸出到那個地方
log4j.rootLogger= ERROR, stdout ,myLog
# 設定日志輸出型別 appender負責控制日志記錄操作的輸出 ConsoleAppender:日志資訊輸出到控制臺
log4j.appender.stdout= org.apache.log4j.ConsoleAppender
# 日志自定義格式
log4j.appender.stdout.layout= org.apache.log4j.PatternLayout
# 日志輸出格式為 優先級、 [產生日志事件的執行緒名]、日志資訊、換行
log4j.appender.stdout.layout.ConversionPattern= %5p [%t] %m%n
### 輸出到日志檔案 ###
log4j.appender.myLog = org.apache.log4j.DailyRollingFileAppender
log4j.appender.myLog.File = E:\\testlog\\log4j\\server.log
log4j.appender.myLog.Append = true
## 只輸出DEBUG級別以上的日志
log4j.appender.myLog.Threshold = DEBUG
#'.'yyyy-MM-dd: 每天產生一個新的檔案
log4j.appender.myLog.DatePattern = '.'yyyy-MM-dd
log4j.appender.myLog.layout = org.apache.log4j.PatternLayout
log4j.appender.myLog.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%t:%r] - [%p] [%c{1}:%L] [%M] %m%n
log4j.additivity.myLog = false
測驗代碼還是之前的,運行結果如下:

自定義文本方式
每天記錄一個日志檔案,這個日志檔案把今天比較重要的日志記錄下來,

每個日志檔案記錄的形式(時間+組裝好的內容),如下 :

是不是有個疑問,如果有多個服務器,日志是記錄到代碼執行的這個服務器上了,外面訪問進來肯定會訪問到不同的服務器上了,日志檔案也肯定存在多個咯,查問題的時候不就得一個個服務器的日志都翻一遍,煩人嗎不是,這個時候你請搞工程的兄弟吃個夜宵他就會告訴你,其實服務器是可以搞成共享一個目錄的,多個服務器訪問同一個日志檔案也是可以的(具體我就不講了),但說實話這種方式我們現在也只是偶爾用一下,

示意代碼
package com.log;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileLog {
public static void writeLog(String file, String conent) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(file, true)));
out.write(conent);
out.newLine();//換行
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat dfTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
//當前時間 方便日志查看
String curTime = dfTime.format(date);
//yyyy-MM-dd格式的,為了每日更換日志檔案
String curDay = df.format(date);
//組裝日志內容
String text="日志內容"+org.apache.commons.lang.RandomStringUtils.randomNumeric(4);
String logStr="["+curTime+"]"+text;
//指定日志檔案路徑
String fileName="E:/testlog/"+curDay+".txt";
System.out.println("start");
//列印日志
writeLog(fileName, logStr);
System.out.println("end");
}
}
記錄到資料庫
我們用的最多的場景是介面,把收發報文記錄下來,如果介面發生錯誤的話,將錯誤的資訊記錄成一條資料,
一旦發生介面呼叫爭議的實話,這個就派上用場了,場景:
對端是個大廠很大的那種(甲方都不吊的那種),你送了資料過去,然后對端說沒收到或者說收到的有問題,但人家又不說具體什么問題,也不給報文,就做甩手掌柜,介面人只好找你了(你懂的,柿子都找軟的捏),你如果沒有呼叫報文和回傳報文的記錄的話,你就等著哭吧,挨罵你只能忍著,就算你確定你的程式沒問題也沒有用,你得有證據,你就得想方設法的找報文,但如果要從日志找的話不是那么好找,甚至有時候找不到,

記錄到庫就很好找,根據工單號、主鍵或者發生時間等等,可以很容易發現問題、定位問題,然后迅速把發送的報文、回傳的報文發給介面人,手一甩就剩下你心情愉悅的摸魚了,

我一般會記錄這些資訊
| 來源系統 | 對端系統/自己的系統代號 |
| 業務 | 不同的模塊寫不同的編碼,方便區分 |
| 工單號 | 唯一標示即可,看自己系統的需求 |
| 方法名 | 呼叫的方法 |
| 型別 | 接識訓者發送 |
| 狀態 | 成功或者失敗 |
| 報文 | 具體的報文資訊 |
| 操作時間 | 創建時間 |
當然有可能會涉及到比較長的報文,所以我們設計的是有好幾個欄位來存,不夠的就往后一個欄位放,比如:
String xmlInfo = vo.getXmlInfo();
int xmlLength = xmlInfo.length();
int count = xmlLength / 1000;
if (count * 1000 < xmlLength)
count++;
String xmlArr[] = new String[count];
for (int i = 0; i < count; i++)
{
int endLength = (i + 1) * 1000;
if (endLength > xmlLength)
endLength = xmlLength;
xmlArr[i] = xmlInfo.substring(i * 1000, endLength);
if (i == 0)
vo.setXmlInfo1(xmlArr[i]);
else if (i == 1)
vo.setXmlInfo2(xmlArr[i]);
else if (i == 2)
vo.setXmlInfo3(xmlArr[i]);
else if (i == 3)
vo.setXmlInfo4(xmlArr[i]);
else if (i == 4)
vo.setXmlInfo5(xmlArr[i]);
else if (i == 5)
vo.setXmlInfo6(xmlArr[i]);
else if (i == 6)
vo.setXmlInfo7(xmlArr[i]);
else if (i == 7)
vo.setXmlInfo8(xmlArr[i]);
}
最后
通常情況下在程式日志里記錄一些比較有意義的資料:程式啟動、登錄、退出、重要變數的狀態變化、重要資料的執行記錄、介面呼叫報文的記錄、定時執行相關任務的狀況 等等,
關注下方公眾號,有更多資料、實體代碼、面試技巧奉上!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/279244.html
標籤:java
下一篇:2021-04-22
