微服務(wù)基于請(qǐng)求的日志跟蹤2

<<微服務(wù)基于請(qǐng)求的日志跟蹤>>上設(shè)計(jì)了基于請(qǐng)求的微服務(wù)日志處理方法, 但是發(fā)現(xiàn)在log4j處于異步的情況下會(huì)失效, 原因是RequestId無(wú)法從原線程傳輸?shù)酱蛴∪罩镜木€程, 異步情況下(AsyncLoggerConfig), 日志先被enqueue到一個(gè)隊(duì)列,然后若干線程去消費(fèi)這個(gè)隊(duì)列, 因?yàn)榭缌司€程,所以不能通過(guò)線程變量傳遞過(guò)去.
查看了相關(guān)代碼, 發(fā)現(xiàn)log4j首先將message生成了LogEvent, 然后將LogEvent丟入隊(duì)列, 而LogEvent提供了一個(gè)ContenxtData的Map來(lái)攜帶屬性變量, 所以我們可以將RequestId放到這里面?zhèn)鬟f過(guò)去.

具體的代碼是:

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.impl.ContextDataFactory;
import org.apache.logging.log4j.core.impl.MutableLogEvent;
import org.apache.logging.log4j.core.impl.ReusableLogEventFactory;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.util.StringMap;

import java.util.List;
public class RequestIdLogEventFactory extends ReusableLogEventFactory {
    @Override
    public LogEvent createEvent(String loggerName, Marker marker, String fqcn, Level level, Message message, List<Property> properties, Throwable t) {
        LogEvent event = super.createEvent(loggerName, marker, fqcn, level, message, properties, t);
        if (event instanceof MutableLogEvent) {
            StringMap contextData = ContextDataFactory.createContextData();
            contextData.putAll(event.getContextData());
            contextData.putValue("RequestId", LogRequestIdPlugin.getRequestId());
            ((MutableLogEvent) event).setContextData(contextData);
        }
        return event;
    }
    public static String getRequestId(LogEvent event) {
        return event.getContextData().getValue("RequestId");
    }
}

同時(shí)修改LogRequestIdPlugin:

    @Override
    public void format(LogEvent event, StringBuilder toAppendTo) {
       toAppendTo.append(RequestIdLogEventFactory.getRequestId(event));
    }

設(shè)置應(yīng)用的啟動(dòng)參數(shù), 指定logEvent工廠, 增加:

-DLog4jLogEventFactory=your_package.RequestIdLogEventFactory

這樣即使在異步輸出的時(shí)候,也能傳遞RequestId到日志文件了.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容