Skip to content

Commit 02c0303

Browse files
committed
Refactor Header Interceptor and modified the server timing header logic
1 parent b4c359c commit 02c0303

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
@@ -1860,16 +1860,21 @@ public OpenTelemetry getOpenTelemetry() {
18601860
}
18611861
}
18621862

1863-
/** Returns an instance of OpenTelemetry object for Built-in Client metrics. */
1864-
public OpenTelemetry getBuiltInMetricsOpenTelemetry() {
1865-
return this.builtInOpenTelemetryMetricsProvider.getOrCreateOpenTelemetry(
1866-
this.getProjectId(), getCredentials());
1863+
/**
1864+
* Returns an instance of Built-In MetricsRecorder object. initializeBuiltInMetrics should be
1865+
* called first before this recorder can be fetched
1866+
*/
1867+
public BuiltInOpenTelemetryMetricsRecorder getBuiltInMetricsRecorder() {
1868+
return this.builtInOpenTelemetryMetricsProvider.getBuiltInOpenTelemetryMetricsRecorder();
18671869
}
18681870

1869-
/** Returns attributes for an instance of Built-in Client metrics. */
1870-
public Map<String, String> getBuiltInMetricsClientAttributes() {
1871-
return builtInOpenTelemetryMetricsProvider.createOrGetClientAttributes(
1872-
this.getProjectId(), "spanner-java/" + GaxProperties.getLibraryVersion(getClass()));
1871+
/** Initialize the built-in metrics provider */
1872+
public void initializeBuiltInMetrics() {
1873+
this.builtInOpenTelemetryMetricsProvider.initialize(
1874+
this.getProjectId(),
1875+
"spanner-java/" + GaxProperties.getLibraryVersion(getClass()),
1876+
getCredentials(),
1877+
this.getMonitoringHost());
18731878
}
18741879

18751880
@Override
@@ -1917,13 +1922,10 @@ private ApiTracerFactory getDefaultApiTracerFactory() {
19171922
}
19181923

19191924
private ApiTracerFactory createMetricsApiTracerFactory() {
1920-
OpenTelemetry openTelemetry =
1921-
this.builtInOpenTelemetryMetricsProvider.getOrCreateOpenTelemetry(
1922-
this.getProjectId(), getCredentials(), this.monitoringHost);
1925+
OpenTelemetry openTelemetry = this.builtInOpenTelemetryMetricsProvider.getOpenTelemetry();
19231926

19241927
Map<String, String> clientAttributes =
1925-
builtInOpenTelemetryMetricsProvider.createOrGetClientAttributes(
1926-
this.getProjectId(), "spanner-java/" + GaxProperties.getLibraryVersion(getClass()));
1928+
builtInOpenTelemetryMetricsProvider.getClientAttributes();
19271929
return openTelemetry != null && clientAttributes != null
19281930
? new MetricsTracerFactory(
19291931
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)