DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • Creating Application using Spring Roo and Deploying on Google App Engine
  • Migrating Spring Java Applications to Azure App Service (Part 1: DataSources and Credentials)
  • Remote Debugging Cloud Foundry Apps
  • Auto Logging in Class and Method Level Using Custom Annotations in Spring Boot App

Trending

  • DZone's Article Submission Guidelines
  • How to Submit a Post to DZone
  • Agile Estimation: Techniques and Tips for Success
  • REST vs. Message Brokers: Choosing the Right Communication
  1. DZone
  2. Coding
  3. Frameworks
  4. OpenTracing JAX-RS Instrumentation

OpenTracing JAX-RS Instrumentation

Implementing RESTful Web Services into your Java application is really just a matter of adding a dependency and registering a tracer instance. Sounds easy enough, right?

Pavol Loffay user avatar by
Pavol Loffay
·
Jul. 10, 17 · Tutorial
Like (3)
Save
Tweet
Share
7.11K Views

Join the DZone community and get the full member experience.

Join For Free

In the previous demo, we demonstrated how to instrument a Spring Boot app using OpenTracing, a vendor-neutral standard for distributed tracing. In this article, we are going to instrument a Java API for RESTful Web Services (JAX-RS), and show you how to trace the business layer and add custom data to the trace.

Demo Application

Creating a JAX-RS app from scratch can be a time-consuming task, therefore, in this case, we are going to use Wildfly Swarm’s app generator. Select JAX-RS and CDI dependencies and hit the generate button.

Wildfy Swarm app generator.

Figure 1: Wildfly Swarm app generator.

The generated application contains one REST endpoint which returns a 'hello world' string. This endpoint is accessible on http://localhost:8080/hello. In the next step, we are going to instrumentation and simple business logic. 

Instrumentation

Adding OpenTracing instrumentation to JAX-RS is very simple, just include the following dependency in the classpath and the tracing feature will be automatically registered.

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

OpenTracing is just an API, therefore it is required to register a specific tracer instance. In this demo, we are going to use the Jaeger tracing system. The tracer should be created and initialized only once per process, hence ServletContextListener is the ideal place for this task:

@WebListener
public class TracingContextListener implements ServletContextListener {

  @Inject
  private io.opentracing.Tracer tracer;

  @Override
  public void contextInitialized(ServletContextEvent sce) {
    GlobalTracer.register(tracer);
  }

  @Override
  public void contextDestroyed(ServletContextEvent sce) {}

  @Produces
  @Singleton
  public static io.opentracing.Tracer jaegerTracer() {
    return new Configuration("wildfly-swarm", new Configuration.SamplerConfiguration(
        ProbabilisticSampler.TYPE, 1),
        new Configuration.ReporterConfiguration())
        .getTracer();
  }
}

Note that we are using Java’s Context and Dependency Injection (CDI) to share a tracer instance in our app. If we forget to register a specific tracer instance, then the tracing feature would use NoopTracer. Now we can verify tracing by starting the Jaeger server using the following command: docker run --rm -it --network=host jaegertracing/all-in-one  and accessing the endpoint at http://localhost:8080/hello. Our trace with one span should be present in the UI at http://localhost:16686.

Instrumenting Business Logic

JAX-RS instrumentation provides nice visibility into your app, however, it is often necessary to add custom data to the trace to see what is happening in the service or database layer.

The following code snippet shows how the service layer can create and add data to the trace:

public class BackendService {

  @Inject
  private io.opentracing.Tracer tracer;

  public String action() throws InterruptedException {
    int random = new Random().nextInt(200);

    try (ActiveSpan span = tracer.buildSpan("action").startActive()) {
      anotherAction();
      Thread.sleep(random);
    }

    return String.valueOf(random);
  }

  private void anotherAction() {
    tracer.activeSpan().setTag("anotherAction", "data");
  }

Note that it’s not necessary to manually pass a span instance around. The method anotherAction  accesses the current active span from the tracer.

With the additional instrumentation shown above, an invocation of the REST endpoint would result in a trace consisting of two spans, one representing the inbound server request, and the other the business logic. The span representing server processing is automatically considered as the parent for span created in the business layer. If we created span in anotherAction then its parent would be the span created in the action method.

Jaeger showing reported spans.

Figure 2: Jaeger showing reported spans.

Video

Conclusion

We have demonstrated that instrumenting a JAX-RS app is just a matter of adding a dependency and registering a tracer instance. If we would like to use a different OpenTracing implementation, Zipkin for instance, it would just require changing the tracer producer code. No changes to the application or business logic! In the next demo, we will wire this app with the Spring Boot created in the previous demo and deploy them on Kubernetes.

Resources

  • OpenTracing
  • GitHub repository with demo
  • OpenTracing JAX-RS .
  • Jaeger
Instrumentation (computer programming) app Spring Framework

Published at DZone with permission of Pavol Loffay, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Creating Application using Spring Roo and Deploying on Google App Engine
  • Migrating Spring Java Applications to Azure App Service (Part 1: DataSources and Credentials)
  • Remote Debugging Cloud Foundry Apps
  • Auto Logging in Class and Method Level Using Custom Annotations in Spring Boot App

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: