欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用MDC快速查詢(xún)應(yīng)用接口全部執(zhí)行日志

 更新時(shí)間:2023年01月08日 17:03:42   作者:程序員拾山  
這篇文章主要為大家介紹了使用MDC快速查詢(xún)應(yīng)用接口全部執(zhí)行日志的方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

對(duì)于每一個(gè)開(kāi)發(fā)者來(lái)說(shuō),查詢(xún)接口的執(zhí)行日志都是一個(gè)高頻率的操作,每當(dāng)測(cè)試說(shuō)接口有問(wèn)題時(shí),我們都需要去服務(wù)器或者日志系統(tǒng)上查報(bào)錯(cuò)的原因。

一般情況下,我們會(huì)通過(guò)對(duì)應(yīng)的關(guān)鍵字或者接口地址去查詢(xún)這個(gè)接口到底報(bào)了什么錯(cuò),但是這帶來(lái)一個(gè)問(wèn)題,就是我們可能少打日志或者忘打某些關(guān)鍵字的日志,導(dǎo)致查詢(xún)記錄比較麻煩。

那么有沒(méi)有一種簡(jiǎn)單高效的方法,即使我們?cè)谌罩局胁淮蛴∪魏侮P(guān)鍵字,系統(tǒng)會(huì)自動(dòng)生成一個(gè)關(guān)鍵字,讓我們一次性查詢(xún)出這個(gè)接口的所有l(wèi)og記錄呢?

MDC

MDC是日志門(mén)面框架SLF4J提供的一個(gè)類(lèi),可以提供在多線(xiàn)程情況下記錄日志的功能,log4j、logback、log4j2都有對(duì)這個(gè)類(lèi)的實(shí)現(xiàn)。

從本質(zhì)上來(lái)說(shuō),MDC可以看做一個(gè)ThreadLocal,由于其線(xiàn)程安全的特性,可以讓我們輕松安全的保存數(shù)據(jù)。

MDC主要的API有clear()、get()、put()、remove()方法等,簡(jiǎn)潔的api讓我們使用上手基本沒(méi)有難度。

如何使用

1,修改日志打印格式

以日志框架logback為例,在logback.xml中,找到日志打印規(guī)則的配置,添加**-%X{reqId}** 屬性,其中reqId可以任意指定,你寫(xiě)其他的屬性也可以,博主這里演示指定為reqId。

<encoder>
  <pattern>-%X{reqId} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %file:%line %msg%n</pattern>
  <charset>UTF-8</charset>
</encoder>

2,添加過(guò)濾器MDCFilter

ps.使用攔截器也可以,效果是一樣的。對(duì)每個(gè)接口 做攔截。

@Component
@AllArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE)
@Slf4j
public class MDCFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        try {
            //給每個(gè)請(qǐng)求接口生成一個(gè)requestId
            String requestId = RandomUtil.randomNumbers(10);
            //這里的reqId就是上面配置的,要保持一致
            MDC.put("reqId", "reqId:" + requestId);
            chain.doFilter(request, response);
        } finally {
            MDC.clear();
        }
    }
    @Override
    public void destroy() {
    }
}

經(jīng)過(guò)簡(jiǎn)單的兩步就配置好了,下面我們看一下效果。

@PostMapping(value = "/mdcTest")
public ResponseEntity&lt;Object&gt; mdcTest(String id, String name) {
    log.info("測(cè)試日志打印,id={},name={}", id, name);
    log.info("測(cè)試日志打印1");
    log.info("測(cè)試日志打印2");
    log.info("測(cè)試日志打印3");
    log.info("測(cè)試日志打印4");
    return ResponseEntity.ok().build();
}

每一行日志都有一個(gè)關(guān)鍵字reqId:9723829830,這樣我們查詢(xún)?nèi)罩緯r(shí)只需要查詢(xún)關(guān)鍵字9723829830就可以直接查出來(lái)這個(gè)接口所有的執(zhí)行記錄了。

如果想更方便的話(huà),也可以把這個(gè)關(guān)鍵字直接輸出到每一個(gè)接口的響應(yīng)頭或者響應(yīng)體中。

進(jìn)階使用

對(duì)于普通的web應(yīng)用我們可以直接攔截每個(gè)接口,自動(dòng)生成一個(gè)請(qǐng)求id,那么對(duì)于微服務(wù)項(xiàng)目,一個(gè)接口可能會(huì)產(chǎn)生很多服務(wù)的調(diào)用,那如何一次性查出來(lái)所有系統(tǒng)內(nèi)的日志呢?

對(duì)于日志的搜集本文暫不考慮,咱們先說(shuō)如何做請(qǐng)求id的傳遞。

其實(shí)也很簡(jiǎn)單,當(dāng)我們有多個(gè)系統(tǒng)間的調(diào)用時(shí),把reqId放到request的header中進(jìn)行傳遞,然后下游系統(tǒng)獲取這個(gè)id就可以了。

比如下方的攔截器:

public class LogInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //如果有上層調(diào)用就從header中取出上層的ID
        String traceId = request.getHeader("reqId");
        if (traceId == null) {
            //如果沒(méi)有,就生成一個(gè)默認(rèn)的
            traceId = RandomUtil.randomNumbers(10);
        }
        MDC.put("reqId", traceId);
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        //調(diào)用結(jié)束后刪除
        MDC.remove("reqId");
    }
}

MDC存在的一些問(wèn)題

我們?cè)谏衔恼f(shuō)過(guò),MDC的本質(zhì)是ThreadLocal,它會(huì)把數(shù)據(jù)都綁定到當(dāng)前線(xiàn)程上。但是當(dāng)我們使用多線(xiàn)程的時(shí)候,就會(huì)帶來(lái)一個(gè)數(shù)據(jù)丟失的問(wèn)題。

所以,我們需要進(jìn)行線(xiàn)程間的數(shù)據(jù)傳遞,保證MDC數(shù)據(jù)不丟失。

以線(xiàn)程池傳遞數(shù)據(jù)為例,ThreadPoolTaskExecutor提供了一個(gè)taskDecorator裝飾器,通過(guò)這個(gè)屬性,我們就可以實(shí)現(xiàn)屬性的傳遞。

首先,定義一個(gè)MDCContextDecorator,

public class MDCContextDecorator implements TaskDecorator {
    @Override
    public Runnable decorate(Runnable runnable) {
        Map&lt;String,String&gt; previous = MDC.getCopyOfContextMap();
        return () -&gt; {
            try {
                if (previous != null) {
                    MDC.setContextMap(previous);
                }
                runnable.run();
            } finally {
                MDC.clear();
            }
        };
    }
}

然后設(shè)置線(xiàn)程池的taskDecorator屬性,

public ThreadPoolTaskExecutor executor() {
  ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  executor.setCorePoolSize(5);
  executor.setMaxPoolSize(20);
  //...其他屬性
  //設(shè)置線(xiàn)程屬性的自動(dòng)傳遞
  executor.setTaskDecorator(new MDCContextDecorator());
  return executor;
}

最后

MDC的使用其實(shí)很簡(jiǎn)單,對(duì)于我們查詢(xún)?nèi)罩疽埠苡袔椭?,?yīng)用也算是非常廣泛了。有興趣的同學(xué)也可以去看一下它的內(nèi)部實(shí)現(xiàn),代碼也并不復(fù)雜。

以上就是使用MDC快速查詢(xún)應(yīng)用接口全部執(zhí)行日志的詳細(xì)內(nèi)容,更多關(guān)于MDC查詢(xún)接口執(zhí)行日志的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java中邏輯控制舉例具體講解

    java中邏輯控制舉例具體講解

    Java程序邏輯控制通俗說(shuō)就是對(duì)代碼執(zhí)行順序的控制,這篇文章主要給大家介紹了關(guān)于java中邏輯控制的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • 初識(shí)Spark入門(mén)

    初識(shí)Spark入門(mén)

    這篇文章主要介紹了初識(shí)Spark入門(mén),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • Maven項(xiàng)目更換本地倉(cāng)庫(kù)過(guò)程圖解

    Maven項(xiàng)目更換本地倉(cāng)庫(kù)過(guò)程圖解

    這篇文章主要介紹了Maven項(xiàng)目更換本地倉(cāng)庫(kù)過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • java對(duì)象數(shù)組實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)

    java對(duì)象數(shù)組實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java對(duì)象數(shù)組實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Mybatis plus中的like查詢(xún)問(wèn)題

    Mybatis plus中的like查詢(xún)問(wèn)題

    這篇文章主要介紹了Mybatis plus中的like查詢(xún)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • http協(xié)議進(jìn)階之Transfer-Encoding和HttpCore實(shí)現(xiàn)詳解

    http協(xié)議進(jìn)階之Transfer-Encoding和HttpCore實(shí)現(xiàn)詳解

    這篇文章主要給大家介紹了http協(xié)議之Transfer-Encoding和HttpCore實(shí)現(xiàn)的相關(guān)資料,文中介紹的非常詳細(xì),相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-04-04
  • 解決打開(kāi)的idea項(xiàng)目maven不生效問(wèn)題

    解決打開(kāi)的idea項(xiàng)目maven不生效問(wèn)題

    這篇文章主要給大家介紹了關(guān)于如何解決打開(kāi)的idea項(xiàng)目maven不生效問(wèn)題,最近在配置maven時(shí),發(fā)現(xiàn)無(wú)論配置幾遍,IDEA中的maven配置總會(huì)還原成默認(rèn)的,所以這里給大家分享下解決辦法,需要的朋友可以參考下
    2023-07-07
  • spring自定義注解及使用方法詳細(xì)例子

    spring自定義注解及使用方法詳細(xì)例子

    這篇文章主要給大家介紹了關(guān)于spring自定義注解及使用方法的相關(guān)資料,Spring 是一個(gè)非常強(qiáng)大的框架,可以使用自定義注解來(lái)完成許多任務(wù),文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • SpringBoot詳解shiro過(guò)濾器與權(quán)限控制

    SpringBoot詳解shiro過(guò)濾器與權(quán)限控制

    當(dāng)shiro被運(yùn)用到web項(xiàng)目時(shí),shiro會(huì)自動(dòng)創(chuàng)建一些默認(rèn)的過(guò)濾器對(duì)客戶(hù)端請(qǐng)求進(jìn)行過(guò)濾。比如身份驗(yàn)證、授權(quán)的相關(guān)的,這篇文章主要介紹了shiro過(guò)濾器與權(quán)限控制
    2022-07-07
  • Java使用分治算法實(shí)現(xiàn)排序數(shù)索引功能示例【二分搜索】

    Java使用分治算法實(shí)現(xiàn)排序數(shù)索引功能示例【二分搜索】

    這篇文章主要介紹了Java使用分治算法實(shí)現(xiàn)排序數(shù)索引功能,結(jié)合具體實(shí)例形式分析了java分治算法進(jìn)行排序索引的相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09

最新評(píng)論