Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import com.linkedin.d2.discovery.stores.zk.ZKPersistentConnection;
import com.linkedin.d2.discovery.stores.zk.ZooKeeper;
import com.linkedin.d2.jmx.XdsServerMetricsProvider;
import com.linkedin.d2.jmx.XdsClientOtelMetricsProvider;
import com.linkedin.d2.jmx.JmxManager;
import com.linkedin.d2.xds.XdsClientValidator;
import com.linkedin.d2.jmx.NoOpJmxManager;
Expand Down Expand Up @@ -237,6 +238,7 @@ public D2Client build()
_config.xdsChannelLoadBalancingPolicyConfig,
_config.subscribeToUriGlobCollection,
_config._xdsServerMetricsProvider,
_config.xdsClientOtelMetricsProvider,
_config.loadBalanceStreamException,
_config.xdsInitialResourceVersionsEnabled,
_config.disableDetectLiRawD2Client,
Expand Down Expand Up @@ -856,6 +858,11 @@ public D2ClientBuilder setXdsServerMetricsProvider(XdsServerMetricsProvider xdsS
return this;
}

public D2ClientBuilder setXdsClientOtelMetricsProvider(XdsClientOtelMetricsProvider xdsClientOtelMetricsProvider) {
_config.xdsClientOtelMetricsProvider = xdsClientOtelMetricsProvider;
return this;
}

public D2ClientBuilder setLoadBalanceStreamException(boolean loadBalanceStreamException) {
_config.loadBalanceStreamException = loadBalanceStreamException;
return this;
Expand Down
148 changes: 148 additions & 0 deletions d2/src/main/java/com/linkedin/d2/balancer/D2ClientConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import com.linkedin.d2.jmx.JmxManager;
import com.linkedin.d2.jmx.NoOpXdsServerMetricsProvider;
import com.linkedin.d2.jmx.NoOpJmxManager;
import com.linkedin.d2.jmx.XdsClientOtelMetricsProvider;
import com.linkedin.d2.jmx.NoOpXdsClientOtelMetricsProvider;
import com.linkedin.r2.transport.common.TransportClientFactory;
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext;
import java.time.Duration;
Expand Down Expand Up @@ -181,6 +183,12 @@ public class D2ClientConfig

public boolean subscribeToUriGlobCollection = false;
public XdsServerMetricsProvider _xdsServerMetricsProvider = new NoOpXdsServerMetricsProvider();

/**
* Provider for OpenTelemetry metrics collection for XDS client operations.
* Defaults to no-op implementation; can be overridden to enable metric tracking.
*/
public XdsClientOtelMetricsProvider xdsClientOtelMetricsProvider = new NoOpXdsClientOtelMetricsProvider();
public boolean loadBalanceStreamException = false;
public boolean xdsInitialResourceVersionsEnabled = false;
public Integer xdsStreamMaxRetryBackoffSeconds = null;
Expand Down Expand Up @@ -293,6 +301,145 @@ public D2ClientConfig()
D2CalleeInfoRecorder d2CalleeInfoRecorder,
Boolean enableIndisDownstreamServicesFetcher,
Duration indisDownstreamServicesFetchTimeout)
{
this(zkHosts, xdsServer, hostName, zkSessionTimeoutInMs, zkStartupTimeoutInMs, lbWaitTimeout, lbWaitUnit,
flagFile, basePath, fsBasePath, indisFsBasePath, componentFactory, clientFactories, lbWithFacilitiesFactory,
sslContext, grpcSslContext, sslParameters, isSSLEnabled, shutdownAsynchronously, isSymlinkAware,
clientServicesConfig, d2ServicePath, useNewEphemeralStoreWatcher, healthCheckOperations, executorService,
retry, restRetryEnabled, streamRetryEnabled, retryLimit, retryUpdateIntervalMs, retryAggregatedIntervalNum,
warmUp, warmUpTimeoutSeconds, indisWarmUpTimeoutSeconds, warmUpConcurrentRequests,
indisWarmUpConcurrentRequests, downstreamServicesFetcher, indisDownstreamServicesFetcher,
backupRequestsEnabled, backupRequestsStrategyStatsConsumer,
backupRequestsLatencyNotificationInterval,
backupRequestsLatencyNotificationIntervalUnit,
enableBackupRequestsClientAsync,
backupRequestsExecutorService,
emitter,
partitionAccessorRegistry,
zooKeeperDecorator,
enableSaveUriDataOnDisk,
loadBalancerStrategyFactories,
requestTimeoutHandlerEnabled,
sslSessionValidatorFactory,
zkConnection,
startUpExecutorService,
indisStartUpExecutorService,
jmxManager,
d2JmxManagerPrefix,
zookeeperReadWindowMs,
enableRelativeLoadBalancer,
deterministicSubsettingMetadataProvider,
canaryDistributionProvider,
enableClusterFailout,
failoutConfigProviderFactory,
failoutRedirectStrategy,
serviceDiscoveryEventEmitter,
dualReadStateManager,
xdsExecutorService,
xdsStreamReadyTimeout,
dualReadNewLbExecutor,
xdsChannelLoadBalancingPolicy,
xdsChannelLoadBalancingPolicyConfig,
subscribeToUriGlobCollection,
xdsServerMetricsProvider,
new NoOpXdsClientOtelMetricsProvider(),
loadBalanceStreamException,
xdsInitialResourceVersionsEnabled,
disableDetectLiRawD2Client,
isLiRawD2Client,
xdsStreamMaxRetryBackoffSeconds,
xdsChannelKeepAliveTimeMins,
xdsMinimumJavaVersion,
actionOnPrecheckFailure,
d2CalleeInfoRecorder,
enableIndisDownstreamServicesFetcher,
indisDownstreamServicesFetchTimeout);
}

D2ClientConfig(String zkHosts,
String xdsServer,
String hostName,
long zkSessionTimeoutInMs,
long zkStartupTimeoutInMs,
long lbWaitTimeout,
TimeUnit lbWaitUnit,
String flagFile,
String basePath,
String fsBasePath,
String indisFsBasePath,
ComponentFactory componentFactory,
Map<String, TransportClientFactory> clientFactories,
LoadBalancerWithFacilitiesFactory lbWithFacilitiesFactory,
SSLContext sslContext,
SslContext grpcSslContext,
SSLParameters sslParameters,
boolean isSSLEnabled,
boolean shutdownAsynchronously,
boolean isSymlinkAware,
Map<String, Map<String, Object>> clientServicesConfig,
String d2ServicePath,
boolean useNewEphemeralStoreWatcher,
HealthCheckOperations healthCheckOperations,
ScheduledExecutorService executorService,
boolean retry,
boolean restRetryEnabled,
boolean streamRetryEnabled,
int retryLimit,
long retryUpdateIntervalMs,
int retryAggregatedIntervalNum,
boolean warmUp,
int warmUpTimeoutSeconds,
int indisWarmUpTimeoutSeconds,
int warmUpConcurrentRequests,
int indisWarmUpConcurrentRequests,
DownstreamServicesFetcher downstreamServicesFetcher,
DownstreamServicesFetcher indisDownstreamServicesFetcher,
boolean backupRequestsEnabled,
BackupRequestsStrategyStatsConsumer backupRequestsStrategyStatsConsumer,
long backupRequestsLatencyNotificationInterval,
TimeUnit backupRequestsLatencyNotificationIntervalUnit,
boolean enableBackupRequestsClientAsync,
ScheduledExecutorService backupRequestsExecutorService,
EventEmitter emitter,
PartitionAccessorRegistry partitionAccessorRegistry,
Function<ZooKeeper, ZooKeeper> zooKeeperDecorator,
boolean enableSaveUriDataOnDisk,
Map<String, LoadBalancerStrategyFactory<? extends LoadBalancerStrategy>> loadBalancerStrategyFactories,
boolean requestTimeoutHandlerEnabled,
SslSessionValidatorFactory sslSessionValidatorFactory,
ZKPersistentConnection zkConnection,
ScheduledExecutorService startUpExecutorService,
ScheduledExecutorService indisStartUpExecutorService,
JmxManager jmxManager,
String d2JmxManagerPrefix,
int zookeeperReadWindowMs,
boolean enableRelativeLoadBalancer,
DeterministicSubsettingMetadataProvider deterministicSubsettingMetadataProvider,
CanaryDistributionProvider canaryDistributionProvider,
boolean enableClusterFailout,
FailoutConfigProviderFactory failoutConfigProviderFactory,
FailoutRedirectStrategy failoutRedirectStrategy,
ServiceDiscoveryEventEmitter serviceDiscoveryEventEmitter,
DualReadStateManager dualReadStateManager,
ScheduledExecutorService xdsExecutorService,
Long xdsStreamReadyTimeout,
ExecutorService dualReadNewLbExecutor,
String xdsChannelLoadBalancingPolicy,
Map<String, ?> xdsChannelLoadBalancingPolicyConfig,
boolean subscribeToUriGlobCollection,
XdsServerMetricsProvider xdsServerMetricsProvider,
XdsClientOtelMetricsProvider xdsClientOtelMetricsProvider,
boolean loadBalanceStreamException,
boolean xdsInitialResourceVersionsEnabled,
boolean disableDetectLiRawD2Client,
boolean isLiRawD2Client,
Integer xdsStreamMaxRetryBackoffSeconds,
Long xdsChannelKeepAliveTimeMins,
String xdsMinimumJavaVersion,
XdsClientValidator.ActionOnPrecheckFailure actionOnPrecheckFailure,
D2CalleeInfoRecorder d2CalleeInfoRecorder,
Boolean enableIndisDownstreamServicesFetcher,
Duration indisDownstreamServicesFetchTimeout)
{
this.zkHosts = zkHosts;
this.xdsServer = xdsServer;
Expand Down Expand Up @@ -367,6 +514,7 @@ public D2ClientConfig()
this.xdsChannelKeepAliveTimeMins = xdsChannelKeepAliveTimeMins;
this.subscribeToUriGlobCollection = subscribeToUriGlobCollection;
this._xdsServerMetricsProvider = xdsServerMetricsProvider;
this.xdsClientOtelMetricsProvider = xdsClientOtelMetricsProvider;
this.loadBalanceStreamException = loadBalanceStreamException;
this.xdsInitialResourceVersionsEnabled = xdsInitialResourceVersionsEnabled;
this.disableDetectLiRawD2Client = disableDetectLiRawD2Client;
Expand Down
8 changes: 7 additions & 1 deletion d2/src/main/java/com/linkedin/d2/jmx/D2ClientJmxManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,13 @@ public void registerXdsClientJmx(XdsClientJmx xdsClientJmx)
{
_log.warn("Setting XdsClientJmx for Non-XDS source type: {}", _discoverySourceType);
}
final String jmxName = String.format("%s-XdsClientJmx", getGlobalPrefix(null));
// Get the client name from global prefix
String clientName = getGlobalPrefix(null);
if(clientName != null && !clientName.isEmpty())
{
xdsClientJmx.setClientName(clientName);
}
final String jmxName = String.format("%s-XdsClientJmx", clientName);
_jmxManager.registerXdsClientJmxBean(jmxName, xdsClientJmx);
}

Expand Down
34 changes: 34 additions & 0 deletions d2/src/main/java/com/linkedin/d2/jmx/D2JmxConstants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
Copyright (c) 2025 LinkedIn Corp.

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also licensing here


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 com.linkedin.d2.jmx;

/**
* Common constants used across D2 JMX and metrics components.
*/
public final class D2JmxConstants

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be just a common utils file instead of D2JmxContants? The NO_VALUE will be used by possibly multiple sensors, so it should just be something like OpenTelemetryConstants.

{
/**
* Default client name used when a specific client name is not set.
* Used for identifying metrics associated with unnamed clients.
*/
public static final String NO_VALUE = "-";

private D2JmxConstants()
{
// Utility class, prevent instantiation
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.linkedin.d2.jmx;

/**
* No-Op implementation of {@link XdsClientOtelMetricsProvider}.
* Used when OpenTelemetry metrics are disabled.
*/
public class NoOpXdsClientOtelMetricsProvider implements XdsClientOtelMetricsProvider {

/**
* {@inheritDoc}
*/
@Override

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add docstring {@inheritDoc} for all of these methods

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

public void recordConnectionLost(String clientName) {
// No-op
}

/**
* {@inheritDoc}
*/
@Override
public void recordConnectionClosed(String clientName) {
// No-op
}

/**
* {@inheritDoc}
*/
@Override
public void recordReconnection(String clientName) {
// No-op
}

/**
* {@inheritDoc}
*/
@Override
public void recordRequestSent(String clientName) {
// No-op
}

/**
* {@inheritDoc}
*/
@Override
public void recordResponseReceived(String clientName) {
// No-op
}

/**
* {@inheritDoc}
*/
@Override
public void recordInitialResourceVersionSent(String clientName, int count) {
// No-op
}

/**
* {@inheritDoc}
*/
@Override
public void recordResourceNotFound(String clientName) {
// No-op
}

/**
* {@inheritDoc}
*/
@Override
public void recordResourceInvalid(String clientName) {
// No-op
}

/**
* {@inheritDoc}
*/
@Override
public void recordServerLatency(String clientName, long latencyMs) {
// No-op
}

/**
* {@inheritDoc}
*/
@Override
public void updateConnectionState(String clientName, boolean isConnected) {
// No-op
}

/**
* {@inheritDoc}
*/
@Override
public void updateActiveInitialWaitTime(String clientName, long waitTimeMs) {
// No-op
}
}
Loading
Loading