<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你真的會打印日志?

          共 2321字,需瀏覽 5分鐘

           ·

          2021-10-23 17:08

          ,!


          一看這個標題我想大家一定進來想“懟”我,你這不是小題大作嗎?在java中打印日志不是一件非常簡單的事情嗎?

          在java中常用的日志級別為DEBUG、INFO、WARN、ERROR四個日志級別。通常開發(fā)環(huán)境開啟DEBUG,生產(chǎn)環(huán)境開啟INFO級別,采用主流的日志采集工具包諸如log4j、logback。

          但日志輸出真的有這么簡單嗎?其實里面蘊含著很多的規(guī)范,或者是最佳實踐,并且還有一些非常有用設計技巧方便查詢關聯(lián)日志的技巧,容我慢慢道來。

          輸出日志的終極目標:助力于快速定位問題、解決問題。

          接下來將圍繞該目標,闡述一下日志相關的一些最佳實踐。

          1、日志的基本規(guī)范

          首先,我們還是簡單介紹一下常用的4個日志級別,并說明各個級別在使用時應該注意的問題。

          • DEBUG 輸出程序的調(diào)試信息,優(yōu)雅的DEBUG日志可以讓我們在排查問題的時候,壓根就不需要使用開發(fā)工具的DEBUG斷點調(diào)試功能,而是直接看Debug的輸出日志即可定位問題。

            • 打印請求、響應數(shù)據(jù)包,特別是入口處將所有請求參數(shù)打印
            • 對核心方法,特別核心計算邏輯前后打印當時的輸入與輸出,并日志中顯示包含方法名稱。
            • 對核心流程(循環(huán)、分支)等條件判斷時輸出必要的入?yún)⒂谂c返回結果,清晰的展示程序的運行軌跡。
          • INFO INFO日志我們通常用于記錄系統(tǒng)/組件的基本運行情況和運行狀態(tài),特別適合打印一次性日志,例如核心類的啟動過程、狀態(tài)變更等信息,輸出的內(nèi)容一定要非常詳細,不要擔心影響性能。

            目前的主流日志輸出框架例如logback,其日志的打印基本都是基于異步的,性能已經(jīng)非常高,無需擔心性能損耗。

          • WARN 警告級別,通常用于可預知但又不希望發(fā)生的情況,典型的使用場景是打印業(yè)務類異常日志,例如參數(shù)校驗不通過、權限不足,余額不足等用戶可處理的;再例如中間件開發(fā)時,有一些分支是我們不希望進入的,因為進入就代表性能差等場景,但這類異常不需要相關系統(tǒng)負責人干預就能得到處理的。

          • ERROR 通常用來打印系統(tǒng)級別的日志,需要人為來干預,通常較大業(yè)務規(guī)模的公司都會將系統(tǒng)級別的異常(ERROR)接入監(jiān)控告警中心,一旦持續(xù)發(fā)生多少條,錯誤率占比多少,將會觸發(fā)告警,相關負責人跟進處理。

            既然需要人為來干預,ERROR日志不僅要打印出錯誤堆棧,同時一定要主動打印出上下文環(huán)境,至少可以打印出該異常所在方法的入?yún)?,盡量讓人能夠根據(jù)錯誤日志與上下文,就能快速定位到具體的代碼行。

          2、日志進階

          上述是一些基本的日志使用規(guī)范,分布式已成為企業(yè)架構的標配,一個應用至少會部署2臺機器,當用戶反饋業(yè)務異常時嘗試去跟蹤日志時會面臨一個問題:去哪臺業(yè)務機器上去查詢?nèi)罩?,如果只?臺還好辦,大不了一臺臺去嘗試,但如果有10臺,20臺甚至上百臺,在這樣輪詢幾乎不可能實現(xiàn),那該如何處理呢?

          經(jīng)典的ELK架構如下圖所示:通常,為了避免在每臺業(yè)務機器上部署一個logstash去抽日志,我們通常建議自定義一個log append,直接將日志寫入到kafka中,然后再掛logstash從kafka中抽取日志,寫入到es集群,然后通過kibana對日志進行可視化搜索。

          然后我們查詢?nèi)罩揪妥兊妙愃七@樣了:本文并沒有打算探討ELK架構,這個后續(xù)應該會單獨展開詳細介紹,而是就算我們接入了ELK,從ELK可以統(tǒng)一查看根據(jù)關鍵字查詢?nèi)罩玖?,該日志會包含所有服務器上的日志,比單獨一臺一臺去找依然方便了很多。

          但這些日志其實是雜亂無章的,查詢出來的日志與日志之間沒有任何關聯(lián)性,而我們在解決特定問題時通常希望日志的**“隔離性”**,希望我們可以根據(jù)一個統(tǒng)一的關鍵字,例如請求號篩選出所有相關的日志,這樣對我們分析排查問題能起到極大的促進作用

          2.1 每條日志包含一個請求序

          那我們?nèi)绾螌ⅰ罢埱筇枴苯y(tǒng)一寫入到日志文件中,肯定不能要求在項目中去修改所有日志輸出到地方,手動去增加請求編號。

          我們可以通過自定義一個append,在append中對用戶的日志統(tǒng)一進行二次加工。

          logback、log4j都可以自定append,接下來以當前使用最廣logback舉例,和大家介紹一下自定義append。

          1、繼承 AppenderBase 并初始化

          首先需要繼承l(wèi)ogback的append的基礎類:AppenderBase,入下圖所示:其中有一個初始化方法start,通常的做法是先調(diào)用super.start()標記append啟動,然后可以在該方法中初始化kafka的消息發(fā)送者對象。

          2、重寫append方法主要是從ILoggingEvent對象中獲取原始日志,然后我們對原始日志加以加工,加工代碼如下圖所示:關鍵是reqeustId的獲取,這個通常會配置一個http filter,進入請求鏈中放入到線程本地變量中(ThreadLocal),然后在日志輸出時從線程上下文環(huán)境中獲取,為了能在線程池等復雜環(huán)境下使用,通??梢允褂茫═ransmittableThreadLocal),關于在線程池中傳遞數(shù)據(jù),需要使用ttl框架,關于這塊的想象介紹可以查看筆者的另一篇博文:全鏈路壓測必備基礎組件之線程上下文管理之“三劍客”


          一鍵三連(關注、點贊、留言)是對我最大的鼓勵。

          ??點擊下方卡片,關注彈出內(nèi)容,回復「PDF」可領取海量學習資料,共同刷題進步,內(nèi)互相監(jiān)督,記錄成長!

          瀏覽 36
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美一交一乱一交一色一色情 | 韩国无码精品久久久 | 欧美日韩免费A片 | 日韩一区二区三区精品 | 中文无码日本高潮喷水 |