最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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包復(fù)制到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

啟動參數(shù)

新增啟動參數(shù)

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

啟動程序后,嘗試通過網(wǎng)關(guān)進行接口調(diào)用,可以在Skywalking-ui上看到鏈路已經(jīng)串起來了

調(diào)用鏈路

但是有個問題,日志里記錄的日志始終不顯示正確的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的調(diào)用鏈路里,放入 < SKYWALKING_CONTEXT_SNAPSHOT - ContextSnapshot >

image.png

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

怎么讓日志獲取到traceId

網(wǎng)上找了下資料,在這里[https://github.com/reactor/reactor-core/blob/main/docs/asciidoc/faq.adoc#context.api]發(fā)現(xiàn)了相關(guā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解析的詳細內(nèi)容,更多關(guān)于SpringCloudGateway Skywalking的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java實現(xiàn)雪花算法的原理

    Java實現(xiàn)雪花算法的原理

    這篇文章主要介紹了Java實現(xiàn)雪花算法的原理,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • 詳解Java對象轉(zhuǎn)換神器MapStruct庫的使用

    詳解Java對象轉(zhuǎn)換神器MapStruct庫的使用

    在我們?nèi)粘i_發(fā)的程序中,為了各層之間解耦,一般會定義不同的對象用來在不同層之間傳遞數(shù)據(jù)。當(dāng)在不同層之間傳輸數(shù)據(jù)時,不可避免地經(jīng)常需要將這些對象進行相互轉(zhuǎn)換。今天給大家介紹一個對象轉(zhuǎn)換工具MapStruct,代碼簡潔安全、性能高,強烈推薦
    2022-09-09
  • Mybatis 如何在配置文件中給實體類起別名

    Mybatis 如何在配置文件中給實體類起別名

    這篇文章主要介紹了Mybatis 如何在配置文件中給實體類起別名的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 如何使用Java實現(xiàn)請求deepseek

    如何使用Java實現(xiàn)請求deepseek

    這篇文章主要為大家詳細介紹了如何使用Java實現(xiàn)請求deepseek功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-02-02
  • springBoot定時任務(wù)處理類的實現(xiàn)代碼

    springBoot定時任務(wù)處理類的實現(xiàn)代碼

    這篇文章主要介紹了springBoot定時任務(wù)處理類,需要的朋友可以參考下
    2018-06-06
  • SpringBoot如何使用RateLimiter通過AOP方式進行限流

    SpringBoot如何使用RateLimiter通過AOP方式進行限流

    這篇文章主要介紹了SpringBoot如何使用RateLimiter通過AOP方式進行限流,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 基于Arrays.sort()和lambda表達式

    基于Arrays.sort()和lambda表達式

    這篇文章主要介紹了Arrays.sort()和lambda表達式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java如何接收前端easyui?datagrid傳遞的數(shù)組參數(shù)

    Java如何接收前端easyui?datagrid傳遞的數(shù)組參數(shù)

    這篇文章分享一下怎么在easyui的datagrid刷新表格時,在后端java代碼中接收datagrid傳遞的數(shù)組參數(shù),本文通過實例代碼給大家介紹的非常詳細,需要的朋友參考下吧
    2023-11-11
  • Spring AOP如何自定義注解實現(xiàn)審計或日志記錄(完整代碼)

    Spring AOP如何自定義注解實現(xiàn)審計或日志記錄(完整代碼)

    這篇文章主要介紹了Spring AOP如何自定義注解實現(xiàn)審計或日志記錄(完整代碼),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • springboot項目中application.properties無法變成小樹葉問題解決方案

    springboot項目中application.properties無法變成小樹葉問題解決方案

    這篇文章主要介紹了springboot項目中application.properties無法變成小樹葉問題解決,本文通過圖文實例代碼相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09

最新評論

建平县| 安庆市| 开化县| 白水县| 岳阳市| 左贡县| 广水市| 徐水县| 邯郸市| 青铜峡市| 西华县| 文山县| 寿光市| 海南省| 桐柏县| 本溪市| 广宗县| 临城县| 喀什市| 西宁市| 永年县| 措美县| 齐河县| 山东| 阜城县| 凉城县| 兰州市| 威海市| 东台市| 闽侯县| 阿鲁科尔沁旗| 东乡县| 杭锦后旗| 福贡县| 兴业县| 凤凰县| 盐城市| 从化市| 阿拉善右旗| 兴国县| 曲松县|