Skip to content

Commit c5a2045

Browse files
perf: cache the key used for OTEL traces and metrics (#3814)
* perf: cache the key used for OTEL traces and metrics The HeaderInterceptor creates a key consisting of the database name and method name that is used for OpenTelemetry attributes and metrics. The number of unique keys is low. However, the key is constructed from the DatabaseName and method name every time, which leads to a lot of string creation: 1. The DatabaseName.toString() method is called every time. This constructs a new string. 2. The result of DatabaseName.toString() is concatenated with the methodName to create yet another string. Instead of creating the key every time, we can cache the key values without doing the string creation and concatenation every time. * chore: generate libraries at Thu Apr 10 11:15:55 UTC 2025 --------- Co-authored-by: cloud-java-bot <[email protected]>
1 parent a2780ed commit c5a2045

File tree

2 files changed

+11
-2
lines changed

2 files changed

+11
-2
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file:
1919
<dependency>
2020
<groupId>com.google.cloud</groupId>
2121
<artifactId>libraries-bom</artifactId>
22-
<version>26.54.0</version>
22+
<version>26.57.0</version>
2323
<type>pom</type>
2424
<scope>import</scope>
2525
</dependency>

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

+10-1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ class HeaderInterceptor implements ClientInterceptor {
8787
CacheBuilder.newBuilder().maximumSize(1000).build();
8888
private final Cache<String, Map<String, String>> builtInAttributesCache =
8989
CacheBuilder.newBuilder().maximumSize(1000).build();
90+
private final Cache<DatabaseName, Cache<String, String>> keyCache =
91+
CacheBuilder.newBuilder().maximumSize(1000).build();
9092

9193
// Get the global singleton Tagger object.
9294
private static final Tagger TAGGER = Tags.getTagger();
@@ -116,7 +118,7 @@ public void start(Listener<RespT> responseListener, Metadata headers) {
116118
try {
117119
Span span = Span.current();
118120
DatabaseName databaseName = extractDatabaseName(headers);
119-
String key = databaseName + method.getFullMethodName();
121+
String key = extractKey(databaseName, method.getFullMethodName());
120122
TagContext tagContext = getTagContext(key, method.getFullMethodName(), databaseName);
121123
Attributes attributes =
122124
getMetricAttributes(key, method.getFullMethodName(), databaseName);
@@ -201,6 +203,13 @@ private Map<String, Long> parseServerTimingHeader(String serverTiming) {
201203
return serverTimingMetrics;
202204
}
203205

206+
private String extractKey(DatabaseName databaseName, String methodName)
207+
throws ExecutionException {
208+
Cache<String, String> keys =
209+
keyCache.get(databaseName, () -> CacheBuilder.newBuilder().maximumSize(1000).build());
210+
return keys.get(methodName, () -> databaseName + methodName);
211+
}
212+
204213
private DatabaseName extractDatabaseName(Metadata headers) throws ExecutionException {
205214
String googleResourcePrefix = headers.get(GOOGLE_CLOUD_RESOURCE_PREFIX_KEY);
206215
if (googleResourcePrefix != null) {

0 commit comments

Comments
 (0)