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

SpringCloudGateway使用Skywalking時日志打印traceId解析

 更新時間:2023年06月14日 14:42:20   作者:SparkOnly  
這篇文章主要為大家介紹了SpringCloudGateway使用Skywalking時日志打印traceId解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

環(huán)境信息

  • SpringCloudGateway 3.1.3
  • Skywalking Agent 8.10.0

環(huán)境配置

Agent

由于SpringCloudGateway是基于WebFlux來實現(xiàn)的,需要進到skywalking的agent目錄,將optional-plugins目錄底下的以下兩個jar包復制到plugins目錄

  • apm-spring-webflux-5.x-plugin-8.10.0.jar
  • apm-spring-cloud-gateway-3.x-plugin-8.10.0.jar

Maven依賴配置

<dependency>
  <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-log4j-2.x</artifactId>
    <version>${skywalking.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-trace</artifactId>
    <version>${skywalking.version}</version>
</dependency>

日志pattern配置

[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%traceId] [%logger{36}] [%thread] [%-5level] %msg%n

啟動參數

新增啟動參數

-javaagent:D:\work\skywalking-agent\skywalking-agent.jar=agent.service_name=xxx
-Dskywalking.collector.backend_service=xxx:11800

啟動程序后,嘗試通過網關進行接口調用,可以在Skywalking-ui上看到鏈路已經串起來了

調用鏈路

但是有個問題,日志里記錄的日志始終不顯示正確的TID

[2022-06-15 14:53:19.958] [TID: N/A]

問題處理過程

查看agent是怎么串聯(lián)鏈路的

查看Skywalking-agent的源碼,可以看到,在apm-spring-webflux-5.x-plugin-8.10.0.jar插件里,攔截了org.springframework.web.reactive.DispatcherHandlerhandle方法
攔截器里往reactor的調用鏈路里,放入 < SKYWALKING_CONTEXT_SNAPSHOT - ContextSnapshot >

image.png

所以traceId可以從reactor的context里獲取到

怎么讓日志獲取到traceId

網上找了下資料,在這里[https://github.com/reactor/reactor-core/blob/main/docs/asciidoc/faq.adoc#context.api]發(fā)現(xiàn)了相關信息

public static <T> Consumer<Signal<T>> logOnNext(Consumer<T> logStatement) {
    return signal -> {
        if (!signal.isOnNext()) return; (1)
        Optional<String> toPutInMdc = signal.getContext().getOrEmpty("CONTEXT_KEY"); (2)
        toPutInMdc.ifPresentOrElse(tpim -> {
            try (MDC.MDCCloseable cMdc = MDC.putCloseable("MDC_KEY", tpim)) { (3)
                logStatement.accept(signal.get()); (4)
            }
        },
        () -> logStatement.accept(signal.get())); (5)
    };
}
@GetMapping("/byPrice")
public Flux<Restaurant> byPrice(@RequestParam Double maxPrice, @RequestHeader(required = false, name = "X-UserId") String userId) {
    String apiId = userId == null ? "" : userId; (1)
    return restaurantService.byPrice(maxPrice))
               .doOnEach(logOnNext(r -> LOG.debug("found restaurant {} for ${}", (2)
                    r.getName(), r.getPricePerPerson())))
               .contextWrite(Context.of("CONTEXT_KEY", apiId)); (3)
}

獲取不到traceId的時候,怎么顯示默認值

https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout

equals{pattern}{test}{substitution}
equalsIgnoreCase{pattern}{test}{substitution}

完整例子

  • pattern改為 [%d{yyyy-MM-dd HH:mm:ss.SSS}] [TID: %equals{%X{traceId}}{}{N/A}] [%logger{36}] [%thread] [%-5level] %msg%n
  • 注冊onEachOperator的Hooks
@Component
public class LogHooks {
    private static final String KEY = "logMdc";
    @PostConstruct
    @SuppressWarnings("unchecked")
    public void setHook() {
        reactor.core.publisher.Hooks.onEachOperator(KEY,
                Operators.lift((scannable, coreSubscriber) -> new MdcSubscriber(coreSubscriber)));
    }
    @PreDestroy
    public void resetHook() {
        reactor.core.publisher.Hooks.resetOnEachOperator(KEY);
    }
}
public class MdcSubscriber implements CoreSubscriber {
    private static final String TRACE_ID = "traceId";
    private static final String SKYWALKING_CTX_SNAPSHOT = "SKYWALKING_CONTEXT_SNAPSHOT";
    private final CoreSubscriber<Object> actual;
    public MdcSubscriber(CoreSubscriber<Object> actual) {
        this.actual = actual;
    }
    @Override
    public void onSubscribe(Subscription s) {
        actual.onSubscribe(s);
    }
    @Override
    public void onNext(Object o) {
        Context c = actual.currentContext();
        Optional<String> traceIdOptional = Optional.empty();
        if (!c.isEmpty() && c.hasKey(SKYWALKING_CTX_SNAPSHOT)) {
            traceIdOptional = Optional.of(c.get(SKYWALKING_CTX_SNAPSHOT)).map(BeanUtil::beanToMap)
                    .map(t -> t.get(TRACE_ID)).map(BeanUtil::beanToMap).map(t -> t.get("id")).map(Object::toString);
        }
        try (MDC.MDCCloseable cMdc = MDC.putCloseable(TRACE_ID, traceIdOptional.orElse("N/A"))) {
            actual.onNext(o);
        }
    }
    @Override
    public void onError(Throwable throwable) {
        actual.onError(throwable);
    }
    @Override
    public void onComplete() {
        actual.onComplete();
    }
    @Override
    public Context currentContext() {
        return actual.currentContext();
    }
}

以上就是SpringCloudGateway使用Skywalking時日志打印traceId解析的詳細內容,更多關于SpringCloudGateway Skywalking的資料請關注腳本之家其它相關文章!

相關文章

  • Java maven三種倉庫,本地倉庫,私服,中央倉庫的配置

    Java maven三種倉庫,本地倉庫,私服,中央倉庫的配置

    今天給大家簡單介紹Maven三種倉庫的配置,文中有非常詳細的解釋,對Java初學者很有幫助喲,需要的朋友可以參考下,希望能夠給你帶來幫助
    2021-09-09
  • springboot整合security和vue的實踐

    springboot整合security和vue的實踐

    本文主要介紹了springboot整合security和vue的實踐,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Java中和隊列相關的基本操作

    Java中和隊列相關的基本操作

    在Java中,隊列是一種常用的數據結構,用于存儲和管理元素。Java提供了Queue接口和其實現(xiàn)類,包括LinkedList和ArrayDeque等。隊列的基本操作包括入隊(enqueue)、出隊(dequeue)、獲取隊首元素(peek)和判斷隊列是否為空(isEmpty)。
    2023-09-09
  • 解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測

    解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測

    這篇文章主要為大家介紹了httpclient的validateAfterInactivity連接池狀態(tài)檢測解讀*,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • SpringBoot中使用Servlet三大組件的方法(Servlet、Filter、Listener)

    SpringBoot中使用Servlet三大組件的方法(Servlet、Filter、Listener)

    這篇文章主要介紹了SpringBoot中使用Servlet三大組件的方法(Servlet、Filter、Listener),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • 使用springboot打包后的文件讀取方式

    使用springboot打包后的文件讀取方式

    這篇文章主要介紹了使用springboot打包后的文件讀取方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java DataInputStream和DataOutputStream詳解及實例代碼

    java DataInputStream和DataOutputStream詳解及實例代碼

    這篇文章主要介紹了java DataInputStream和DataOutputStream詳解及實例代碼的相關資料,需要的朋友可以參考下
    2017-01-01
  • Java中String類的常見方法超詳細講解

    Java中String類的常見方法超詳細講解

    這篇文章主要介紹了Java中String類常見方法的相關資料,String類是不可變的,字符串常量池用于存儲字符串字面量,常用方法包括字符串查找、轉換、比較、替換、拆分和截取,需要的朋友可以參考下
    2025-04-04
  • Java?Web開發(fā)中的分頁與參數校驗舉例詳解

    Java?Web開發(fā)中的分頁與參數校驗舉例詳解

    這篇文章主要介紹了JavaWeb開發(fā)中的分頁設計和參數校驗,分頁設計通過分頁查詢參數優(yōu)化查詢性能,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-02-02
  • 數據庫CURD必備搭檔mybatis?plus詳解

    數據庫CURD必備搭檔mybatis?plus詳解

    這篇文章主要為大家介紹了數據庫CURD必備搭檔mybatis?plus詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05

最新評論