業(yè)務(wù)代碼異常,日志卻不見了?高效排查指南
開發(fā)過程中,業(yè)務(wù)代碼拋出異常,但日志系統(tǒng)卻“沉默”的情況時有發(fā)生。本文將結(jié)合實(shí)例,分析可能原因并提供高效的排查策略。
案例代碼:
try { List<Plan> plans = planService.lambdaQuery() .eq(Plan::getYn, YnEnum.YES.getLabel()) .eq(Plan::getStatus, Plan.Status.DONE.getCode()) .isNotNull(Plan::getPId) .list(); List<List<Plan>> partition = Lists.partition(plans, 5); partition.forEach(planList -> { try { // 業(yè)務(wù)代碼1 (潛在異常點(diǎn)) } catch (Exception exception) { log.Error("報錯信息1:", exception); // 內(nèi)層異常捕獲 } }); } catch (Exception exception) { log.error("報錯信息2:", exception); // 外層異常捕獲 } finally { log.info("釋放requestId[{}]的鎖", requestId); Redis.unlock(Module.REFRESH_PROMOTE, workerLockKey, requestId); }
問題: “業(yè)務(wù)代碼1”可能拋出異常,但“報錯信息1”日志缺失。
分析:
代碼采用雙層try-catch結(jié)構(gòu)。如果“業(yè)務(wù)代碼1”拋出異常,內(nèi)層catch塊捕獲并記錄“報錯信息1”。 如果內(nèi)層catch處理異常后程序繼續(xù)執(zhí)行,外層catch不會執(zhí)行,導(dǎo)致“報錯信息2”也不輸出。因此,日志缺失可能源于日志記錄配置問題。例如:
- 日志級別設(shè)置過高: 日志系統(tǒng)可能只記錄ERROR級別以上日志,而log.error的實(shí)際級別被配置為WARN或INFO。
- 日志輸出目標(biāo)錯誤: 日志文件路徑配置錯誤,或日志系統(tǒng)無法寫入目標(biāo)文件。
- 日志系統(tǒng)故障: 日志系統(tǒng)本身出現(xiàn)問題,導(dǎo)致日志無法記錄。
排查步驟:
-
驗(yàn)證異常是否存在: 首先,務(wù)必確認(rèn)“業(yè)務(wù)代碼1”是否真的拋出異常。通過調(diào)試模式運(yùn)行代碼,觀察異常堆棧信息。如果異常存在,則繼續(xù)下一步。
-
檢查日志配置:
-
檢查日志系統(tǒng): 如果日志配置正確,但日志仍然缺失,則可能存在日志系統(tǒng)本身的問題。檢查日志系統(tǒng)的運(yùn)行狀態(tài),查看是否有錯誤日志,嘗試重啟日志系統(tǒng)。
-
監(jiān)控系統(tǒng): 一些監(jiān)控系統(tǒng)可以捕獲未被日志系統(tǒng)記錄的異常。檢查監(jiān)控系統(tǒng)是否有相關(guān)告警。
-
代碼審查: 仔細(xì)檢查“業(yè)務(wù)代碼1”及周圍代碼,確認(rèn)異常是否被意外吞沒(例如,catch塊中沒有l(wèi)og.error語句,或catch塊中存在return語句)。
-
異常類型: 某些異常類型可能被jvm或應(yīng)用服務(wù)器自動處理,未記錄到日志中。檢查JVM或應(yīng)用服務(wù)器的日志,查看是否有相關(guān)信息。
通過以上步驟,系統(tǒng)地排查日志缺失問題,并找到根本原因。 記住,先驗(yàn)證異常的存在,再檢查日志配置,最后才是日志系統(tǒng)本身。