How it works: Java and OpenTelemetry

6.3 Applies to 6.3.

Understand instrumentation and configuration options for integrating OpenTelemetry Java™ in CICS®. This topic outlines the benefits of using OpenTelemetry Java, explains the differences between automatic and manual approaches, and provides guidance on trace context propagation across Liberty and OSGi JVM servers to support distributed tracing and observability.

OpenTelemetry Java is a language-specific implementation of the OpenTelemetry (OTel) standard. It enables end-to-end distributed tracing and observability across both CICS transactions and Java applications, allowing Java applications to produce telemetry data by using:
  • An application programming interface (API), which records telemetry data.
  • A software development kit (SDK), which implements the API and manages how data is recorded.
  • Tools, which enable Java applications to generate and collect telemetry data.

Why use OpenTelemetry Java in CICS ?

Integrating OpenTelemetry Java with CICS offers several benefits:
  • Better visibility into Java application performance and its impact on overall transaction processing.
  • Easier diagnosis of performance bottlenecks and service dependencies.
  • Increased reliability in complex, mixed-language CICS environments.

Key concepts: instrumentation and configuration

Java applications running in either a CICS Liberty JVM server or an OSGi JVM server can be instrumented to generate telemetry data providing the hosting CICS region is configured for OpenTelemetry tracing.

The terms instrumentation and configuration refer to two distinct but complementary aspects of observability setup for OpenTelemetry Java. Instrumentation is about enabling your application to generate telemetry data such as traces, metrics, and logs. Configuration is about controlling how the telemetry data is collected, processed, and exported. Instrumentation and configuration can be done manually or automatically.

Instrumentation options

In OpenTelemetry Java, the difference between automatic instrumentation and manual instrumentation lies in how telemetry data (like traces and metrics) is added to your application.

Automatic instrumentation
Uses the OpenTelemetry Java Agent.
Does not require code changes.
Supports commonly-used libraries, such as SpringBoot, JDBC, and gRPC.
Is useful for quick setup and consistent instrumentation across services.
Manual instrumentation
Requires adding OpenTelemetry API calls in your code.
Offers fine-grained control over what and how data is captured.
Is useful for custom logic or unsupported libraries.

Configuration options

The difference between automatic configuration and manual (programmatic) configuration is in how and where you define the settings that control telemetry behavior.

Automatic configuration
Uses environment variables, system properties, or configuration files.
Does not require code changes.
Is implicitly used when using the OpenTelemetry Java Agent for automatic instrumentation.
Programmatic configuration
Requires adding OpenTelemetry SDK calls into Java code.
Allows dynamic logic and custom exporters.
Provides more flexibility, but requires more effort and maintenance.

Choosing the right strategy

By combining these options, you can tailor your observability strategy to suit your operational needs. The following table highlights some use cases and associated approaches.
Table 1. Choosing the right approach
Approach Use Case
Automatic instrumentation with automatic configuration The SDK is automatically configured from system properties, and instrumentation is automatically generated by the Java agent. This approach enables quick observability by using the OpenTelemetry Java agent and environment-based configuration. Useful for a standard CICS Java service where quick setup and minimal code changes are required.
Manual instrumentation with automatic configuration The SDK is automatically configured from system properties, and instrumentation is coded in applications. Manual instrumentation provides precise control over trace data and enables the inclusion of custom business attributes, supporting compliance, auditing, and performance monitoring by enabling tracing of only critical operations with enriched context and secure telemetry routing.
Manual instrumentation with programmatic configuration The SDK is configured in code and instrumentation is coded in applications. Offers precise control over what telemetry data is collected and how it is exported. Only required for complex use cases.

Instrumentation methods in OpenTelemetry Java in CICS

The OpenTelemetry Java instrumentation ecosystem includes several categories, each suited to different needs and scenarios.

Java Agent
The Java Agent provides zero-code automatic instrumentation by dynamically injecting bytecode that calls the APIs to record OTel data at the edges of the application. This means you can start generating OTel data with minimal configuration and no changes to your existing codebase.
The Java Agent can be attached to either a Liberty or an OSGi JVM server. In a Liberty JVM server, the spans from the Java agent are created as sibling spans to the CICS spans. In an OSGi JVM server or a Link to Liberty scenario, spans that are created automatically by the Java Agent do not use the CICS transaction span as their parent, which might affect how traces are correlated. For more information, see OpenTelemetry Java Agent.
The Java Agent is a good option for Liberty JVM servers as it is feature-rich and supports inbound and outbound HTTP communication, JDBC, and JMS. A full list is available in the Supported libraries, frameworks, application servers, and JVMs documentation. The Java Agent is also useful when working with legacy applications or in scenarios where accessing or modifying the application source code is not a viable option.
CICS provides the OpenTelemetry Java Agent library in the USSHOME directory.
MicroProfile Telemetry
MicroProfile Telemetry is provided in Liberty as a feature. It is not supported in an OSGi JVM server. MicroProfile Telemetry is not as feature-rich as the Java Agent, and focuses on inbound and outbound HTTP communication for Jakarta RESTful Web Services, and inbound HTTP communication for Servlets.
In enterprise Java applications running on JVM servers, MicroProfile Telemetry can be used to generate OTel data. MicroProfile Telemetry instrumentation is useful if your environment already uses MicroProfile standards and you want to integrate OTel within that ecosystem. However, it is important to note that spans created automatically by MicroProfile Telemetry are sibling spans, and do not use the CICS transaction span as their parent, which might affect how traces are correlated. MicroProfile Telemetry is provided by the JVM server. For more information, see MicroProfile Telemetry.
Manual instrumentation

Application authors have the option to write custom code by using the APIs to record OTel data. This manual approach allows for more control over what OTel data is captured and how it is processed, making it suitable for complex or specialized monitoring requirements where automatic instrumentation might not provide enough detail.

The SDK implements this API and can be configured to process and export the collected OTel data. For more information, see Record Telemetry with API.

Architecture of OpenTelemetry Java in CICS

OpenTelemetry Java in CICS works by propagating trace context from CICS transactions into Java threads. This ensures that spans created by Java applications are properly linked to the originating CICS transaction, enabling full trace visibility.
  1. The CICS transaction starts and creates a span.
  2. The span context is passed into the Java thread.
  3. The instrumented Java code generates telemetry data.
  4. The OpenTelemetry SDK collects and exports the data directly to an observability backend (for example Jaeger, or Zipkin) or via an OpenTelemetry Collector.

The following diagram shows the architecture of OpenTelemetry Java in CICS.

Figure 1. Architecture of OTel Java in CICS
This diagram shows the architecture of how spans are emitted from Java directly to a backend system or via a collector.

Trace context propagation in Liberty JVM servers

In Liberty JVM servers, when an HTTP request is received, CICS checks for W3C Trace Context headers. If present, these headers are used to create a CICS transaction and a corresponding span. This span context is passed into the Java thread handling the request, becoming the active span. Any telemetry generated by Java code using OpenTelemetry is automatically linked as a child of the CICS span, preserving trace continuity. OpenTelemetry-enabled third-party libraries also inherit this context, allowing them to contribute to the same trace.

The following diagram shows the flow of an inbound HTTP request to a CICS Liberty JVM Server.

Figure 2. Flow of an inbound HTTP request to a CICS Liberty JVM Server
This diagram shows the flow when an HTTP request is received by a CICS Liberty JVM server.

CICS Liberty OTel functionality is illustrated in Figure 2, where an HTTP request is received by the Liberty JVM server. The HTTP headers are inspected for W3C trace-context headers, which contain the span context from the originating Java client. This span context is used to build a new CICS transaction, and a CICS span is created to represent this transaction. When the Java code runs, the CICS span context is set as the current Java span, enabling the propagation of trace context between native CICS and Java. Any additional spans that are created by the Java code using the OTel SDK are added as child spans to the original CICS transaction span.

Trace context propagation in Link to Liberty and OSGI JVM servers

For Link to Liberty and OSGi JVM servers, when a CICS program invokes Java, the active CICS span is passed into the new Java thread. This ensures that any telemetry generated in Java is associated with the original CICS transaction. If the Java code makes outbound HTTP calls, it creates client spans that include trace-context headers, enabling downstream services to continue the trace. Although these Java spans are not propagated back into CICS, the trace remains intact across the full transaction path.

Figure 3. OpenTelemetry context propagation flow for Link to Liberty
CICS program with an existing span links to an Enterprise Java program running in a Liberty JVM server.

In Figure 3, a CICS program with an existing span links to an Enterprise Java program running in a Liberty JVM server. The existing CICS span context is set as the current Java span for the thread executing the user code, maintaining trace continuity between native CICS and Java execution. In the scenario depicted in Figure 3, the Java code then makes an HTTP request to an external web service, creating a new client span to represent this outbound call.

In the context of OTel, a client span is a type of span that represents a request or call made by a client (in this case, the Java code running in the Liberty JVM server) to an external service or resource, such as a web service, database, or messaging system. The client span captures the timing and details of the outbound request, including the request method, URL, headers, and any relevant context.

In the scenario depicted in the diagram, the client span is created by the Java code when it makes an HTTP request to the external web service. This client span represents the duration and details of that specific request, and its context is propagated using W3C trace-context headers on the outbound request, allowing the external web service to continue the distributed trace.

The Liberty JVM server (or OSGi JVM server) ensures that the span context is propagated using W3C trace-context headers on the outbound request, enabling the external service to continue the distributed trace. Additional spans that are created by the Java code are not propagated back into CICS, but the overall flow maintains tracing from the original CICS transaction through the Java environment and out to the external web service.

What to do next

Check that the hosting CICS region is configured for OpenTelemetry tracing. For more information, see Configuring OpenTelemetry tracing in CICS

To begin using OpenTelemetry Java in your CICS environment, instrument your Java applications to generate telemetry data. For more information, see Automatically instrumenting Java applications with the OpenTelemetry Java agent and Manually instrumenting Java applications with OpenTelemetry.

You can then configure the OpenTelemetry Java SDK to process and export telemetry data. For more information, see Automatically configuring the OpenTelemetry Java SDK in a JVM server.