Skip to content

Commit 59459ae

Browse files
committed
Refactor Header Interceptor and modified the server timing header logic
1 parent 3b03055 commit 59459ae

File tree

7 files changed

+164
-119
lines changed

7 files changed

+164
-119
lines changed

google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInOpenTelemetryMetricsProvider.java

Lines changed: 67 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.google.cloud.opentelemetry.detection.AttributeKeys;
2929
import com.google.cloud.opentelemetry.detection.DetectedPlatform;
3030
import com.google.cloud.opentelemetry.detection.GCPPlatformDetector;
31+
import com.google.common.annotations.VisibleForTesting;
3132
import com.google.common.cache.Cache;
3233
import com.google.common.cache.CacheBuilder;
3334
import com.google.common.hash.HashFunction;
@@ -44,72 +45,96 @@
4445
import java.util.HashMap;
4546
import java.util.Map;
4647
import java.util.UUID;
47-
import java.util.concurrent.ExecutionException;
4848
import java.util.logging.Level;
4949
import java.util.logging.Logger;
5050
import javax.annotation.Nullable;
5151

5252
final class BuiltInOpenTelemetryMetricsProvider {
5353

54-
static BuiltInOpenTelemetryMetricsProvider INSTANCE = new BuiltInOpenTelemetryMetricsProvider();
54+
public static BuiltInOpenTelemetryMetricsProvider INSTANCE =
55+
new BuiltInOpenTelemetryMetricsProvider();
5556

5657
private static final Logger logger =
5758
Logger.getLogger(BuiltInOpenTelemetryMetricsProvider.class.getName());
5859

60+
private final Cache<String, Map<String, String>> clientAttributesCache =
61+
CacheBuilder.newBuilder().maximumSize(1000).build();
62+
5963
private static String taskId;
6064

6165
private OpenTelemetry openTelemetry;
6266

63-
private final Cache<String, Map<String, String>> clientAttributesCache =
64-
CacheBuilder.newBuilder().maximumSize(1000).build();
67+
private Map<String, String> clientAttributes;
68+
69+
private boolean isInitialized;
6570

66-
private BuiltInOpenTelemetryMetricsProvider() {}
71+
private BuiltInOpenTelemetryMetricsRecorder builtInOpenTelemetryMetricsRecorder;
72+
73+
private BuiltInOpenTelemetryMetricsProvider() {};
74+
75+
void initialize(
76+
String projectId,
77+
String client_name,
78+
@Nullable Credentials credentials,
79+
@Nullable String monitoringHost) {
6780

68-
OpenTelemetry getOrCreateOpenTelemetry(
69-
String projectId, @Nullable Credentials credentials, @Nullable String monitoringHost) {
7081
try {
71-
if (this.openTelemetry == null) {
72-
SdkMeterProviderBuilder sdkMeterProviderBuilder = SdkMeterProvider.builder();
73-
BuiltInOpenTelemetryMetricsView.registerBuiltinMetrics(
74-
SpannerCloudMonitoringExporter.create(projectId, credentials, monitoringHost),
75-
sdkMeterProviderBuilder);
76-
SdkMeterProvider sdkMeterProvider = sdkMeterProviderBuilder.build();
77-
this.openTelemetry = OpenTelemetrySdk.builder().setMeterProvider(sdkMeterProvider).build();
78-
Runtime.getRuntime().addShutdownHook(new Thread(sdkMeterProvider::close));
82+
if (!isInitialized) {
83+
this.openTelemetry = createOpenTelemetry(projectId, credentials, monitoringHost);
84+
this.clientAttributes = createClientAttributes(projectId, client_name);
85+
this.builtInOpenTelemetryMetricsRecorder =
86+
new BuiltInOpenTelemetryMetricsRecorder(openTelemetry, clientAttributes);
87+
isInitialized = true;
7988
}
80-
return this.openTelemetry;
81-
} catch (IOException ex) {
89+
} catch (Exception ex) {
8290
logger.log(
8391
Level.WARNING,
84-
"Unable to get OpenTelemetry object for client side metrics, will skip exporting client side metrics",
92+
"Unable to initialize OpenTelemetry object or attributes for client side metrics, will skip exporting client side metrics",
8593
ex);
86-
return null;
8794
}
8895
}
8996

90-
Map<String, String> createOrGetClientAttributes(String projectId, String client_name) {
91-
try {
92-
String key = projectId + client_name;
93-
return clientAttributesCache.get(
94-
key,
95-
() -> {
96-
Map<String, String> clientAttributes = new HashMap<>();
97-
clientAttributes.put(LOCATION_ID_KEY.getKey(), detectClientLocation());
98-
clientAttributes.put(PROJECT_ID_KEY.getKey(), projectId);
99-
clientAttributes.put(INSTANCE_CONFIG_ID_KEY.getKey(), "unknown");
100-
clientAttributes.put(CLIENT_NAME_KEY.getKey(), client_name);
101-
String clientUid = getDefaultTaskValue();
102-
clientAttributes.put(CLIENT_UID_KEY.getKey(), clientUid);
103-
clientAttributes.put(CLIENT_HASH_KEY.getKey(), generateClientHash(clientUid));
104-
return clientAttributes;
105-
});
106-
} catch (ExecutionException executionException) {
107-
logger.log(
108-
Level.WARNING,
109-
"Unable to get Client Attributes for client side metrics, will skip exporting client side metrics",
110-
executionException);
111-
return null;
112-
}
97+
OpenTelemetry getOpenTelemetry() {
98+
return this.openTelemetry;
99+
}
100+
101+
Map<String, String> getClientAttributes() {
102+
return this.clientAttributes;
103+
}
104+
105+
BuiltInOpenTelemetryMetricsRecorder getBuiltInOpenTelemetryMetricsRecorder() {
106+
return this.builtInOpenTelemetryMetricsRecorder;
107+
}
108+
109+
@VisibleForTesting
110+
void reset() {
111+
isInitialized = false;
112+
}
113+
114+
private Map<String, String> createClientAttributes(String projectId, String client_name) {
115+
Map<String, String> clientAttributes = new HashMap<>();
116+
clientAttributes.put(LOCATION_ID_KEY.getKey(), detectClientLocation());
117+
clientAttributes.put(PROJECT_ID_KEY.getKey(), projectId);
118+
clientAttributes.put(INSTANCE_CONFIG_ID_KEY.getKey(), "unknown");
119+
clientAttributes.put(CLIENT_NAME_KEY.getKey(), client_name);
120+
String clientUid = getDefaultTaskValue();
121+
clientAttributes.put(CLIENT_UID_KEY.getKey(), clientUid);
122+
clientAttributes.put(CLIENT_HASH_KEY.getKey(), generateClientHash(clientUid));
123+
return clientAttributes;
124+
}
125+
126+
private OpenTelemetry createOpenTelemetry(
127+
String projectId, @Nullable Credentials credentials, @Nullable String monitoringHost)
128+
throws IOException {
129+
OpenTelemetry openTelemetry;
130+
SdkMeterProviderBuilder sdkMeterProviderBuilder = SdkMeterProvider.builder();
131+
BuiltInOpenTelemetryMetricsView.registerBuiltinMetrics(
132+
SpannerCloudMonitoringExporter.create(projectId, credentials, monitoringHost),
133+
sdkMeterProviderBuilder);
134+
SdkMeterProvider sdkMeterProvider = sdkMeterProviderBuilder.build();
135+
openTelemetry = OpenTelemetrySdk.builder().setMeterProvider(sdkMeterProvider).build();
136+
Runtime.getRuntime().addShutdownHook(new Thread(sdkMeterProvider::close));
137+
return openTelemetry;
113138
}
114139

115140
/**

google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInOpenTelemetryMetricsRecorder.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Google LLC
2+
* Copyright 2025 Google LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -44,10 +44,11 @@ public class BuiltInOpenTelemetryMetricsRecorder {
4444
*/
4545
public BuiltInOpenTelemetryMetricsRecorder(
4646
OpenTelemetry openTelemetry, Map<String, String> clientAttributes) {
47-
if (openTelemetry != null && clientAttributes != null) {
47+
if (openTelemetry == null || clientAttributes == null) {
4848
gfeLatencyRecorder = null;
4949
return;
5050
}
51+
5152
Meter meter =
5253
openTelemetry
5354
.meterBuilder(BuiltInMetricsConstant.SPANNER_METER_NAME)

google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,16 +1825,21 @@ public OpenTelemetry getOpenTelemetry() {
18251825
}
18261826
}
18271827

1828-
/** Returns an instance of OpenTelemetry object for Built-in Client metrics. */
1829-
public OpenTelemetry getBuiltInMetricsOpenTelemetry() {
1830-
return this.builtInOpenTelemetryMetricsProvider.getOrCreateOpenTelemetry(
1831-
this.getProjectId(), getCredentials());
1828+
/**
1829+
* Returns an instance of Built-In MetricsRecorder object. initializeBuiltInMetrics should be
1830+
* called first before this recorder can be fetched
1831+
*/
1832+
public BuiltInOpenTelemetryMetricsRecorder getBuiltInMetricsRecorder() {
1833+
return this.builtInOpenTelemetryMetricsProvider.getBuiltInOpenTelemetryMetricsRecorder();
18321834
}
18331835

1834-
/** Returns attributes for an instance of Built-in Client metrics. */
1835-
public Map<String, String> getBuiltInMetricsClientAttributes() {
1836-
return builtInOpenTelemetryMetricsProvider.createOrGetClientAttributes(
1837-
this.getProjectId(), "spanner-java/" + GaxProperties.getLibraryVersion(getClass()));
1836+
/** Initialize the built-in metrics provider */
1837+
public void initializeBuiltInMetrics() {
1838+
this.builtInOpenTelemetryMetricsProvider.initialize(
1839+
this.getProjectId(),
1840+
"spanner-java/" + GaxProperties.getLibraryVersion(getClass()),
1841+
getCredentials(),
1842+
this.getMonitoringHost());
18381843
}
18391844

18401845
@Override
@@ -1882,13 +1887,10 @@ private ApiTracerFactory getDefaultApiTracerFactory() {
18821887
}
18831888

18841889
private ApiTracerFactory createMetricsApiTracerFactory() {
1885-
OpenTelemetry openTelemetry =
1886-
this.builtInOpenTelemetryMetricsProvider.getOrCreateOpenTelemetry(
1887-
this.getProjectId(), getCredentials(), this.monitoringHost);
1890+
OpenTelemetry openTelemetry = this.builtInOpenTelemetryMetricsProvider.getOpenTelemetry();
18881891

18891892
Map<String, String> clientAttributes =
1890-
builtInOpenTelemetryMetricsProvider.createOrGetClientAttributes(
1891-
this.getProjectId(), "spanner-java/" + GaxProperties.getLibraryVersion(getClass()));
1893+
builtInOpenTelemetryMetricsProvider.getClientAttributes();
18921894
return openTelemetry != null && clientAttributes != null
18931895
? new MetricsTracerFactory(
18941896
new OpenTelemetryMetricsRecorder(openTelemetry, BuiltInMetricsConstant.METER_NAME),

google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ public GapicSpannerRpc(final SpannerOptions options) {
333333
this.endToEndTracingEnabled = options.isEndToEndTracingEnabled();
334334
this.numChannels = options.getNumChannels();
335335
this.isGrpcGcpExtensionEnabled = options.isGrpcGcpExtensionEnabled();
336+
options.initializeBuiltInMetrics();
336337

337338
if (initializeStubs) {
338339
// First check if SpannerOptions provides a TransportChannelProvider. Create one
@@ -357,8 +358,7 @@ public GapicSpannerRpc(final SpannerOptions options) {
357358
options.getInterceptorProvider(),
358359
SpannerInterceptorProvider.createDefault(
359360
options.getOpenTelemetry(),
360-
options.getBuiltInMetricsOpenTelemetry(),
361-
options.getBuiltInMetricsClientAttributes(),
361+
options.getBuiltInMetricsRecorder(),
362362
(() -> directPathEnabledSupplier.get()))))
363363
// This sets the trace context headers.
364364
.withTraceContext(endToEndTracingEnabled, options.getOpenTelemetry())

0 commit comments

Comments
 (0)