1. 程式人生 > >基於Log4j NDC 多執行緒條件下記錄日誌,排查生產問題

基於Log4j NDC 多執行緒條件下記錄日誌,排查生產問題

在大吞吐,高併發的場景, 一個請求到達後端,通常是轉換成多執行緒並行處理請求, 如何通過一個標誌找到這個請求對應的多個執行緒,瞭解這個請求的完整的處理情況,從而幫助我們定位這次呼叫到底哪一步出現了問題,對我們快速定位排查生產問題是非常有用的。我們在每個子任務程式碼開始處(每個子任務都會啟動一個新的執行緒)將當前執行緒的執行緒號設定為父執行緒的執行緒號,在日誌中通過這個執行緒號將整個處理過程關聯起來了, 下面程式碼是一個子任務, MiscUtil.setNDC(param) 方法在子執行緒開始時設定了ndc 和父執行緒相同,原始碼如下:

    @Override
    public OnwayAndArrived call() throws Exception {
        MiscUtils.setNDC(param);
        Transaction tx = Cat.newTransaction("Callable", "FundOnwayAndArrivedCallable.call");
        try {
            String clientNo = param.getBecifNo();
            String bankAcc = param.getAccountList();
            String businCode = param.getExtensionMap().get("businCode");
            String startDate = param.getStartDate();
            String endDate = param.getEndDate();
            OnwayAndArrived on = OnwayAndArrivedService.this.queryFundOnWayAndArrived(clientNo, bankAcc, businCode, null, startDate, endDate);
            tx.setSuccessStatus();
            return on;
        }catch (Exception e) {
            LOGGER.error(e.getMessage());
            tx.setStatus(e);
            return null;
        }finally {
            tx.complete();
        }
    }



public static void setNDC(AbstractBaseParam baseParamParam) {
    Map<String, String> extensionMap = baseParamParam.getExtensionMap();
    if (null != extensionMap && extensionMap.containsKey(Constant.LOG_NDC)) {
        NDC.clear();
        NDC.push(extensionMap.get(Constant.LOG_NDC));
    }
}