Giter Club home page Giter Club logo

java-jaxrs's Introduction

Build Status Released Version

OpenTracing JAX-RS Instrumentation

OpenTracing instrumentation for JAX-RS standard. It supports tracing of server and client requests.

Instrumentation by default adds a set of standard HTTP tags and as an operation name it uses a string defined in @Path annotation. Custom tags or operation name can be added via span decorators. This instrumentation also supports tracing of (de)serialization of response and requests bodies.

MicroProfile-OpenTracing

This implementation is compatible with MicroProfile-OpenTracing (MP-OT). It can be used as a building block of MicroProfile compatible application server. Note that application servers have to add a few things which are not provided by this project: CDI interceptor, automatically register tracing filters into client... SmallRye-OpenTracing uses this library to provide a vendor neutral implementation of MP-OT.

Tracing server requests

Tracing server requests requires two components: JAX-RS dynamic feature and servlet filter. Span is started in JAX-RS filter and finished in servlet filter.

Auto discovery

Tracing can be automatically enabled by adding the following dependency on classpath. This mechanism requires a tracer to be registered in GlobalTracer. This is typically done in ServletContextListener. Note that JAX-RS clients are not automatically instrumented. Client tracing feature has to be explicitly registered to all client instances.

<dependency>
  <groupId>io.opentracing.contrib</groupId>
  <artifactId>opentracing-jaxrs2-discovery</artifactId>
</dependency>

Custom configuration

For custom configuration use the following dependency:

<dependency>
  <groupId>io.opentracing.contrib</groupId>
  <artifactId>opentracing-jaxrs2</artifactId>
</dependency>

The Custom configuration can be achieved by adding ServerTracingDynamicFeature to Application.singletons or by wrapping the feature with a class annotated with @Provider. This approach does not require adding all classes to singletons set.

Dynamic feature registration via custom provider:

@Provider
public class TracingInitializer implements DynamicFeature {

  private final ServerTracingDynamicFeature serverTracingDynamicFeature =
      new ServerTracingDynamicFeature.Builder(GlobalTracer.get())
          .withOperationNameProvider(ClassNameOperationName.newBuilder())
      .build();

  @Override
  public void configure(ResourceInfo resourceInfo, FeatureContext context) {
    serverTracingDynamicFeature.configure(resourceInfo, context);
  }
}

Dynamic feature registration via singletons:

public class JaxRsApp extends javax.ws.rs.core.Application {

  @Override
  public Set<Object> getSingletons() {
    DynamicFeature tracing = new ServerTracingDynamicFeature.Builder(tracer)
        .withDecorators(decorators)
        .withSerializationDecorators(serializationDecorators)
        .build();

    return Collections.singleton(tracing);
  }
}

Filter registration:

@WebListener
public class OpenTracingContextInitializer implements javax.servlet.ServletContextListener {

  @Override
  public void contextInitialized(ServletContextEvent servletContextEvent) {
    io.opentracing.tracer tracer = new ....
    GlobalTracer.register(tracer); // or preferably use CDI
    
    ServletContext servletContext = servletContextEvent.getServletContext();
    Dynamic filterRegistration = servletContext
        .addFilter("tracingFilter", new SpanFinishingFilter());
    filterRegistration.setAsyncSupported(true);
    filterRegistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ASYNC), false, "*");
  }
}

An example of traced REST endpoint:

@GET
@Path("/hello")
@Traced(operationName = "helloRenamed") // optional, see javadoc
public Response hello() { // optional to get server span context

  // this span will be ChildOf of span representing server request processing
  Span childSpan = tracer.buildSpan("businessOperation")
          .start())

   // business logic
  childSpan.finish();

  return Response.status(Response.Status.OK).build();
}

Tracing client requests

Client client = ClientBuilder.newBuilder()
  .reqister(ClientTracingFeature.class)
  .build();

Response response = client.target("http://localhost/endpoint")
  .request()
  .property(TracingProperties.CHILD_OF, parentSpanContext) // optional, by default new parent is inferred from span source
  .property(TracingProperties.TRACING_DISABLED, false) // optional, by default everything is traced
  .get();

Async

Async requests are executed in a different thread than when the client has been invoked, therefore spans representing client requests are not connected to appropriate parent. To fix this JAX-RS client has to use OpenTracing-aware ExecutorService.

Jersey

@ClientAsyncExecutor
public class DelegateExecutorServiceProvider implements ExecutorServiceProvider {

  private final ExecutorService executorService;

  public DelegateExecutorServiceProvider(ExecutorService executorService) {
    this.executorService = executorService;
  }

  @Override
  public ExecutorService getExecutorService() {
    return executorService;
  }

  @Override
  public void dispose(ExecutorService executorService) {
  }
}

Client client = ClientBuilder.newBuilder()
    .register(new DelegateExecutorServiceProvider(
        new TracedExecutorService(Executors.newFixedThreadPool(8), tracer)))
    ...

RestEasy

Client client = new ResteasyClientBuilder()
    .executorService(new TracedExecutorService(Executors.newFixedThreadPool(8), tracer))
    ...

Development

./mvnw clean install

Release

Follow instructions in RELEASE

License

Apache 2.0 License.

java-jaxrs's People

Contributors

bensigelman avatar bpedman avatar cyberdelia avatar hypnoce avatar jerchung avatar joshlong avatar jpkrohling avatar mpetazzoni avatar objectiser avatar pavolloffay avatar rishi-lgtm avatar rnorth avatar safris avatar shreya1771 avatar sjoerdtalsma avatar tmszdmsk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

java-jaxrs's Issues

activeSpan being reused

I believe we're seeing an issue using opentracing-contrib:java-jaxrx:0.1.4, io.zipkin.brave:brave:4.19.2 and brave-opentracing-0.30.3 (all of this inside Dropwizard 1.2), however I'm very new to open tracing in and the available Java tracers and I'm hoping someone here can point me in the right direction:

The active span is not being cleared across requests and all spans that are created in requests are being tagged to the parent thread created in the first request to the server.

On this line the finishing filter pulls the active scope via the tracer's scope manager.

This active scope is closed via it's close() method. This eventually calls this close implementation in the BraveScopeManager. This scope manager has a noop close implementation and thus the scope remains open.

Then in later requests the JAXRS filter grabs the active span. On subsequent requests the active span is set to span that was created during the first request and all traces end up being children of the first trace ever created.

I'm unsure of the relation between Spans and Scopes in this situation but we've confirmed that the active span is being reused across all requests.

For context this is how we are initializing our filters:

AsyncReporter<Span> reporter = AsyncReporter.builder(sender).build();

Tracer tracer = BraveTracer
        .newBuilder(
                Tracing.newBuilder()
                        .localServiceName(openTracingConfig.getServiceName())
                        .spanReporter(reporter)
                        .sampler(Sampler.ALWAYS_SAMPLE)
                        .build()
        )
        .build();


GlobalTracer.register(tracer);

// Register feature / servlet filter to start traces
environment.jersey().register(
        new ServerTracingDynamicFeature.Builder(tracer).build()    
 );

// Register filter to end traces
FilterRegistration.Dynamic registration = environment.servlets()
        .addFilter("tracing-filter", new SpanFinishingFilter(tracer));

registration.setAsyncSupported(true);
registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "*");

Improve README

I cannot figure out what is going on in the README. It seems to suggest two different ways to instrument frameworks, but no straightforward explanation of the internals and/or how the default configuration works. I am struggling to understand how to instrument a Jersey server given that only an example client is provided in the README. How do I instrument a server for client requests, server responses, and span closing? Is that the default configuration? I have no idea from the documentation.

Fix broken auto-discovery tests

Auto discovery tests are broken. The test is reported as successful but it was not executed.

I would like to migrate it from swarm to something else e.g. wildfly? The other question is do we want to keep this test? It was useful when we didn't integrate with servlet filter now filter has to be added manually.

Update JAX-RS to 2.1

Hi,

as requested in #49, JAX-RS was not updated to the latest version 2.1.
Do you think it brings value to do so ?

Thanks !

Francois

Integrate with servlet filter

Jax-rs instrumentation cannot trace all request:

  • no URL mapping
  • unauthenticated requests

I propose to use servlet filter in conjunction with jax-rs filters. However, jax-rs filters should work alone too, but when there is a span created in filter it should be respected.

Multiple ServerTracingDynamicFeature instances

The JAX-RS framework seems instantiating the ServerTracingDynamicFeature instance by the default constructor and uses the instance to call the configure method. This instance has its own Builder instance instantiated by the "Builder(Tracer tracer)" and it is referenced in the configure method.

When I call (following the README)

ServerTracingDynamicFeature.Builder
   .traceAll(yourPreferredTracer)
   .withDecorators(Arrays.asList(ServerSpanDecorator.HTTP_WILDCARD_PATH_OPERATION_NAME, 
    ServerSpanDecorator.STANDARD_TAGS))
    .build();

, this instantiates another instance of the ServerTracingDynamicFeature and an inner Builder class. This instance is not used by the framework for the configure call and the "tradeAll" or "withDecorators" method call don't have effects.

Mark the JAX-RS dependency as `provided`

The JAX-RS dependency should be marked as provided, as the party consuming the OT instrumentation has a concrete implementation as dependency already.

This is what's shown as mvn dependency:tree for a Wildfly Swarm application when requiring io.opentracing.contrib:opentracing-jaxrs2:0.0.8:

[INFO] +- io.opentracing.contrib:opentracing-jaxrs2:jar:0.0.8:compile
[INFO] |  +- io.opentracing.contrib:opentracing-concurrent:jar:0.0.1:compile
[INFO] |  \- javax.ws.rs:javax.ws.rs-api:jar:2.0.1:compile

SpanFinishingFilter does not wipe out previous span

As described here https://gitter.im/jaegertracing/Lobby?at=5a718da6e217167e2c22d430, I'm getting nested spans when using the current setup (with jaeger-core v.0.23.0, java-jaxrs v0.1.0) and dropwizard:

GlobalTracer.register(tracer);
DynamicFeature tracing = new ServerTracingDynamicFeature.Builder(tracer)
    .withSkipPattern("(\\/app\\/apiadmin\\/ping$|\\/api\\/app\\/v.*\\/view\\/.*$)")
    .withTraceSerialization(false)
    .build();

env.jersey().register(tracing);

env.servlets()
    .addFilter("span-finisher", new SpanFinishingFilter(tracer))
.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");

Turns out the old span is kept in the thread and becomes the parent span when the first thread is reused.

AS = Active Span, PS = Parent Span, TID = Trace Id. Looks like the parent span is kept for each thread. The "Finished span" output is a modified version of the SpanWrapper that prints out the span stored.

[22][dw-22 - GET /api/app/v1/lists/11-5898345890e0b10777347c39] [AS: 5509402670663705252/PS: 0/TID: 5509402670663705252]
[22][Thread[dw-22,5,main]] Finishing span 4c755489f57fa2a4:4c755489f57fa2a4:0:1 - api/app/v1/lists/{listId}
[30][dw-30 - GET /api/app/v1/lists/11-5898345890e0b10777347c39] [AS: 8731863753192287363/PS: 0/TID: 8731863753192287363]
[30][Thread[dw-30,5,main]] Finishing span 792dcfd1f422ac83:792dcfd1f422ac83:0:1 - api/app/v1/lists/{listId}
[32][dw-32 - GET /api/app/v1/lists/11-5898345890e0b10777347c39] [AS: 4773869689215032917/PS: 0/TID: 4773869689215032917]
[32][Thread[dw-32,5,main]] Finishing span 4240313075aa9e55:4240313075aa9e55:0:1 - api/app/v1/lists/{listId}

[22][dw-22 - GET /api/app/v1/lists/11-5898345890e0b10777347c39] [AS: -4035566196088312288/PS: 5509402670663705252/TID: 5509402670663705252]
[22][Thread[dw-22,5,main]] Finishing span 4c755489f57fa2a4:c7fec9ed0e94ee20:4c755489f57fa2a4:1 - api/app/v1/lists/{listId}
[30][dw-30 - GET /api/app/v1/lists/11-5898345890e0b10777347c39] [AS: 7263183733100460979/PS: 8731863753192287363/TID: 8731863753192287363]
[30][Thread[dw-30,5,main]] Finishing span 792dcfd1f422ac83:64cc031f8dd93bb3:792dcfd1f422ac83:1 - api/app/v1/lists/{listId}
[32][dw-32 - GET /api/app/v1/lists/11-5898345890e0b10777347c39] [AS: 8179141403428200331/PS: 4773869689215032917/TID: 4773869689215032917]
[32][Thread[dw-32,5,main]] Finishing span 4240313075aa9e55:718225c57f071f8b:4240313075aa9e55:1 - api/app/v1/lists/{listId}

Looking at
https://github.com/opentracing-contrib/java-jaxrs/blob/master/opentracing-jaxrs2/src/main/java/io/opentracing/contrib/jaxrs2/server/SpanFinishingFilter.java#L58 , is there a slight possiblity that the ThreadLocalScope is never closed in the SpanFinishingFilter (I can only find close as part of the catch clause) ?

I get expected behaviour when I move the closing part outside the catch block, but that can have other implications I am not aware of.

Apache CXF client set custom ExecutorService

Apache client does not allow to specify custom ExecutorService(in our case OpenTracing-aware), therefore when simultaneously invoking multiple async requests parent is not correctly inferred.

ClientTracingFilter does not close activated Scope

ClientTracingFilter calls startActive on request, not does not close the activated Scope on response. This leaves incorrect Scope in ThreadLocalScopeManager and breaks closing of other (activated earlier) scopes.

What is not traced

Server

  • URLs without mapping. see also #13
  • exceptions in handlers. see also #13, #50 - Traced by servlet filter SpanFinishingFilter.
  • Exceptions added to AsyncResponse#resume() are not propagated to onComplete or onError async callbacks

Client

  • interceptors do not catch UnknownHostException #30
  • some impls do not allow to specify custom ExecutorService (which propagates active span), therefore when invoking multiple async requests at the same time created spans can have a wrong parent #37 CXF does not support this but it invokes filters in the same thread, however async response filter is executed in a different thread so it cannot close scopes!

When accessing a root resource StringIndexOutOfBoundsException is thrown

This is a stack trace, I think you need to check if a path is empty as well:

java.lang.StringIndexOutOfBoundsException: String index out of range: 0
	at java.lang.String.charAt(String.java:658) ~[?:1.8.0_151]
	at io.opentracing.contrib.jaxrs2.server.OperationNameProvider$WildcardOperationName.operationName(OperationNameProvider.java:89) ~[opentracing-jaxrs2-0.1.0.jar:?]
	at io.opentracing.contrib.jaxrs2.server.ServerTracingFilter.filter(ServerTracingFilter.java:67) ~[opentracing-jaxrs2-0.1.0.jar:?]
	at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:132) ~[jersey-server-2.26.jar:?]
	at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:68) ~[jersey-server-2.26.jar:?]
	at org.glassfish.jersey.process.internal.Stages.process(Stages.java:197) ~[jersey-common-2.26.jar:?]
	at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:269) [jersey-server-2.26.jar:?]
	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:272) [jersey-common-2.26.jar:?]

Builder.withTraceNothing() doesn't seem to work

Actually it works a little too wel, as it indeed traces nothing.
However, it promises:

/**
 * Only resources annotated with {@link Traced} will be traced.
 * @return builder
 */
public Builder withTraceNothing() {
    allTraced = false;
    return this;
}

I believe the problem is in the configure method:

public void configure(ResourceInfo resourceInfo, FeatureContext context) {
    // TODO why it is called twice for the same endpoint
    if (!tracingDisabled(resourceInfo) && builder.allTraced) {
        log(resourceInfo);
        // .. configuration
    }
}

Here, tracingDisabled concerns itself with the @Traced annotation. Therefore I think the && should be changed to || in order to fulfill the promised annotation support.
while you're at it, short-circuit on the boolean instead of the annotation search:

if (builder.allTraced || !tracingDisabled(resourceInfo)) { ...

Using GlobalTracer.register() doesn't enable JAX-RS instrumentation in Spring Boog

I've been struggling to integrate the library with Spring Boot the same way I did with Wildfly Swarm on a previous project. My first thought was to declare a Jaeger Bean at application level and inject it when calling to GlobalTracer.register() at application startup on the main() method:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
	ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
        GlobalTracer.register(context.getBean(Tracer.class));
    }
    
    @Bean
    public JacksonJsonProvider jsonProvider() {
        return new JacksonJsonProvider();
    }
    
    @Bean
    public Tracer tracer() {
    	return new Configuration("orders", 
				new SamplerConfiguration(ProbabilisticSampler.TYPE, 1),
				new Configuration.ReporterConfiguration()).getTracer();
    }

With this I got the tracer created and usable for any ActiveSpan I may create, but the JAX-RS instrumentation just wasn't there. I changed the approach by using a ServletContextListener and performing there the call to the register method of GlobalTracer to initialize the JAX-RS instrumentation:

@WebListener
public class TracingContextListener implements ServletContextListener {

	@Autowired
	Tracer tracer;

	@Override
	public void contextDestroyed(ServletContextEvent arg0) {

	}

	@Override
	public void contextInitialized(ServletContextEvent servletContextEvent) {
		GlobalTracer.register(context.getBean(Tracer.class));
	}

}

The result was the same. I finally managed to make the instrumentation work by manually declaring the ServerTracingDynamicFeature and the SpanFinishingFilter manually as beans:

@SpringBootApplication
public class Application {
	
    @Autowired
    private Tracer tracer;

    public static void main(String[] args) {
	SpringApplication.run(Application.class, args);
    }
    
    @Bean
    public JacksonJsonProvider jsonProvider() {
        return new JacksonJsonProvider();
    }
    
    @Bean
    public Tracer tracer() {
    	return new Configuration("orders", 
				new SamplerConfiguration(ProbabilisticSampler.TYPE, 1),
				new Configuration.ReporterConfiguration()).getTracer();
    }
    
    @Bean
    public FilterRegistrationBean spanFinishingFilterBean() {
    	final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
    	filterRegBean.setFilter(new SpanFinishingFilter(tracer));
    	filterRegBean.addUrlPatterns("/*");
    	filterRegBean.setEnabled(Boolean.TRUE);
    	filterRegBean.setName("SpanFinishingFilter");
    	filterRegBean.setAsyncSupported(Boolean.TRUE);
    	return filterRegBean;
    }
    
    @Bean
    public DynamicFeature serverTracingDynamicFeatureBean() {
    	return new ServerTracingDynamicFeature.Builder(tracer)
    	        .build();
    }

}

Is this the way to go in Spring Boot? Is there any way to perform this configuration automatically by calling GlobalTracer.register() as in Wildfly Swarm?

WildcardOperationName can't get value of @Path when using interface

Currently, WildcardOperationName won't be able to get value of @Path annotation if using API interface as follows:

// Interface, TestService.java
@Path("/foo")
public interface TestService {
  @GET
  @Path("/bar")
  Response test();
}

// Implementation, TestServiceImpl.java
public class TestServiceImpl implements TestService {
  public Response test() {
    return Response.ok().build();
  }
}

Probably can add some logic after here to get the value from interface class as follows:

if (classPath.isEmpth() || methodPath.isEmpty()) {
  for (Class<?> c : clazz.getInterfaces()) {
    // Get @Path value from interface class
  }
}

JAX-RS intergation doesn't work well with web servlet filter

Extracted from: #13 (comment)

Recently when I was working on Opentracing in Dropwizard project I noticed that jaxrs and servlet integrations do not play well together, i.e. jaxrs-integration spans are not children of servlet-integration created spans. Maybe original idea was that you should have only one of them installed but not all endpoints have to be handled by jaxrs so it is beneficial to have both.
My idea would be to modify jaxrs integration in such a way that:

  • if there is active span (presumably created by servlet integration), don't extract span information from request headers
  • if there is no active span - proceed as it is now.

Exceptional async server spans are not marked with an error tag or HTTP status

Firstly, thanks for this useful library - it's helped us very quickly instrument Dropwizard services for OpenTracing!

We're seeing a bit of an edge case, perhaps. We have the following simple test endpoints:

    @GET
    @Path("/runtime")
    public void throwRuntimeException() {
        throw new RuntimeException();
    }

    @GET
    @Path("/runtime/async")
    public void throwRuntimeException(@Suspended AsyncResponse async) {
        new Thread(() -> {
            sleepUninterruptibly(5, SECONDS);
            async.resume(new RuntimeException());
        }).start();
    }

(N.B. We have an exception mapper in place - not sure if this is relevant)

What we're seeing is that:

  1. the sync endpoint produces a span with the error tag set to true, and there is no HTTP status set
  2. the async endpoint produces a span without an error tag - in fact there's no way to tell that the span was an error without looking at the HTTP response code recorded by a caller's client span.

I'd have expected that at least the error tag would be set on the async server span. (It would be nice if the HTTP status code were set too, but this is really a separate question).

It feels like SpanFinishingFilter.SpanFinisher is the right place to set the error tag. At present, it just finishes the span without modifying it, regardless of the response:

    @Override
    public void onComplete(AsyncEvent event) throws IOException {
        spanWrapper.finish();
    }

I'm considering raising a PR to amend to:

    @Override
    public void onComplete(AsyncEvent event) throws IOException {
        if (event.getSuppliedResponse() instanceof Response) {
            final int status = ((Response) event.getSuppliedResponse()).getStatus();
            if (status >= 500) {
              Tags.ERROR.set(spanWrapper.get(), true);
            }
        }

        spanWrapper.finish();
    }

I don't really like having to use the status code, so I wondered if you have any different suggestions!

Spans/traces leak between requests if child spans not finished correctly

I don't think this is a bug per se, but perhaps a missed opportunity: the current implementation relies on developers' span handling being bug-free, otherwise extremely undesirable traces are generated.

As an example, we had a service where a span had been started but not finished due to a bug in service code. This imbalance between start/finish meant that, when the server started handling a new request, there was already an unrelated span in on the threadlocal. Future requests served on the same thread would all pile on top of the same trace.

The effect for us was massive, useless traces, with many thousands of spans and lasting for minutes or hours.

Obviously 'don't forget to finish spans' would be good advice, but I think the JAX-RS filter could do more to limit the damage when such a bug inevitably occurs.

ServerTracingFilter seems to actively try and join any existing (thread local) spans - I can see that this was a deliberate move as part of #74. I'm wondering if this behaviour could be made configurable, though, so that users can opt out.

If it helps, I've created an example repo to demonstrate the issue:

We have forked ServerTracingFilter locally to do this, so could easily submit a PR if you'd like.

FWIW we did also try a few approaches to fix this in SpanFinishingFilter, but found it difficult to correctly clear out thread local state. In the end, an approach of ignoring the state in ServerTracingFilter was the only thing that worked for us.

I think this is similar to, but not the same as, #87.

Use GlobalTracer as a default configuration

ServerTracingDynamicFeature is annotated with @Provider but there si no suitable constructor [1].

We might provide a default constructor:

ServerTracingDynamicFeature() {
   this(new Builder(GlobalTracer.get()));
}

Then the issue might be how to exclude registration if users would like to use custom tracing configuration (e.g. span decorators)

[1]: http://download.oracle.com/otn-pub/jcp/jaxrs-1.0-fr-eval-oth-JSpec/jaxrs-1.0-final-spec.pdf section 4.1.1

cc @jpkrohling @johnament

Client instrumentation does not finish spans after ConnectionException

It seems that ClientTracingFilter.filter(request, response) is not called after:
javax.ws.rs.ProcessingException: java.net.ConnectException: Connection refused (Connection refused)

ClientRuntime.invoke from jersey client:

    public ClientResponse invoke(final ClientRequest request) {
        ClientResponse response;
        try {
            try {
                response = connector.apply(addUserAgent(Stages.process(request, requestProcessingRoot), connector.getName()));
            } catch (final AbortException aborted) {
                response = aborted.getAbortResponse();
            }

            return Stages.process(response, responseProcessingRoot);
        } catch (final ProcessingException pe) {
            throw pe;
        } catch (final Throwable t) {
            throw new ProcessingException(t.getMessage(), t);
        }
    }

The exception is thrown from the line with response = conn... and the execution skips over Stages.process(response, responseProcessingRoot) which would run the filter.

Maybe there is some other mechanism which can react to this exception.

Redirects in Clients

Some jax-rs clients (RestEasy, Apache CXF) do not support redirects. (Jersey supports it). We should make sure that span context is copied to redirected requests.

Change log level in client registration

e.g.

2018-05-03 20:35:50,651 INFO  [io.opentracing.contrib.jaxrs2.client.ClientTracingFeature] (default task-33) Registering client OpenTracing, with configuration:io.opentracing.contrib.jaxrs2.client.ClientTracingFeature$Builder@6df7e45f

shouldn't be at info level

Adding traceId/spanId to accesslogs and applogs

I've been following the various opentracing/jaeger/zipkin java client repos looking for some guidance on the cleanest way to get traceId/spanId into the logs. There has been some discussion in various places on this topic but nothing definitive and no code anywhere (unless I look in the brave implementation)

At present we are running our application inside a tomcat container, deployed as a war.

I've got basic span/trace forwarding working however I'd also like to enrich both our access logs and application logs so that these can also be used for diagnosis.

For application logs we are using logback and so my assumption is the cleanest way to manage this would be to write the relevant information into MDC and use logback native patterns to include the relevant fields.

For tomcat access logs, I would assume I would need to update the values into either the request or response context and use AccessLogValve patterns to pick this up.

However, I'm unsure of the best place to populate these. Should I write this functionality as an additional filter, or extend one of the existing classes? Is there any prior art I have missed that would make this easier?

Update OpenTracing API to 0.31.0

The current master depends on MP-OpenTracing which uses OT 0.30.0. MP does not use any OT directly it just exposes tracer bean to the application.

Do we want to bump TO version even though MP will depend on the old version?

Not nesting spans

I'm running a Dropwizard app which uses Jersey for JAXRS. I have setup the following in the configuration of the service:

        Tracer tracer = TracerResolver.resolveTracer();
        DynamicFeature tracing = new ServerTracingDynamicFeature.Builder(tracer)
                    .build();

However, whenever a call is made I see two traces: 1) is for the JAXRS request, and 2) is from the nested code's tracing. I expected to see the nested code's span within the JAXRS req span. Is there some other configuration that needs to be applied?

Decorate SpanBuilders and Spans instead of only Spans

Hi,

We have a customer opentracing implementation that emits events when SpanBuilder.start is called and when Span.finish is called.

For that reason, it would be convenient if the decorators decorated the SpanBuilder when handling a request, and the Span when handling a response. The request filters would also be changed to decorate the builder before starting the span.

I don't think that this would change the existing behaviour... would a PR that made this switch be acceptable?

Thanks.

Integrate with microprofile.io

MicroProfile has a spec for distributed tracing using OpenTracing API https://github.com/eclipse/microprofile-opentracing. From the features perspective, it's very close to this implementation.

For me it makes sense to integrate with microprofile.io. Then this instrumentation could be used as a component in application servers to implement microprofile-opentracing support.

Additionally, application servers would have to:

  • change default ClientBuilder to one with registered tracing and OpenTracing-aware executor service (for async API to wire the correct parent)
  • register servlet filter and jax-rs server filters

What will have to change in this instrumentation:

  • use @Traced annotation from MP (possibly other annotations and constants)
  • use servlet filter to finish the span and log exceptions (span will be started in jax-rs filter due to @Traced(false))

cc @objectiser @pilhuhn @kenfinnigan

Flaky test Apache CXF testMultipleServerRequests

CI: https://travis-ci.org/opentracing-contrib/java-jaxrs/builds/524893506

testMultipleServerRequests(io.opentracing.contrib.jaxrs2.itest.cxf.ApacheCXFITest)  Time elapsed: 0.352 sec  <<< FAILURE!
java.lang.AssertionError: expected:<100> but was:<99>
	at org.junit.Assert.fail(Assert.java:88)
	at org.junit.Assert.failNotEquals(Assert.java:834)
	at org.junit.Assert.assertEquals(Assert.java:645)
	at org.junit.Assert.assertEquals(Assert.java:631)
	at 


Results :
Failed tests:   testMultipleServerRequests(io.opentracing.contrib.jaxrs2.itest.cxf.ApacheCXFITest): expected:<100> but was:<99>
Tests run: 42, Failures: 1, Errors: 0, Skipped: 0

Provide configuration via web.xml

#96 started a discussion whether we should provide a configuration via web.xml. If we go that route I would except all options would be available via web.xml. Note that servlet attributes are not available in jax-rs features - maybe it can be injected as @Context private ServletContext context;

No Trace when @Path concatenation between class and methods in a particular case

Hi,

A project that I instrument has @path annotation on a class and its methods, but one of this methods have an empty path. like this:

@Path(value = "foo/bar")
public class myClass {

    @Path(value = "")
    public void myMethod()

Which gives me as a result no span creation

but with something like this:

@Path(value = "foo")
public class myClass {

    @Path(value = "bar")
    public void myMethod()

All is working well !

Any idea to fix that ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.