OpenTelemetry Integration

Introduction

Purpose

Integrate OpenTelemetry with Bloomreach Experience Manager (XM) to collect distributed traces from your CMS application and forward them to an observability backend such as Honeycomb, Jaeger, Grafana, or Dynatrace. This integration supports trace data only; metrics and logs export are not included.

OpenTelemetry Overview

OpenTelemetry is an open-source observability framework maintained by the Cloud Native Computing Foundation (CNCF). It standardizes the collection and export of telemetry data—traces, metrics, and logs—from applications.

Bloomreach Experience Manager supports OpenTelemetry through the Java auto-instrumentation agent. The agent attaches to the JVM at startup and automatically generates trace spans for servlets, JDBC calls, JAX-RS endpoints, and HTTP clients without requiring code changes.

In addition to auto-instrumentation, Bloomreach Experience Manager enriches traces with CMS-specific context. This includes the Wicket UI action that initiated the request, the logged-in CMS user, and, for slow requests, a detailed breakdown of the internal diagnostic task tree. This enrichment extends the CMS Diagnostics feature to OpenTelemetry, making the same diagnostic data available in your observability backend.

The agent determines whether tracing is active: attach the agent to enable tracing, or remove it to eliminate overhead. No code changes or configuration flags are required.

Default Configuration

By default, trace data is collected via auto-instrumentation for supported Java libraries and frameworks and includes enrichment specific to Bloomreach Experience Manager.

The default configuration prioritizes low overhead and minimal trace data volume. JDBC instrumentation, metrics, and logs export are disabled by default. These settings are automatically applied by the otel-auto-instrumentation Maven profile for local development. For production deployments, configure these properties manually as described in the Production Deployment section.

SettingDefault
otel.instrumentation.jdbc.enabledfalse
otel.metrics.exporternone
otel.instrumentation.log4j-appender.enabledfalse
otel.resource.disabled.keysprocess.command_args
otel.instrumentation.common.experimental.controller-telemetry.enabledtrue

Trace Content

Traces include three layers of information:

1. OTel Auto-Instrumentation

The Java agent automatically creates spans for servlets, JAX-RS endpoints, HTTP clients, and other supported frameworks. No code changes are necessary; attaching the agent is sufficient.

2. CMS-Specific Enrichment

Each CMS request is enriched with details such as the logged-in CMS user, the project version, and, for Ajax requests, the Wicket UI action that triggered the request. The UI action is recorded as the hdc.brxm_ui_trace span attribute, linking backend traces to specific user interactions.

3. CMS Diagnostics (HDC Task Tree)

The internal CMS diagnostic task tree is exported as child spans when the OTel agent is attached. This export is independent of the CMS Diagnostics console logging feature; you do not need to enable CMS Diagnostics to obtain OTel traces. The thresholdMillisec property (default: 3000 ms) determines which requests include a detailed subtask breakdown.

Running Locally with an Archetype Project

Step 1: Configure the Backend

Create or edit conf/platform-dev.properties in your project root:

otel.service.name=my-project-cms
otel.exporter.otlp.endpoint=https://api.eu1.honeycomb.io
otel.exporter.otlp.headers=x-honeycomb-team=YOUR_API_KEY
otel.resource.attributes=deployment.environment.name=local-dev

Replace my-project-cms with your preferred service name. These four properties are required at minimum.

Refer to your observability backend's documentation for the correct endpoint, headers, and any additional configuration.

Step 2: Run with the OTel Maven Profile

mvn clean verify && mvn -P cargo.run,otel-auto-instrumentation

The otel-auto-instrumentation profile downloads the OTel Java agent JAR, reads properties from conf/platform-dev.properties, passes them as JVM system properties, and attaches the agent using -javaagent:.

You can override properties defined in conf/platform-dev.properties by specifying them with -D on the Maven command line. To add properties not defined in the profile, use cargo.jvm.args:

mvn -P cargo.run,otel-auto-instrumentation -Dcargo.jvm.args="-Dmy.custom.property=value"

For full control over all settings, copy the otel-auto-instrumentation profile from the parent POM into your project's POM and modify it as needed.

Step 3: Verify Agent Attachment

On startup, check cms.log for a message similar to the following:

WARN  OpenTelemetry: Java agent detected. service.name=my-project-cms,
  endpoint=https://api.eu1.honeycomb.io,
  resource.attributes=[service.version=17.0.0,deployment.environment.name=local],
  sampler=parentbased_always_on (default), jdbc=false

If this message does not appear, verify that you included the otel-auto-instrumentation profile in your Maven command.

Step 4: Generate and View Traces

Access the CMS at http://localhost:8080/cms/, perform actions such as browsing, editing, or publishing documents, and then check your observability backend for traces using the configured service name.

Customizing Your Codebase

Using Traceable Wicket Components

When creating custom Wicket components with Ajax interactions, extend the traceable base classes to automatically include UI action names in traces. The action name is recorded as the hdc.brxm_ui_trace span attribute, allowing you to identify which user action triggered a request.

Instead ofUse
AjaxLinkTraceableAjaxLink
AjaxButtonTraceableAjaxButton
AjaxEventBehaviorTraceableAjaxEventBehavior

The default implementation generates an action name based on the component's label, model, or class name. To specify a custom action name, override getActionName():

new TraceableAjaxLink<Void>("myAction") { @Override public void onClick(AjaxRequestTarget target) { // handle click } @Override protected String getActionName() { return "custom:my-special-action"; } };

Adding Custom OTel Spans

Use the standard OpenTelemetry API to add custom spans:

import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Scope; Tracer tracer = GlobalOpenTelemetry.get().getTracer("my-project"); Span span = tracer.spanBuilder("processOrder") .setAttribute("order.id", orderId) .startSpan(); try (Scope scope = span.makeCurrent()) { // your business logic } finally { span.end(); }

Custom spans are nested under the agent's server span and appear in your trace backend alongside auto-instrumented spans. If the agent is not attached, all API calls are no-ops and introduce no overhead.

Production Deployment

Bloomreach Experience Manager's OpenTelemetry integration uses the standard OpenTelemetry Java auto-instrumentation agent. The agent attaches to the JVM at startup and collects trace data with minimal overhead.

The default configuration is conservative to minimize overhead, reduce trace data volume, and avoid noise from internal framework activity.

Before enabling OpenTelemetry in production, first enable it in a non-production environment to verify compatibility and monitor resource usage in your deployment.

To enable OpenTelemetry in production:

  • Attach the OpenTelemetry Java agent JAR to the JVM using -javaagent.

  • Configure OTel properties as JVM system properties or environment variables. The following table lists recommended values based on the default configuration; adjust as needed for your environment.

    PropertyRequiredExample
    otel.service.nameYesbrxm-cms
    otel.exporter.otlp.endpointYeshttps://your-backend:4318
    otel.exporter.otlp.headersBackend-specificAuthorization=Bearer TOKEN
    otel.resource.attributesRecommendeddeployment.environment.name=production
    otel.instrumentation.jdbc.enabledRecommendedfalse
    otel.metrics.exporterRecommendednone
    otel.instrumentation.log4j-appender.enabledRecommendedfalse
    otel.resource.disabled.keysRecommendedprocess.command_args
  • Select a sampling strategy appropriate for your environment. Head-based sampling (configured via otel.traces.sampler) is straightforward to set up. Tail-based sampling (using an OTel Collector) allows sampling decisions based on trace outcomes, such as errors or latency. Refer to the OpenTelemetry documentation for guidance.

Share Feedback
Page: /deploy/on-premise-deployment/opentelemetry-integration
Section: Deploy
Category *