Skip to content

Commit f122c6f

Browse files
lqiu96blakeli0
andauthored
feat: Allow Adding Client Level Attributes to MetricsTracerFactory (#2614)
Allow the MetricsTracerFactory to take in a second parameter (Map of attributes) that will be treated as client level attributes. These attributes will be added to every single MetricsTracer created throughout the lifecycle of the client. Was able to verify this behavior inside Cloud Monitoring: ![image](https://github.com/googleapis/sdk-platform-java/assets/6621793/832f485e-2834-4765-b381-9a15e2913412) Additional Attribute was recorded. Via: ``` InstantiatingGrpcChannelProvider channelProvider = InstantiatingGrpcChannelProvider.newBuilder().build(); Map<String, String> clientAttributesMapping = new HashMap<>(); clientAttributesMapping.put("directpath_enabled", String.valueOf(channelProvider.canUseDirectPath())); ... options .setApiTracerFactory(new MetricsTracerFactory(recorder, clientAttributesMapping)) .build(); ``` --------- Co-authored-by: Blake Li <[email protected]>
1 parent dc88ea2 commit f122c6f

File tree

6 files changed

+448
-105
lines changed

6 files changed

+448
-105
lines changed

gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java

+59-19
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import com.google.api.core.ApiFunction;
3333
import com.google.api.core.BetaApi;
3434
import com.google.api.core.InternalApi;
35-
import com.google.api.core.InternalExtensionOnly;
3635
import com.google.api.gax.core.ExecutorProvider;
3736
import com.google.api.gax.rpc.FixedHeaderProvider;
3837
import com.google.api.gax.rpc.HeaderProvider;
@@ -82,13 +81,26 @@
8281
* <p>The client lib header and generator header values are used to form a value that goes into the
8382
* http header of requests to the service.
8483
*/
85-
@InternalExtensionOnly
8684
public final class InstantiatingGrpcChannelProvider implements TransportChannelProvider {
85+
86+
static String systemProductName;
87+
88+
static {
89+
try {
90+
systemProductName =
91+
Files.asCharSource(new File("/sys/class/dmi/id/product_name"), StandardCharsets.UTF_8)
92+
.readFirstLine();
93+
} catch (IOException e) {
94+
// If not on Compute Engine, FileNotFoundException will be thrown. Use empty string
95+
// as it won't match with the GCE_PRODUCTION_NAME constants
96+
systemProductName = "";
97+
}
98+
}
99+
87100
@VisibleForTesting
88101
static final Logger LOG = Logger.getLogger(InstantiatingGrpcChannelProvider.class.getName());
89102

90-
private static final String DIRECT_PATH_ENV_DISABLE_DIRECT_PATH =
91-
"GOOGLE_CLOUD_DISABLE_DIRECT_PATH";
103+
static final String DIRECT_PATH_ENV_DISABLE_DIRECT_PATH = "GOOGLE_CLOUD_DISABLE_DIRECT_PATH";
92104
private static final String DIRECT_PATH_ENV_ENABLE_XDS = "GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS";
93105
static final long DIRECT_PATH_KEEP_ALIVE_TIME_SECONDS = 3600;
94106
static final long DIRECT_PATH_KEEP_ALIVE_TIMEOUT_SECONDS = 20;
@@ -147,6 +159,19 @@ private InstantiatingGrpcChannelProvider(Builder builder) {
147159
: builder.directPathServiceConfig;
148160
}
149161

162+
/**
163+
* Package-Private constructor that is only visible for testing DirectPath functionality inside
164+
* tests. This overrides the computed systemProductName when the class is initialized to help
165+
* configure the result of {@link #isOnComputeEngine()} check.
166+
*
167+
* <p>If productName is null, that represents the result of an IOException
168+
*/
169+
@VisibleForTesting
170+
InstantiatingGrpcChannelProvider(Builder builder, String productName) {
171+
this(builder);
172+
systemProductName = productName;
173+
}
174+
150175
/**
151176
* @deprecated If executor is not set, this channel provider will create channels with default
152177
* grpc executor.
@@ -257,8 +282,8 @@ private boolean isDirectPathEnabled() {
257282
return false;
258283
}
259284

260-
@VisibleForTesting
261-
boolean isDirectPathXdsEnabled() {
285+
@InternalApi
286+
public boolean isDirectPathXdsEnabled() {
262287
// Method 1: Enable DirectPath xDS by option.
263288
if (Boolean.TRUE.equals(attemptDirectPathXds)) {
264289
return true;
@@ -320,15 +345,9 @@ boolean isCredentialDirectPathCompatible() {
320345
static boolean isOnComputeEngine() {
321346
String osName = System.getProperty("os.name");
322347
if ("Linux".equals(osName)) {
323-
try {
324-
String result =
325-
Files.asCharSource(new File("/sys/class/dmi/id/product_name"), StandardCharsets.UTF_8)
326-
.readFirstLine();
327-
return result.contains(GCE_PRODUCTION_NAME_PRIOR_2016)
328-
|| result.contains(GCE_PRODUCTION_NAME_AFTER_2016);
329-
} catch (IOException ignored) {
330-
return false;
331-
}
348+
// systemProductName will be empty string if not on Compute Engine
349+
return systemProductName.contains(GCE_PRODUCTION_NAME_PRIOR_2016)
350+
|| systemProductName.contains(GCE_PRODUCTION_NAME_AFTER_2016);
332351
}
333352
return false;
334353
}
@@ -370,10 +389,7 @@ private ManagedChannel createSingleChannel() throws IOException {
370389

371390
// Check DirectPath traffic.
372391
boolean useDirectPathXds = false;
373-
if (isDirectPathEnabled()
374-
&& isCredentialDirectPathCompatible()
375-
&& isOnComputeEngine()
376-
&& canUseDirectPathWithUniverseDomain()) {
392+
if (canUseDirectPath()) {
377393
CallCredentials callCreds = MoreCallCredentials.from(credentials);
378394
ChannelCredentials channelCreds =
379395
GoogleDefaultChannelCredentials.newBuilder().callCredentials(callCreds).build();
@@ -446,6 +462,24 @@ && canUseDirectPathWithUniverseDomain()) {
446462
return managedChannel;
447463
}
448464

465+
/**
466+
* Marked as Internal Api and intended for internal use. DirectPath must be enabled via the
467+
* settings and a few other configurations/settings must also be valid for the request to go
468+
* through DirectPath.
469+
*
470+
* <p>Checks: 1. Credentials are compatible 2.Running on Compute Engine 3. Universe Domain is
471+
* configured to for the Google Default Universe
472+
*
473+
* @return if DirectPath is enabled for the client AND if the configurations are valid
474+
*/
475+
@InternalApi
476+
public boolean canUseDirectPath() {
477+
return isDirectPathEnabled()
478+
&& isCredentialDirectPathCompatible()
479+
&& isOnComputeEngine()
480+
&& canUseDirectPathWithUniverseDomain();
481+
}
482+
449483
/** The endpoint to be used for the channel. */
450484
@Override
451485
public String getEndpoint() {
@@ -753,6 +787,12 @@ public Builder setAttemptDirectPathXds() {
753787
return this;
754788
}
755789

790+
@VisibleForTesting
791+
Builder setEnvProvider(EnvironmentProvider envProvider) {
792+
this.envProvider = envProvider;
793+
return this;
794+
}
795+
756796
/**
757797
* Sets a service config for direct path. If direct path is not enabled, the provided service
758798
* config will be ignored.

0 commit comments

Comments
 (0)