Spring boot version 3.0.0 is not working with jaeger 3.3.1 (latest version)

3.1k views Asked by At

I am using spring boot version 3.3.1 in my spring boot project with jaeger for distributed tracing (version 3.3.1 which latest recommended version) and my java version is 17.

I have added dependencies as follows:

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>3.0.0</version>
   <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
   <groupId>io.opentracing.contrib</groupId>
   <artifactId>opentracing-spring-jaeger-cloud-starter</artifactId>
   <version>3.3.1</version>
</dependency>

This my configuration file:

package com.example.jaegerclient.config;

import io.jaegertracing.internal.JaegerTracer;
import io.jaegertracing.internal.samplers.ConstSampler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class JaegerConfig {

    @Bean
    public WebClient webClient() {
        return WebClient.create();
    }

    @Bean
    public JaegerTracer jaegerTracer() {

        return new io.jaegertracing.Configuration("jaeger-client")
                .withSampler(new io.jaegertracing.Configuration.SamplerConfiguration().withType(ConstSampler.TYPE)
                        .withParam(1))
                .withReporter(new io.jaegertracing.Configuration.ReporterConfiguration().withLogSpans(true))
                .getTracer();
    }
}

Upon starting application I can see in logs that jaeger has configured

2022-12-20T12:22:51.543+05:30 INFO 22028 --- [ main] io.jaegertracing.Configuration : Initialized tracer=JaegerTracer(version=Java-1.1.0, serviceName=jaeger-client, reporter=CompositeReporter(reporters=[RemoteReporter(sender=UdpSender(), closeEnqueueTimeout=1000), LoggingReporter(logger=Logger[io.jaegertracing.internal.reporters.LoggingReporter])]), sampler=ConstSampler(decision=true, tags={sampler.type=const, sampler.param=true}), tags={hostname=xyz, jaeger.version=Java-1.1.0, ip=192.xxx.xx.xx}, zipkinSharedRpcSpan=false, expandExceptionLogs=false, useTraceId128Bit=false)

But I am not able see the service in jaeger UI or any traces even after I hit the request.

When I use spring boot lower than 3.0.0 like 2.7.7, I am able to see the service and traces in jaeger UI.

I just want to know that jaeger is not compatible with spring boot 3.0.0 or I am doing something wrong.

Thanks in advance.

3

There are 3 answers

0
Priyanshu Parate On

yes, currently it is not supporting, I also tried. with no change, it work on the 2.7.7 version

0
Sergei I. On

Looks like it is a known issue #146 due to Spring removing support for spring.factories. A suggested workaround:

As temporary workaround you may create plain text file META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports and put io.opentracing.contrib.java.spring.jaeger.starter.JaegerAutoConfiguration into it.

2
Mohammad Mahdi Tilab On

I integrated Jaeger with Spring boot 3.0 with sample code in following repository. Also you can find my article in Persian language:

https://github.com/m-tilab/springboot3-jaeger-integration

https://virgool.io/@mohammadmahditilab/%D8%A7%D8%A8%D8%B2%D8%A7%D8%B1%DB%8C-%D8%A8%D9%87-%D9%86%D8%A7%D9%85-jaeger-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%A8%D9%87%D8%AA%D8%B1-%D8%AF%DB%8C%D8%AF%D9%86-%D8%AE%D8%B7%D8%A7%D9%87%D8%A7-%D8%AF%D8%B1-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-%D9%85%D8%A7%DA%A9%D8%B1%D9%88%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-%D9%88-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-%D8%A2%D9%86-%D8%AF%D8%B1-spring-boot-30-c6nugawkzlyh

You need to create main span manually and initialize your Tracker bean in start up. look at following codes:

@Configuration
public class JaegerConfig {

    @Value("${opentracing.jaeger.enabled:false}")
    private boolean jaegerEnabled;

    @Value("${opentracing.jaeger.udp-sender.host}")
    private String opentracingUdpSenderHost;

    @Value("${opentracing.jaeger.udp-sender.port}")
    private Integer opentracingUdpSenderPort;

    @Bean
    public Tracer jaegerTracer() {

        if (!jaegerEnabled)
            return NoopTracerFactory.create();

        JaegerTracer tracer = new io.jaegertracing.Configuration("instrument-list-job")
                .withSampler(new io.jaegertracing.Configuration.SamplerConfiguration().withType(ConstSampler.TYPE).withParam(1))
                .withReporter(new io.jaegertracing.Configuration.ReporterConfiguration()
                        .withSender(new io.jaegertracing.Configuration.SenderConfiguration()
                                .withAgentHost(opentracingUdpSenderHost).withAgentPort(opentracingUdpSenderPort)).withLogSpans(true)).getTracer();

        GlobalTracer.registerIfAbsent(tracer);

        return tracer;
    }
}

Also, Create main span as follow:

@Configuration
@Order(Integer.MIN_VALUE)
public class JaegerWebFilter implements WebFilter {

    @Value("${application.name}")
    private String applicationName;

    @Autowired
    private Tracer tracer;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {

        Span span = tracer.buildSpan(applicationName).start();

        Scope scope = tracer.activateSpan(span);

        return chain.filter(exchange).doFinally(signalType -> {

            span.log(spanLogDecorator(exchange, span));

            scope.close();
            span.finish();
        });
    }

    @Nullable
    private Map<String, Object> spanLogDecorator(ServerWebExchange exchange, Span span) {

        final Object handler = exchange.getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE);
        if (handler == null) {
            return null;
        }

        final Map<String, Object> logs = new HashMap<>(4);
        logs.put("event", "handle");

        final Object pattern = exchange.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        final String patternAsString = pattern == null ? null : pattern.toString();
        if (pattern != null) {
            logs.put("handler", patternAsString);
        }

        if (handler instanceof HandlerMethod handlerMethod) {

            final String methodName = handlerMethod.getMethod().getName();
            logs.put("handler.method_name", handlerMethod.getMethod().getName());
            span.setOperationName(methodName);
            logs.put("handler.class_simple_name", handlerMethod.getBeanType().getSimpleName());
        } else {
            if (pattern != null) {
                span.setOperationName(patternAsString);
            }
            logs.put("handler.class_simple_name", handler.getClass().getSimpleName());
        }

        Tags.COMPONENT.set(span, "java-spring-webflux");
        final ServerHttpRequest request = exchange.getRequest();
        Tags.HTTP_METHOD.set(span, request.getMethod().name());
        Tags.HTTP_URL.set(span, request.getURI().toString());
        Optional.ofNullable(request.getRemoteAddress()).ifPresent(remoteAddress -> {
            Tags.PEER_HOSTNAME.set(span, remoteAddress.getHostString());
            Tags.PEER_PORT.set(span, remoteAddress.getPort());
            Optional.ofNullable(remoteAddress.getAddress()).ifPresent(inetAddress -> {
                if (inetAddress instanceof Inet6Address) {
                    Tags.PEER_HOST_IPV6.set(span, inetAddress.getHostAddress());
                } else {
                    Tags.PEER_HOST_IPV4.set(span, inetAddress.getHostAddress());
                }
            });
        });

        return logs;
    }
}