OpenTelemetry Tracing: Visualize JGroups communication (#39659)

Closes #39658

Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
Alexander Schwartz 2025-07-22 11:51:58 +02:00 committed by GitHub
parent 98612bbb67
commit 7fd3380b19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 503 additions and 7 deletions

View File

@ -63,6 +63,13 @@ In order to maintain backwards compatibility, {project_name}'s upgrade will modi
For more information about client configuration, please see link:{adminguide_link}#_client-saml-configuration[Creating a SAML client] chapter in the {adminguide_name}.
=== Tracing extended for embedded Infinispan caches
When tracing is enabled, now also calls to other nodes of a {project_name} cluster will create spans in the traces.
To disable this kind of tracing, set the option `tracing-infinispan-enabled` to `false`.
// ------------------------ Deprecated features ------------------------ //
== Deprecated features

View File

@ -0,0 +1,34 @@
package org.keycloak.infinispan.module.factory;
import io.opentelemetry.api.OpenTelemetry;
import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.spi.CDI;
import org.infinispan.factories.AbstractComponentFactory;
import org.infinispan.factories.AutoInstantiableFactory;
import org.infinispan.factories.annotations.DefaultFactoryFor;
import org.infinispan.factories.scopes.Scope;
import org.infinispan.factories.scopes.Scopes;
import org.infinispan.telemetry.InfinispanTelemetry;
import org.infinispan.telemetry.impl.DisabledInfinispanTelemetry;
@Scope(Scopes.GLOBAL)
@DefaultFactoryFor(classes = InfinispanTelemetry.class)
public class InfinispanTelemetryFactory extends AbstractComponentFactory implements AutoInstantiableFactory {
@Override
public Object construct(String componentName) {
CDI<Object> current;
try {
current = CDI.current();
} catch (IllegalStateException e) {
// No CDI context, assume tracing is not available
return new DisabledInfinispanTelemetry();
}
Instance<OpenTelemetry> selector = current.select(OpenTelemetry.class);
if (!selector.isResolvable()) {
return new DisabledInfinispanTelemetry();
} else {
return new OpenTelemetryService(selector.get());
}
}
}

View File

@ -0,0 +1,74 @@
package org.keycloak.infinispan.module.factory;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapGetter;
import org.infinispan.telemetry.InfinispanSpan;
import org.infinispan.telemetry.InfinispanSpanAttributes;
import org.infinispan.telemetry.InfinispanSpanContext;
import org.infinispan.telemetry.InfinispanTelemetry;
public class OpenTelemetryService implements InfinispanTelemetry, TextMapGetter<InfinispanSpanContext> {
private static final String INFINISPAN_SERVER_TRACING_NAME = "org.infinispan.server.tracing";
private static final String INFINISPAN_SERVER_TRACING_VERSION = "1.0.0";
private final Tracer tracer;
private volatile String nodeName = "n/a";
public OpenTelemetryService(OpenTelemetry openTelemetry) {
this.tracer = openTelemetry.getTracer(INFINISPAN_SERVER_TRACING_NAME, INFINISPAN_SERVER_TRACING_VERSION);
}
@Override
public <T> InfinispanSpan<T> startTraceRequest(String operationName, InfinispanSpanAttributes attributes) {
// The original Infininspan implementation allows for filtering via the trace attributes. We don't support this here and instead trace everything.
var builder = tracer.spanBuilder(operationName)
.setSpanKind(SpanKind.SERVER);
// the parent context is inherited automatically,
// because the parent span is created in the same process
return createOpenTelemetrySpan(builder, attributes);
}
@Override
public <T> InfinispanSpan<T> startTraceRequest(String operationName, InfinispanSpanAttributes attributes, InfinispanSpanContext context) {
// The original Infinispan implementation allows for filtering via the trace attributes. We don't support this here and instead trace everything
var builder = tracer.spanBuilder(operationName)
.setSpanKind(SpanKind.SERVER)
.setParent(Context.current().with(Span.current()));
return createOpenTelemetrySpan(builder, attributes);
}
@Override
public void setNodeName(String nodeName) {
if (nodeName != null) {
this.nodeName = nodeName;
}
}
private <T> InfinispanSpan<T> createOpenTelemetrySpan(SpanBuilder builder, InfinispanSpanAttributes attributes) {
attributes.cacheName().ifPresent(cacheName -> builder.setAttribute("cache", cacheName));
builder.setAttribute("category", attributes.category().toString());
builder.setAttribute("server.address", nodeName);
return new OpenTelemetrySpan<>(builder.startSpan());
}
@Override
public Iterable<String> keys(InfinispanSpanContext ctx) {
return ctx.keys();
}
@Override
public String get(InfinispanSpanContext ctx, String key) {
assert ctx != null;
return ctx.getKey(key);
}
}

View File

@ -0,0 +1,42 @@
package org.keycloak.infinispan.module.factory;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.context.Scope;
import org.infinispan.telemetry.InfinispanSpan;
import org.infinispan.telemetry.SafeAutoClosable;
import java.util.Objects;
public class OpenTelemetrySpan<T> implements InfinispanSpan<T> {
private final Span span;
private final Scope scope;
public OpenTelemetrySpan(Span span) {
this.span = Objects.requireNonNull(span);
// TODO: This is actually wrong if you are doing asynchronous calls, but it allows the JGroups calls to be nested
// This should be fixed in ISPN 16+ so that it is no longer needed
// https://github.com/infinispan/infinispan/issues/15287
this.scope = span.makeCurrent();
}
@Override
public SafeAutoClosable makeCurrent() {
//noinspection resource
Scope scope = span.makeCurrent();
return scope::close;
}
@Override
public void complete() {
scope.close();
span.end();
}
@Override
public void recordException(Throwable throwable) {
span.setStatus(StatusCode.ERROR, "Error during the cache request processing");
span.recordException(throwable);
}
}

View File

@ -0,0 +1,98 @@
/*
* Copyright 2025 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.jgroups.header;
import org.jgroups.Header;
import org.jgroups.util.Util;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
/**
* Header which carries an OpenTelemetry {@link io.opentelemetry.api.trace.Span} between requests and responses
*
* @author Bela Ban
* @since 1.0.0
*/
public class TracerHeader extends Header {
public static final short ID = 1050;
protected final Map<String, String> ctx = new HashMap<>();
public TracerHeader() {
}
public short getMagicId() {
return ID;
}
public Supplier<? extends Header> create() {
return TracerHeader::new;
}
public void put(String key, String value) {
ctx.put(key, value);
}
public String get(String key) {
return ctx.get(key);
}
public Set<String> keys() {
return ctx.keySet();
}
public int serializedSize() {
int size = Integer.BYTES;
int num_attrs = ctx.size();
if (num_attrs > 0) {
for (Map.Entry<String, String> entry : ctx.entrySet()) {
String key = entry.getKey();
String val = entry.getValue();
size += Util.size(key) + Util.size(val);
}
}
return size;
}
public void writeTo(DataOutput out) throws IOException {
out.writeInt(ctx.size());
if (!ctx.isEmpty()) {
for (Map.Entry<String, String> e : ctx.entrySet()) {
Util.writeString(e.getKey(), out);
Util.writeString(e.getValue(), out);
}
}
}
public void readFrom(DataInput in) throws IOException {
int size = in.readInt();
if (size > 0) {
for (int i = 0; i < size; i++)
ctx.put(Util.readString(in), Util.readString(in));
}
}
public String toString() {
return ctx.toString();
}
}

View File

@ -0,0 +1,194 @@
/*
* Copyright 2025 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.jgroups.protocol;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.context.propagation.TextMapGetter;
import org.jgroups.Message;
import org.jgroups.Version;
import org.jgroups.annotations.MBean;
import org.jgroups.annotations.Property;
import org.jgroups.stack.Protocol;
import org.jgroups.util.MessageBatch;
import org.keycloak.jgroups.header.TracerHeader;
import java.util.ArrayList;
import java.util.List;
/**
* Provides Open Telemetry (https://opentelemetry.io/) tracing for JGroups. It should be placed just above the
* transport.<br/>
* When a message is sent, a {@link TracerHeader} is added with the (optional) parent span.
* When received a new span is started (as a child span, if the parent span in the header is non-null), and ended when
* the the thread returns.
*
* @author Bela Ban
* @since 1.0.0
*/
@MBean(description = "Records OpenTelemetry traces of sent and received messages")
public class OPEN_TELEMETRY extends Protocol {
public static final short OPEN_TELEMETRY_ID = 1026;
protected OpenTelemetry otel;
protected Tracer tracer;
@Property(description = "When active, traces are recorded, otherwise not")
protected boolean active = true;
public boolean active() {
return active;
}
public OPEN_TELEMETRY active(boolean f) {
active = activate(f);
return this;
}
public void start() throws Exception {
super.start();
activate(active);
}
public Object down(Message msg) {
if (!active || !Span.current().getSpanContext().isValid())
return down_prot.down(msg);
SpanBuilder spanBuilder = tracer.spanBuilder("JGroups.sendSingleMessage");
if (Span.current().isRecording()) {
if (msg.getDest() != null) {
spanBuilder.setAttribute("kc.jgroups.dest", msg.getDest().toString());
}
if (msg.getSrc() != null) {
spanBuilder.setAttribute("kc.jgroups.src", msg.getSrc().toString());
}
}
Span span = spanBuilder.startSpan();
try (var ignored = span.makeCurrent()) {
TracerHeader hdr = new TracerHeader();
populateHeader(hdr); // will populate if a span exists (created by the caller)
msg.putHeader(OPEN_TELEMETRY_ID, hdr);
return down_prot.down(msg);
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, String.format("failed delivering single message to %s", msg.dest()));
span.recordException(t);
throw t;
} finally {
span.end();
}
}
public Object up(Message msg) {
if (!active)
return up_prot.up(msg);
TracerHeader hdr = msg.getHeader(OPEN_TELEMETRY_ID);
if (hdr != null) {
Context extractedContext = otel.getPropagators().getTextMapPropagator()
.extract(Context.current(), hdr, TEXT_MAP_GETTER);
Span span = tracer.spanBuilder("JGroups.deliverSingleMessage")
.setSpanKind(SpanKind.SERVER)
.setParent(extractedContext).startSpan();
try (Scope ignored = span.makeCurrent()) {
span.setAttribute("from", msg.src().toString());
return up_prot.up(msg);
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, String.format("failed delivering single message from %s", msg.src()));
span.recordException(t);
throw t;
} finally {
span.end();
}
} else {
return up_prot.up(msg);
}
}
public void up(MessageBatch batch) {
if (!active) {
if (!batch.isEmpty())
up_prot.up(batch);
return;
}
List<Span> spans = new ArrayList<>(batch.size());
int index = 0, batch_size = batch.size();
for (Message msg : batch) {
index++;
TracerHeader hdr = msg.getHeader(OPEN_TELEMETRY_ID);
if (hdr != null) {
Context extractedContext = otel.getPropagators().getTextMapPropagator()
.extract(Context.current(), hdr, TEXT_MAP_GETTER);
Span span = tracer.spanBuilder("deliver-batched-msg")
.setSpanKind(SpanKind.SERVER)
.setParent(extractedContext).startSpan();
span.setAttribute("batch-msg", String.format("%d/%d", index, batch_size));
spans.add(span);
}
}
try {
if (!batch.isEmpty())
up_prot.up(batch);
} catch (Throwable t) {
spans.forEach(s -> {
s.setStatus(StatusCode.ERROR, String.format("failed delivering batched message from %s", batch.sender()))
.recordException(t);
});
throw t;
} finally {
spans.forEach(Span::end);
}
}
protected static void populateHeader(TracerHeader hdr) {
// Inject the request with the *current* Context, which contains our current Span.
W3CTraceContextPropagator.getInstance().inject(Context.current(), hdr, (carrier, key, val) -> hdr.put(key, val));
}
protected static final TextMapGetter<TracerHeader> TEXT_MAP_GETTER =
new TextMapGetter<>() {
@Override
public String get(TracerHeader carrier, String key) {
return carrier.get(key);
}
@Override
public Iterable<String> keys(TracerHeader carrier) {
return carrier.keys();
}
};
protected boolean activate(boolean flag) {
if (flag && otel == null)
otel = GlobalOpenTelemetry.get();
if (flag && tracer == null)
tracer = otel.getTracer("org.jgroups.trace", Version.printVersion());
return flag;
}
}

View File

@ -74,6 +74,7 @@ public class DefaultCacheEmbeddedConfigProviderFactory implements CacheEmbeddedC
// Configuration
public static final String CONFIG = "configFile";
private static final String METRICS = "metricsEnabled";
public static final String TRACING = "tracingEnabled";
private static final String HISTOGRAMS = "metricsHistogramsEnabled";
public static final String STACK = "stack";
public static final String NODE_NAME = "nodeName";

View File

@ -60,6 +60,8 @@ import org.keycloak.connections.jpa.JpaConnectionProviderFactory;
import org.keycloak.connections.jpa.util.JpaUtils;
import org.keycloak.infinispan.util.InfinispanUtils;
import org.keycloak.jgroups.protocol.KEYCLOAK_JDBC_PING2;
import org.keycloak.jgroups.protocol.OPEN_TELEMETRY;
import org.keycloak.jgroups.header.TracerHeader;
import org.keycloak.models.KeycloakSession;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
@ -82,6 +84,8 @@ public final class JGroupsConfigurator {
// Use custom Keycloak JDBC_PING implementation that workarounds issue https://issues.redhat.com/browse/JGRP-2870
// The id 1025 follows this instruction: https://github.com/belaban/JGroups/blob/38219e9ec1c629fa2f7929e3b53d1417d8e60b61/conf/jg-protocol-ids.xml#L85
ClassConfigurator.addProtocol((short) 1025, KEYCLOAK_JDBC_PING2.class);
ClassConfigurator.addProtocol((short) 1026, OPEN_TELEMETRY.class);
ClassConfigurator.add(TracerHeader.ID, TracerHeader.class);
}
/**
@ -97,7 +101,8 @@ public final class JGroupsConfigurator {
transportOf(holder).stack(stack);
}
configureTransport(config);
configureDiscovery(holder, session);
boolean tracingEnabled = config.getBoolean(DefaultCacheEmbeddedConfigProviderFactory.TRACING, false);
configureDiscovery(holder, session, tracingEnabled);
configureTls(holder, session);
warnDeprecatedStack(holder);
}
@ -177,7 +182,7 @@ public final class JGroupsConfigurator {
return socketFactory;
}
private static void configureDiscovery(ConfigurationBuilderHolder holder, KeycloakSession session) {
private static void configureDiscovery(ConfigurationBuilderHolder holder, KeycloakSession session, boolean tracingEnabled) {
var stackXmlAttribute = transportStackOf(holder);
if (stackXmlAttribute.isModified() && !isJdbcPingStack(stackXmlAttribute.get())) {
logger.debugf("Custom stack configured (%s). JDBC_PING discovery disabled.", stackXmlAttribute.get());
@ -194,7 +199,7 @@ public final class JGroupsConfigurator {
var stackName = transportStackOf(holder).get();
var isUdp = stackName.endsWith("udp");
var tableName = JpaUtils.getTableNameForNativeQuery("JGROUPS_PING", em);
var stack = getProtocolConfigurations(tableName, isUdp);
var stack = getProtocolConfigurations(tableName, isUdp, tracingEnabled);
var connectionFactory = (JpaConnectionProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(JpaConnectionProvider.class);
holder.addJGroupsStack(new JpaFactoryAwareJGroupsChannelConfigurator(stackName, stack, connectionFactory, isUdp), null);
@ -202,7 +207,7 @@ public final class JGroupsConfigurator {
JGroupsConfigurator.logger.info("JGroups JDBC_PING discovery enabled.");
}
private static List<ProtocolConfiguration> getProtocolConfigurations(String tableName, boolean udp) {
private static List<ProtocolConfiguration> getProtocolConfigurations(String tableName, boolean udp, boolean tracingEnabled) {
var list = new ArrayList<ProtocolConfiguration>(udp ? 1 : 2);
list.add(new ProtocolConfiguration(KEYCLOAK_JDBC_PING2.class.getName(),
Map.of(
@ -224,6 +229,12 @@ public final class JGroupsConfigurator {
if (!udp && InfinispanUtils.isVirtualThreadsEnabled())
list.add(new ProtocolConfiguration(TCP.class.getSimpleName(), Map.of("bundler_type", "per-destination")));
if (tracingEnabled) {
list.add(new ProtocolConfiguration(OPEN_TELEMETRY.class.getName(), Map.of(
"stack.combine", "INSERT_ABOVE",
"stack.position", udp ? "UDP" : "TCP"
)));
}
return list;
}

View File

@ -85,4 +85,11 @@ public class TracingOptions {
.description("OpenTelemetry compression method used to compress payloads. If unset, compression is disabled.")
.defaultValue(TracingCompression.none)
.build();
public static final Option<Boolean> TRACING_INFINISPAN_ENABLED = new OptionBuilder<>("tracing-infinispan-enabled", Boolean.class)
.category(OptionCategory.TRACING)
.description("Enables the OpenTelemetry tracing for embedded Infinispan.")
.defaultValue(true)
.build();
}

View File

@ -185,7 +185,7 @@ final class CachingPropertyMappers {
return getOptionalKcValue(CachingOptions.CACHE_REMOTE_HOST_PROPERTY).isPresent();
}
private static boolean cacheSetToInfinispan() {
public static boolean cacheSetToInfinispan() {
if (InfinispanUtils.isRemoteInfinispan()) {
return false;
}

View File

@ -18,6 +18,7 @@
package org.keycloak.quarkus.runtime.configuration.mappers;
import org.keycloak.common.Profile;
import org.keycloak.config.TracingOptions;
import org.keycloak.quarkus.runtime.cli.PropertyException;
import org.keycloak.quarkus.runtime.configuration.Configuration;
import org.keycloak.utils.StringUtil;
@ -29,6 +30,7 @@ import java.net.URL;
import static org.keycloak.config.TracingOptions.TRACING_COMPRESSION;
import static org.keycloak.config.TracingOptions.TRACING_ENABLED;
import static org.keycloak.config.TracingOptions.TRACING_ENDPOINT;
import static org.keycloak.config.TracingOptions.TRACING_INFINISPAN_ENABLED;
import static org.keycloak.config.TracingOptions.TRACING_JDBC_ENABLED;
import static org.keycloak.config.TracingOptions.TRACING_PROTOCOL;
import static org.keycloak.config.TracingOptions.TRACING_RESOURCE_ATTRIBUTES;
@ -91,6 +93,11 @@ public class TracingPropertyMappers {
.mapFrom(TRACING_ENABLED)
.isEnabled(TracingPropertyMappers::isTracingEnabled, TRACING_ENABLED_MSG)
.to("quarkus.datasource.jdbc.telemetry")
.build(),
fromOption(TRACING_INFINISPAN_ENABLED)
.mapFrom(TracingOptions.TRACING_ENABLED)
.to("kc.spi-cache-embedded--default--tracing-enabled")
.isEnabled(TracingPropertyMappers::isTracingAndEmbeddedInfinispanEnabled, "tracing and embedded Infinispan is enabled")
.build()
};
}
@ -129,8 +136,8 @@ public class TracingPropertyMappers {
return Configuration.isTrue(TRACING_ENABLED);
}
public static boolean isTracingJdbcEnabled() {
return Configuration.isTrue(TRACING_JDBC_ENABLED);
public static boolean isTracingAndEmbeddedInfinispanEnabled() {
return Configuration.isTrue(TRACING_ENABLED) && CachingPropertyMappers.cacheSetToInfinispan();
}
private static boolean isValidUrl(String url) {

View File

@ -368,6 +368,9 @@ Tracing:
--tracing-endpoint <url>
OpenTelemetry endpoint to connect to. Default: http://localhost:4317.
Available only when Tracing is enabled.
--tracing-infinispan-enabled <true|false>
Enables the OpenTelemetry tracing for embedded Infinispan. Default: true.
Available only when tracing and embedded Infinispan is enabled.
--tracing-jdbc-enabled <true|false>
Enables the OpenTelemetry JDBC tracing. Default: true. Available only when
Tracing is enabled.

View File

@ -368,6 +368,9 @@ Tracing:
--tracing-endpoint <url>
OpenTelemetry endpoint to connect to. Default: http://localhost:4317.
Available only when Tracing is enabled.
--tracing-infinispan-enabled <true|false>
Enables the OpenTelemetry tracing for embedded Infinispan. Default: true.
Available only when tracing and embedded Infinispan is enabled.
--tracing-jdbc-enabled <true|false>
Enables the OpenTelemetry JDBC tracing. Default: true. Available only when
Tracing is enabled.

View File

@ -599,6 +599,9 @@ Tracing:
--tracing-endpoint <url>
OpenTelemetry endpoint to connect to. Default: http://localhost:4317.
Available only when Tracing is enabled.
--tracing-infinispan-enabled <true|false>
Enables the OpenTelemetry tracing for embedded Infinispan. Default: true.
Available only when tracing and embedded Infinispan is enabled.
--tracing-jdbc-enabled <true|false>
Enables the OpenTelemetry JDBC tracing. Default: true. Available only when
Tracing is enabled.

View File

@ -600,6 +600,9 @@ Tracing:
--tracing-endpoint <url>
OpenTelemetry endpoint to connect to. Default: http://localhost:4317.
Available only when Tracing is enabled.
--tracing-infinispan-enabled <true|false>
Enables the OpenTelemetry tracing for embedded Infinispan. Default: true.
Available only when tracing and embedded Infinispan is enabled.
--tracing-jdbc-enabled <true|false>
Enables the OpenTelemetry JDBC tracing. Default: true. Available only when
Tracing is enabled.

View File

@ -531,6 +531,9 @@ Tracing:
--tracing-endpoint <url>
OpenTelemetry endpoint to connect to. Default: http://localhost:4317.
Available only when Tracing is enabled.
--tracing-infinispan-enabled <true|false>
Enables the OpenTelemetry tracing for embedded Infinispan. Default: true.
Available only when tracing and embedded Infinispan is enabled.
--tracing-protocol <protocol>
OpenTelemetry protocol used for the telemetry data. Possible values are: grpc,
http/protobuf. Default: grpc. Available only when Tracing is enabled.

View File

@ -599,6 +599,9 @@ Tracing:
--tracing-endpoint <url>
OpenTelemetry endpoint to connect to. Default: http://localhost:4317.
Available only when Tracing is enabled.
--tracing-infinispan-enabled <true|false>
Enables the OpenTelemetry tracing for embedded Infinispan. Default: true.
Available only when tracing and embedded Infinispan is enabled.
--tracing-jdbc-enabled <true|false>
Enables the OpenTelemetry JDBC tracing. Default: true. Available only when
Tracing is enabled.

View File

@ -597,6 +597,9 @@ Tracing:
--tracing-endpoint <url>
OpenTelemetry endpoint to connect to. Default: http://localhost:4317.
Available only when Tracing is enabled.
--tracing-infinispan-enabled <true|false>
Enables the OpenTelemetry tracing for embedded Infinispan. Default: true.
Available only when tracing and embedded Infinispan is enabled.
--tracing-jdbc-enabled <true|false>
Enables the OpenTelemetry JDBC tracing. Default: true. Available only when
Tracing is enabled.