Categories
Jakarta EE Observability

Using OpenTelemetry with Jakarta EE

OpenTelemetry (informally called OTEL or OTel) is a powerful observability framework that assists in generating and capturing telemetry data from the software. With the rise of now-distributed systems, it has become increasingly difficult for developers to see how their services depend on or affect other services, especially in critical situations such as deployments or outages. OpenTelemetry provides a solution to this problem by making it possible for both developers and operators to gain visibility into their systems.

It is the merger of two other standards, OpenTracing provided a vendor-neutral API for sending telemetry data over to an Observability back-end, and OpenCensus provided a set of language-specific libraries that developers could use to instrument their code and send to any one of their supported back-ends.

As a CNCF incubating project, it is providing a set of standardized, vendor-agnostic SDKs, APIs, and tools for ingesting, transforming, and sending data to an Observability back-end. There is an implementation of the API for Java available, so integration with any Jakarta EE runtime is very easy and doesn’t require any additional implementation.

What does it do?

If you are not familiar with Otel or Observability, then this little introduction is for you. Especially in a micro-services world, but also in other scenarios, it can be very helpful to trace back individual requests and where they spent their time on. Not that it is the main goal, it already captures how much time was needed before a response was sent back to the client. But it can also collect information about database calls, calls to other services, etc … You get information about each request and you can use it to analyse your environment and find the bottlenecks for example. As the saying goes β€œTo measure is to know.” (Although that sounds way much better in dutch “meten is weten”).

You can analyse the information as all the different pieces of information are linked together and stored by a collector. A kind of data storage where you can retrieve and analyse the information.

Observability is much more than just tracking a request throughout your environment. It is also about metrics and processing logs. In this blog, I’m concentrating on request tracing.

Out of the box

The Java implementation of OTel provides integration with Jakarta REST out of the box through a Java Agent. You can find all the supported frameworks and libraries on this page. Some of them require a specific dependency, other frameworks, like JAX-RS require only the Java agent itself.

Personally, I’m not a fan of Java agents. It allows of course to add functionality to your project without the need to change anything in your project. But I don’t like fiddling with the command line to add the Java agent and large sections to define the configuration. And in most cases, you will require the OpenTelemetry API in your application anyway as you want to interact with the system and define for example which CDI methods you like to be included in the trace.

Manual integration

But also integrating the OTel functionality in the application yourself is very straightforward. As an example, I created an integration of the OpenTelemetry Java API for Jakarta EE 10 with the following features.

  • Traces the JAX-RS requests that are processed.
  • Starts a new Tracing or starts a new child span if the header indicates that tracing is already in progress.
  • You can include information about CDI method calls by using an annotation on the method.
  • A Filter for JAX-RS clients is available to propagate the OpenTelemetry information on the header
  • Automatically registers this filter when you have a MicroProfile Rest Client available.

And all this with around 10 classes.

What do you need to do?

If you are interested in creating this integration for your project yourself, have a look at the GitHub repository. It should give you all the information needed to create a specific integration yourself very rapidly.

If you want to use my version in your Jakarta EE 10 project, follow the following steps.

  • Add the maven artefact to your project
    <dependency>
    <groupId>be.atbash.jakarta</groupId>
    <artifactId>opentelemetry</artifactId>
    <version>0.9.0</version>
    </dependency>
  • Define the name of your service, and how it shows up in the OpenTelemetry collector, through a MicroProfile Config source with the key atbash.otel.service.name.
  • Configure, if needed to OTel connector connection through environment variables as required by the OpenTelemetry Specification.
  • Use @WithSpan on a CDI method, or register RestClientPropagationFilter on your JAX-RS client if you want to make use of it.

And that is it.

You can access the current Span by injecting it into your CDI bean.

@Inject
private Span currentSpan;

You can add attributes and events to the span using this instance. These attributes end up in your collector and events mark specific moments in the span.

You can also make use of Baggage Items to carry information to other parts of the requests. Although, you should not see this as a replacement for passing parameters to methods and other services that are called. For that reason, the Baggage Items are not propagated externally. However, by adding the W3CBaggagePropagator provided by the Otel Java implementation to the OpenTelemetry instance, this is possible.

To add something to a baggage item.

    Baggage.current()
            .toBuilder()
            .put("baggageItem", name)
            .build()
            .makeCurrent();

And to access it later on

Baggage.current().asMap();

Conclusion

The OpenTelemetry specification goal is to get insight into what your process is doing when processing requests from the users. Besides metrics and logging, an important part is tracing the requests through your entire environment. It is a language-agnostic specification so that information is compatible regardless of what language the processes are programmed in. But there are also implementations available for many languages, including Java.

This means that vendors or framework maintainers don’t need to do anything to get it integrated. And developers can just use the Java implementation if they need the functionality in their environment. There exists a Java Agent but also manual integration can be done very easily as showcased by the Jakarta EE 10 integration code available in the Github repo.

Atbash Training and Support

Do you need a specific training session on Jakarta or MicroProfile? Or do you need some help in getting up and running with your next project? Have a look at the training support that I provide on the page https://www.atbash.be/training/ and contact me for more information.

Enjoy

This website uses cookies. By continuing to use this site, you accept our use of cookies.  Learn more