當運營向我們上報BUG時,我們第一時間是捕獲相關的介面。從監控系統中,就可以查到使用者使用時介面的請求和響應資料。

  若介面的請求正常,那麼就需要深入到介面程式碼中,檢視相關的日誌,通常會先瀏覽資料庫查詢語句以及內部介面的通訊日誌。

  在本地也可以檢視到上述日誌,但有個問題,有時候開啟某個頁面會報錯,那是因為本地的資料庫沒有與測試或正式環境的同步。

  可能是有些欄位缺失了,也可能是某張表缺失了,情況比較多。所以,最保險的是在測試或正式環境檢視。

  在這兩個環境中,都有日誌管理系統,但日誌量是非常巨大的,若要查詢某一條記錄,就得有非常精確的過濾條件,並且日誌無法連續。

  這條日誌下面的一條,很可能是另外一個介面留下的,因此,需要一個小工具能檢視到指定介面的日誌,解決日常開發的一個痛點。

一、蒐集日誌

1)管理系統

  首先需要將需要的日誌蒐集起來,我使用了一個比較簡單的方法。

  就是在啟動檔案中,新增一個全域性的logMessages變數,宣告為一個空陣列。

global.logMessages = [];

  然後在MongoDB、MySQL、請求內部介面函式中,將他們的查詢語句日誌和通訊日誌塞入logMessages陣列內。

mongoose.set('debug', (...args) => {
logger.debug(...args);
global.logMessages.push(args);
});
new Sequelize(database, username, password, {
...options,
logging: (msg, benchmark) => {
logger.debug(msg, `${benchmark}ms`);
global.logMessages.push(msg);
}
});

  再新增一箇中間件(Server專案基於KOA2),這個中介軟體的作用就是清空logMessages陣列,免得將所有介面的日誌都蒐集起來,因為我只要一個介面的日誌。

export default () => async (ctx, next) => {
//每次請求清空要讀取的日誌陣列
global.logMessages.length = 0;
await next();
};

  這麼設計會有一個問題,伺服器在處理多個請求(高併發)時,互相會影響各自的日誌蒐集,可能會出現這個介面日誌中夾雜著另一個介面的日誌,也可能是蒐集到一半的日誌就被清除了。

  當然,在測試環境,這種情況可以控制住。但是測試環境有時候資料不完整,邏輯可能走不下去,得上生產環境,那生產環境就有概率出現上述問題。

  後面將中介軟體去除,logMessages變數在一個介面中宣告,這個介面就是下面介面中點提交時請求的介面,能解決日誌被無故清除的問題,但還是會出現串線的問題。

  生產環境暫時無解,好在還有一個預發環境,它使用的資料來源和生產是相同的,只要保證程式碼和生產同步,那麼就能得到想要的日誌列表。

2)Web API

  Web API是另一個介面服務,也需要監控其中的日誌,但是它與之前的管理系統不同,它是一個獨立的服務。

  也就是說,我無法直接在管理系統中通過 global.logMessages 讀取日誌。

  一開始是想將日誌寫入快取中,然後在管理系統中讀取快取中的日誌,不過這樣做不僅太繞,平添複雜度,而且日誌寫法也會與之前的不一致。

  於是否決了此方案,改用一箇中間件,日誌的寫入和讀取與之前保持一致。不同點是在一箇中間件中,將日誌作為響應的引數返回。

  在下面的程式碼中,當需要日誌時,我會帶上一個特殊的引數:isLogMessages,只有這個引數存在時,才表示需要返回記錄。

export default () => async (ctx, next) => {
// 只有帶了特殊引數的請求,才會把介面日誌帶上
const isLogMessages = ctx.query.isLogMessages || ctx.request.body.isLogMessages;
if(isLogMessages) {
global.logMessages = [];
}
await next();
if(isLogMessages) {
const { body } = ctx;
if(typeof body === 'string') {
ctx.body = {
data: body
};
}else {
ctx.body = {
...body
}
}
ctx.body.logMessages = global.logMessages;
delete global.logMessages;
}

二、介面

  在完成上述的日誌蒐集之後,就需要有一張操作介面(如圖所示),提升我們組自己的使用者體驗,藉助之前封裝的模板元件,搭建這樣一個頁面幾十分鐘就好了。

  

  介面中包括API路徑、方法、專案和引數,其中引數可動態增加,點選提交就會開始模擬請求介面,得到日誌(如圖所示)和響應。

  

  這樣一套操作之後,就能馬上知道介面內的細節,可幫助我們快速定位問題,也是一種降低時間成本的手段。