成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

log4j MDC實(shí)現(xiàn)日志追蹤

aristark / 3162人閱讀

摘要:介紹中包含的可以被同一線程中執(zhí)行的代碼所訪問內(nèi)容。當(dāng)前線程的子線程會(huì)繼承其父線程中的的內(nèi)容。記錄日志時(shí),只需要從中獲取所需的信息即可。作用使用來記錄日志,可以規(guī)范多開發(fā)下日志格式。

介紹:
MDC 中包含的可以被同一線程中執(zhí)行的代碼所訪問內(nèi)容。當(dāng)前線程的子線程會(huì)繼承其父線程中的 MDC 的內(nèi)容。記錄日志時(shí),只需要從 MDC 中獲取所需的信息即可。
作用:
使用MDC來記錄日志,可以規(guī)范多開發(fā)下日志格式。

一:新建線程處理類 ThreadContext

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * 線程上下文
 *
 * @date 2017年3月1日
 * @since 1.0.0
 */
public class ThreadContext {
    /**
     * 線程上下文變量的持有者
     */
    private final static ThreadLocal> CTX_HOLDER = new ThreadLocal>();

    static {
        CTX_HOLDER.set(new HashMap());
    }

 
    /**
     * traceID
     */
    private final static String TRACE_ID_KEY = "traceId";

    /**
     * 會(huì)話ID
     */
    private final static String SESSION_KEY = "token";

    /**
     * 操作用戶ID
     */
    private final static String VISITOR_ID_KEY = "userId";
    /**
     * 操作用戶名
     */
    private final static String VISITOR_NAME_KEY = "userName";

    /**
     * 客戶端IP
     */
    private static final String CLIENT_IP_KEY = "clientIp";

    /**
     * 添加內(nèi)容到線程上下文中
     *
     * @param key
     * @param value
     */
    public final static void putContext(String key, Object value) {
        Map ctx = CTX_HOLDER.get();
        if (ctx == null) {
            return;
        }
        ctx.put(key, value);
    }

    /**
     * 從線程上下文中獲取內(nèi)容
     *
     * @param key
     */
    @SuppressWarnings("unchecked")
    public final static  T getContext(String key) {
        Map ctx = CTX_HOLDER.get();
        if (ctx == null) {
            return null;
        }
        return (T) ctx.get(key);
    }

    /**
     * 獲取線程上下文
     */
    public final static Map getContext() {
        Map ctx = CTX_HOLDER.get();
        if (ctx == null) {
            return null;
        }
        return ctx;
    }

    /**
     * 刪除上下文中的key
     *
     * @param key
     */
    public final static void remove(String key) {
        Map ctx = CTX_HOLDER.get();
        if (ctx != null) {
            ctx.remove(key);
        }
    }

    /**
     * 上下文中是否包含此key
     *
     * @param key
     * @return
     */
    public final static boolean contains(String key) {
        Map ctx = CTX_HOLDER.get();
        if (ctx != null) {
            return ctx.containsKey(key);
        }
        return false;
    }

    /**
     * 清空線程上下文
     */
    public final static void clean() {
        CTX_HOLDER.remove();
    }

    /**
     * 初始化線程上下文
     */
    public final static void init() {
        CTX_HOLDER.set(new HashMap());
    }


    /**
     * 設(shè)置traceID數(shù)據(jù)
     */
    public final static void putTraceId(String traceId) {
        putContext(TRACE_ID_KEY, traceId);
    }

    /**
     * 獲取traceID數(shù)據(jù)
     */
    public final static String getTraceId() {
        return getContext(TRACE_ID_KEY);
    }

    /**
     * 設(shè)置會(huì)話的用戶ID
     */
    public final static void putUserId(Integer userId) {
        putContext(VISITOR_ID_KEY, userId);
    }

    /**
     * 設(shè)置會(huì)話的用戶ID
     */
    public final static int getUserId() {
        Integer val = getContext(VISITOR_ID_KEY);
        return val == null ? 0 : val;
    }

    /**
     * 設(shè)置會(huì)話的用戶名
     */
    public final static void putUserName(String userName) {
        putContext(VISITOR_NAME_KEY, userName);
    }

    /**
     * 獲取會(huì)話的用戶名稱
     */
    public final static String getUserName() {
        return Optional.ofNullable(getContext(VISITOR_NAME_KEY))
                .map(name -> String.valueOf(name))
                .orElse("");
    }

    /**
     * 取出IP
     *
     * @return
     */
    public static final String getClientIp() {
        return getContext(CLIENT_IP_KEY);
    }

    /**
     * 設(shè)置IP
     *
     * @param ip
     */
    public static final void putClientIp(String ip) {
        putContext(CLIENT_IP_KEY, ip);
    }

    /**
     * 設(shè)置會(huì)話ID
     *
     * @param token
     */
    public static void putSessionId(String token) {
        putContext(SESSION_KEY, token);
    }

    /**
     * 獲取會(huì)話ID
     *
     * @param token
     */
    public static String getSessionId(String token) {
        return getContext(SESSION_KEY);
    }

    /**
     * 清空會(huì)話數(shù)據(jù)
     */
    public final static void removeSessionId() {
        remove(SESSION_KEY);
    }
}

二:添加工具類TraceUtil

import java.util.UUID;
import org.slf4j.MDC;
import ThreadContext;

/**
 * trace工具
 *
 * @date 2017年3月10日
 * @since 1.0.0
 */
public class TraceUtil {

    public static void traceStart() {
        ThreadContext.init();
        String traceId = generateTraceId();
        MDC.put("traceId", traceId);
        ThreadContext.putTraceId(traceId);
    }

    public static void traceEnd() {
        MDC.clear();
        ThreadContext.clean();
    }

    /**
     * 生成跟蹤ID
     *
     * @return
     */
    private static String generateTraceId() {
        return UUID.randomUUID().toString();
    }
}

三:添加ContextFilter,對(duì)于每個(gè)請(qǐng)求隨機(jī)生成RequestID并放入MDC

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.filter.OncePerRequestFilter;

import com.pingan.manpan.common.util.TraceUtil;
import com.pingan.manpan.user.dto.ThreadContext;
import com.pingan.manpan.web.common.surpport.IpUtils;

/**
 * 上下文Filter
 *
 * @date 2017/3/10
 * @since 1.0.0
 */
//@Order 標(biāo)記組件的加載順序
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ContextFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        try {
            ThreadContext.putClientIp(IpUtils.getClientIp(request));
            TraceUtil.traceStart();

            filterChain.doFilter(request, response);
        } finally {
            TraceUtil.traceEnd();
        }
    }
}

四:在webConfiguriation注冊(cè)filter

    /**
     * 請(qǐng)求上下文,應(yīng)該在最外層
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean requestContextRepositoryFilterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new ContextFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }

五:修改log4j日志配置文件,設(shè)置日志traceId





    

    
    
    

    
    

    
        
            ${FILE_LOG_PATTERN}
        
        ${LOG_FILE}${LOG_FILE_SUFFIX}
        
            ${LOG_FILE}.%d{yyyy-MM-dd}${LOG_FILE_SUFFIX}
        
    

    
        127.0.0.1
        local6
        514
        ${FILE_LOG_PATTERN}
    
    
    

    
        
        
        
    


文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/68984.html

相關(guān)文章

  • 日志排查問題困難?分布式日志鏈路跟蹤來幫你

    摘要:當(dāng)前線程的子線程會(huì)繼承其父線程中的的內(nèi)容。若希望在線程池與主線程間傳遞,需配合和使用。 一、背景 開發(fā)排查系統(tǒng)問題用得最多的手段就是查看系統(tǒng)日志,在分布式環(huán)境中一般使用ELK來統(tǒng)一收集日志,但是在并發(fā)大時(shí)使用日志定位問題還是比較麻煩,由于大量的其他用戶/其他線程的日志也一起輸出穿行其中導(dǎo)致很難篩選出指定請(qǐng)求的全部相關(guān)日志,以及下游線程/服務(wù)對(duì)應(yīng)的日志。 ? 二、解決思路 每個(gè)請(qǐng)求都使...

    EasonTyler 評(píng)論0 收藏0
  • 分布式調(diào)用跟蹤實(shí)戰(zhàn)

    摘要:為了追蹤一個(gè)請(qǐng)求完整的流轉(zhuǎn)過程,我可以給請(qǐng)求分配一個(gè)唯一的,當(dāng)請(qǐng)求調(diào)用其他服務(wù)時(shí),我們傳遞這個(gè)。這是一個(gè)簡(jiǎn)單的實(shí)現(xiàn)分布式調(diào)用追蹤的實(shí)踐,以上。 背景 分布式環(huán)境下,跨服務(wù)之間的調(diào)用錯(cuò)綜復(fù)雜,如果突然爆出一個(gè)錯(cuò)誤,雖然有日志記錄,但到底是哪個(gè)服務(wù)出了問題呢?是移動(dòng)端傳的參數(shù)有錯(cuò)誤,還是系統(tǒng)X或者系統(tǒng)Y提供的接口導(dǎo)致?在這種情況下,錯(cuò)誤排查起來就非常費(fèi)勁。 為了追蹤一個(gè)請(qǐng)求完整的流轉(zhuǎn)過程,...

    jlanglang 評(píng)論0 收藏0
  • Spring Boot 參考指南(日志記錄)

    摘要:默認(rèn)情況下,如果使用,則使用進(jìn)行日志記錄,還包括適當(dāng)?shù)穆酚?,以確保使用或的依賴庫都能正確工作。分隔符,用于區(qū)分實(shí)際日志消息的開始。 26. 日志記錄 Spring Boot為所有內(nèi)部日志記錄使用Commons Logging,但開放底層日志實(shí)現(xiàn),提供了Java Util Logging、Log4J2和Logback的默認(rèn)配置,在每種情況下,日志記錄器都被預(yù)先配置為使用控制臺(tái)輸出,可選的...

    mengera88 評(píng)論0 收藏0
  • Spring Cloud 參考文檔(Spring Cloud Sleuth特性)

    摘要:介紹從版本開始,使用作為追蹤庫,為方便起見,在此處嵌入了的部分文檔。具有一個(gè)上下文,其中包含標(biāo)識(shí)符,該標(biāo)識(shí)符將放置在表示分布式操作的樹中的正確位置。追蹤通常由攔截器自動(dòng)完成,在幕后,他們添加與他們?cè)诓僮髦械慕巧嚓P(guān)的標(biāo)簽和事件。 Spring Cloud Sleuth特性 將trace和span ID添加到Slf4J MDC,因此你可以在日志聚合器中從給定的trace或span提取...

    chinafgj 評(píng)論0 收藏0
  • 【Java筆記】ThreadLocal的學(xué)習(xí)和理解

    摘要:底層是一個(gè)的散列表可擴(kuò)容的數(shù)組,并采用開放地址法來解決沖突。稍后討論方法每個(gè)對(duì)象都有一個(gè)值,每初始化一個(gè)對(duì)象,值就增加一個(gè)固定的大小。因此在使用的時(shí)候要手動(dòng)調(diào)用方法,防止內(nèi)存泄漏。 ThreadLocal定義 先看JDK關(guān)于ThreadLocal的類注釋: This class provides thread-local variables. These variables diffe...

    red_bricks 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<