Skip to content

Commit 754b75b

Browse files
committed
chore: add support for OpenTelemetry metrics to Connection API
1 parent e99b78c commit 754b75b

File tree

3 files changed

+69
-2
lines changed

3 files changed

+69
-2
lines changed

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
import com.google.common.base.Strings;
4040
import com.google.common.collect.Sets;
4141
import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions;
42+
import io.opentelemetry.api.GlobalOpenTelemetry;
43+
import io.opentelemetry.api.OpenTelemetry;
4244
import java.io.IOException;
4345
import java.lang.reflect.Constructor;
4446
import java.lang.reflect.InvocationTargetException;
@@ -54,6 +56,7 @@
5456
import java.util.regex.Matcher;
5557
import java.util.regex.Pattern;
5658
import java.util.stream.Stream;
59+
import javax.annotation.Nonnull;
5760
import javax.annotation.Nullable;
5861

5962
/**
@@ -484,6 +487,7 @@ public static class Builder {
484487
private List<StatementExecutionInterceptor> statementExecutionInterceptors =
485488
Collections.emptyList();
486489
private SpannerOptionsConfigurator configurator;
490+
private OpenTelemetry openTelemetry;
487491

488492
private Builder() {}
489493

@@ -633,6 +637,11 @@ Builder setCredentials(Credentials credentials) {
633637
return this;
634638
}
635639

640+
public Builder setOpenTelemetry(OpenTelemetry openTelemetry) {
641+
this.openTelemetry = openTelemetry;
642+
return this;
643+
}
644+
636645
/** @return the {@link ConnectionOptions} */
637646
public ConnectionOptions build() {
638647
Preconditions.checkState(this.uri != null, "Connection URI is required");
@@ -691,6 +700,7 @@ public static Builder newBuilder() {
691700
private final boolean retryAbortsInternally;
692701
private final boolean useVirtualThreads;
693702
private final boolean useVirtualGrpcTransportThreads;
703+
private final OpenTelemetry openTelemetry;
694704
private final List<StatementExecutionInterceptor> statementExecutionInterceptors;
695705
private final SpannerOptionsConfigurator configurator;
696706

@@ -792,6 +802,7 @@ private ConnectionOptions(Builder builder) {
792802
this.retryAbortsInternally = parseRetryAbortsInternally(this.uri);
793803
this.useVirtualThreads = parseUseVirtualThreads(this.uri);
794804
this.useVirtualGrpcTransportThreads = parseUseVirtualGrpcTransportThreads(this.uri);
805+
this.openTelemetry = builder.openTelemetry;
795806
this.statementExecutionInterceptors =
796807
Collections.unmodifiableList(builder.statementExecutionInterceptors);
797808
this.configurator = builder.configurator;
@@ -856,6 +867,19 @@ private static Integer parseIntegerProperty(String propertyName, String value) {
856867
return null;
857868
}
858869

870+
/**
871+
* Returns an instance of OpenTelemetry. If OpenTelemetry object is not set then
872+
* GlobalOpenTelemetry will be used as fallback.
873+
*/
874+
@Nonnull
875+
OpenTelemetry getOpenTelemetry() {
876+
if (this.openTelemetry != null) {
877+
return this.openTelemetry;
878+
} else {
879+
return GlobalOpenTelemetry.get();
880+
}
881+
}
882+
859883
SpannerOptionsConfigurator getConfigurator() {
860884
return configurator;
861885
}

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerPool.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.common.base.Preconditions;
3030
import com.google.common.base.Ticker;
3131
import io.grpc.ManagedChannelBuilder;
32+
import io.opentelemetry.api.OpenTelemetry;
3233
import java.io.IOException;
3334
import java.util.ArrayList;
3435
import java.util.HashMap;
@@ -156,6 +157,7 @@ static class SpannerPoolKey {
156157
private final String databaseRole;
157158
private final boolean routeToLeader;
158159
private final boolean useVirtualGrpcTransportThreads;
160+
private final OpenTelemetry openTelemetry;
159161

160162
@VisibleForTesting
161163
static SpannerPoolKey of(ConnectionOptions options) {
@@ -183,6 +185,7 @@ private SpannerPoolKey(ConnectionOptions options) throws IOException {
183185
this.userAgent = options.getUserAgent();
184186
this.routeToLeader = options.isRouteToLeader();
185187
this.useVirtualGrpcTransportThreads = options.isUseVirtualGrpcTransportThreads();
188+
this.openTelemetry = options.getOpenTelemetry();
186189
}
187190

188191
@Override
@@ -201,7 +204,8 @@ public boolean equals(Object o) {
201204
&& Objects.equals(this.userAgent, other.userAgent)
202205
&& Objects.equals(this.routeToLeader, other.routeToLeader)
203206
&& Objects.equals(
204-
this.useVirtualGrpcTransportThreads, other.useVirtualGrpcTransportThreads);
207+
this.useVirtualGrpcTransportThreads, other.useVirtualGrpcTransportThreads)
208+
&& Objects.equals(this.openTelemetry, other.openTelemetry);
205209
}
206210

207211
@Override
@@ -216,7 +220,8 @@ public int hashCode() {
216220
this.databaseRole,
217221
this.userAgent,
218222
this.routeToLeader,
219-
this.useVirtualGrpcTransportThreads);
223+
this.useVirtualGrpcTransportThreads,
224+
this.openTelemetry);
220225
}
221226
}
222227

@@ -349,6 +354,9 @@ Spanner createSpanner(SpannerPoolKey key, ConnectionOptions options) {
349354
.setDatabaseRole(options.getDatabaseRole())
350355
.setCredentials(options.getCredentials());
351356
builder.setSessionPoolOption(key.sessionPoolOptions);
357+
if (key.openTelemetry != null) {
358+
builder.setOpenTelemetry(key.openTelemetry);
359+
}
352360
if (key.numChannels != null) {
353361
builder.setNumChannels(key.numChannels);
354362
}

google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SpannerPoolTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
import com.google.cloud.spanner.connection.SpannerPool.SpannerPoolKey;
4040
import com.google.common.base.Ticker;
4141
import com.google.common.testing.FakeTicker;
42+
43+
import io.opentelemetry.api.OpenTelemetry;
44+
import io.opentelemetry.sdk.OpenTelemetrySdk;
45+
4246
import java.io.ByteArrayOutputStream;
4347
import java.io.OutputStream;
4448
import java.util.concurrent.TimeUnit;
@@ -69,6 +73,10 @@ public class SpannerPoolTest {
6973
private ConnectionOptions options7 = mock(ConnectionOptions.class);
7074
private ConnectionOptions options8 = mock(ConnectionOptions.class);
7175

76+
private ConnectionOptions optionsOpenTelemetry1 = mock(ConnectionOptions.class);
77+
private ConnectionOptions optionsOpenTelemetry2 = mock(ConnectionOptions.class);
78+
private ConnectionOptions optionsOpenTelemetry3 = mock(ConnectionOptions.class);
79+
7280
private SpannerPool createSubjectAndMocks() {
7381
return createSubjectAndMocks(0L, Ticker.systemTicker());
7482
}
@@ -83,6 +91,9 @@ Spanner createSpanner(SpannerPoolKey key, ConnectionOptions options) {
8391
}
8492
};
8593

94+
OpenTelemetry openTelemetry1 = OpenTelemetrySdk.builder().build();
95+
OpenTelemetry openTelemetry2 = OpenTelemetrySdk.builder().build();
96+
8697
when(options1.getCredentialsUrl()).thenReturn(credentials1);
8798
when(options1.getProjectId()).thenReturn("test-project-1");
8899
when(options2.getCredentialsUrl()).thenReturn(credentials2);
@@ -101,6 +112,13 @@ Spanner createSpanner(SpannerPoolKey key, ConnectionOptions options) {
101112
when(options8.getProjectId()).thenReturn("test-project-3");
102113
when(options8.isRouteToLeader()).thenReturn(false);
103114

115+
when(optionsOpenTelemetry1.getProjectId()).thenReturn("test-project-1");
116+
when(optionsOpenTelemetry1.getOpenTelemetry()).thenReturn(openTelemetry1);
117+
when(optionsOpenTelemetry2.getProjectId()).thenReturn("test-project-1");
118+
when(optionsOpenTelemetry2.getOpenTelemetry()).thenReturn(openTelemetry1);
119+
when(optionsOpenTelemetry3.getProjectId()).thenReturn("test-project-1");
120+
when(optionsOpenTelemetry3.getOpenTelemetry()).thenReturn(openTelemetry2);
121+
104122
return pool;
105123
}
106124

@@ -498,4 +516,21 @@ public void testSpannerPoolKeyEquality() {
498516
assertEquals(key3, key4);
499517
assertNotEquals(key4, key5);
500518
}
519+
520+
@Test
521+
public void testOpenTelemetry() {
522+
SpannerPool pool = createSubjectAndMocks();
523+
Spanner spanner1;
524+
Spanner spanner2;
525+
526+
// assert equal
527+
spanner1 = pool.getSpanner(optionsOpenTelemetry1, connection1);
528+
spanner2 = pool.getSpanner(optionsOpenTelemetry2, connection2);
529+
assertEquals(spanner1, spanner2);
530+
531+
// assert not equal
532+
spanner1 = pool.getSpanner(optionsOpenTelemetry1, connection1);
533+
spanner2 = pool.getSpanner(optionsOpenTelemetry3, connection2);
534+
assertNotEquals(spanner1, spanner2);
535+
}
501536
}

0 commit comments

Comments
 (0)