smallrye / smallrye-opentelemetry

SmallRye OpenTelemetry - A CDI and Jakarta REST implementation of OpenTelemetry Tracing
Apache License 2.0
21 stars 16 forks source link

OpenTelemetryClientFilter not correctly initialized #316

Open fabrii opened 5 months ago

fabrii commented 5 months ago

Hello!

I am working with OpenTelemetry in WildFly 32.0.1 that uses smallrye-opentelemetry 2.6.0. I dont know if this a smallrye-opentelemetry bug or a wildfly bug.

I create my RestClients like this:

Interface

@Path("/v1/example")
@Consumes(MediaType.APPLICATION_JSON)
@RegisterProvider(ObjectMapperContextResolver.class)
@RegisterProvider(BackendExceptionMapper.class)
public interface ExampleInterface extends Closeable {

    @GET
    @Path("/{id:[1-9][0-9]*}")
    public Example findById(@PathParam("id") Long id);
}

Generic Client

public class GenericClient<T extends Closeable> implements Serializable {

    private Class<T> interfaceClass;
    private T proxy;
    private String baseUrl;
    private ClientRequestFilter[] filters;

    public GenericClient(Class c, String burl, ClientRequestFilter... filters) {
        this.interfaceClass= c;
        this.baseUrl = burl;
        this.filters = filters;
    }

    protected T getProxy() {
        if (proxy == null) {
            RestClientBuilder b = RestClientBuilder.newBuilder()
                    .baseUri(UriBuilder.fromPath(baseUrl).build());
            if (filters != null) {
                for (ClientRequestFilter fil : filters) {
                    b = b.register(fil);
                }
            }
            proxy = b.build(interfaceClass);
        }

        return proxy;
    }

    @PreDestroy
    public void preDestroy() {
        try {
            if (proxy != null){
                proxy.close();
            } 
        } catch (Exception ex) {
            LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
        }
    }

}

Client

@Named
@RequestScoped
public class ExampleClient extends GenericClient<ExampleInterface> {

    public ExampleClient () {
        super(ExampleInterface.class, ConfigProvider.getConfig().getValue("backend.baseUrl", String.class), new AuthHeaderRequestFilter());
    }

    public Example findById(Long id) throws Exception {
        return getProxy().findById(id);
    }

}

I read in the WildFly docs, that the OpenTelemetryClientFilter is registered by default for Jakarta Rest Clients, but it is not working as no traces are sent to the collector. I think the problem is related to injection, because of the following:

If I manually register the filter, like this:

@Path("/v1/example")
@Consumes(MediaType.APPLICATION_JSON)
@RegisterProvider(ObjectMapperContextResolver.class)
@RegisterProvider(BackendExceptionMapper.class)
@RegisterProvider(OpenTelemetryClientFilter.class) <----
public interface ExampleInterface extends Closeable {

    @GET
    @Path("/{id:[1-9][0-9]*}")
    public Example findById(@PathParam("id") Long id);
}

I get the following log:

WARN  [org.jboss.resteasy.resteasy_jaxrs.i18n] (default task-11) RESTEASY002160: Provider instance io.smallrye.opentelemetry.implementation.rest.OpenTelemetryClientFilter is already registered.  2nd registration is being ignored

So, the Filter seems to be registered, but not working.

To bypass this problem, I created a CustomOpenTelemetryClientFilter, that is basically a copy of OpenTelemetryClientFilter with different name. After registering with @RegisterProvider(CustomOpenTelemetryClientFilter.class) on the interface level, the traces are correctly sent to the collector.

I think that the problem might be related to the injection of

@Inject
public OpenTelemetryClientFilter(final OpenTelemetry openTelemetry) {}

in the automatic registration of the filter.

radcortez commented 5 months ago

@jasondlee can you help?

radcortez commented 4 months ago

I've added a test that works in SR OpenTelemetry (but we use Jetty).

@fabrii are you able to debug and check the filter if instrumenter is null or if the constructor with the OpenTelemetry injection is being called?