Skip to content

chore: add connection property for API tracing #3168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ If you are using Maven without the BOM, add this to your dependencies:
If you are using Gradle 5.x or later, add this to your dependencies:

```Groovy
implementation platform('com.google.cloud:libraries-bom:26.41.0')
implementation platform('com.google.cloud:libraries-bom:26.42.0')

implementation 'com.google.cloud:google-cloud-spanner'
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ public String[] getValidValues() {
private static final int DEFAULT_MAX_PARTITIONS = 0;
private static final int DEFAULT_MAX_PARTITIONED_PARALLELISM = 1;
private static final Boolean DEFAULT_ENABLE_EXTENDED_TRACING = null;
private static final Boolean DEFAULT_ENABLE_API_TRACING = null;

private static final String PLAIN_TEXT_PROTOCOL = "http:";
private static final String HOST_PROTOCOL = "https:";
Expand Down Expand Up @@ -280,6 +281,7 @@ public String[] getValidValues() {
"maxPartitionedParallelism";

public static final String ENABLE_EXTENDED_TRACING_PROPERTY_NAME = "enableExtendedTracing";
public static final String ENABLE_API_TRACING_PROPERTY_NAME = "enableApiTracing";

private static final String GUARDED_CONNECTION_PROPERTY_ERROR_MESSAGE =
"%s can only be used if the system property %s has been set to true. "
Expand Down Expand Up @@ -448,7 +450,14 @@ private static String generateGuardedConnectionPropertyError(
"Include the SQL string in the OpenTelemetry traces that are generated "
+ "by this connection. The SQL string is added as the standard OpenTelemetry "
+ "attribute 'db.statement'.",
DEFAULT_ENABLE_EXTENDED_TRACING))));
DEFAULT_ENABLE_EXTENDED_TRACING),
ConnectionProperty.createBooleanProperty(
ENABLE_API_TRACING_PROPERTY_NAME,
"Add OpenTelemetry traces for each individual RPC call. Enable this "
+ "to get a detailed view of each RPC that is being executed by your application, "
+ "or if you want to debug potential latency problems caused by RPCs that are "
+ "being retried.",
DEFAULT_ENABLE_API_TRACING))));

private static final Set<ConnectionProperty> INTERNAL_PROPERTIES =
Collections.unmodifiableSet(
Expand Down Expand Up @@ -743,6 +752,7 @@ public static Builder newBuilder() {
private final OpenTelemetry openTelemetry;
private final String tracingPrefix;
private final Boolean enableExtendedTracing;
private final Boolean enableApiTracing;
private final List<StatementExecutionInterceptor> statementExecutionInterceptors;
private final SpannerOptionsConfigurator configurator;

Expand Down Expand Up @@ -851,6 +861,7 @@ private ConnectionOptions(Builder builder) {
this.openTelemetry = builder.openTelemetry;
this.tracingPrefix = builder.tracingPrefix;
this.enableExtendedTracing = parseEnableExtendedTracing(this.uri);
this.enableApiTracing = parseEnableApiTracing(this.uri);
this.statementExecutionInterceptors =
Collections.unmodifiableList(builder.statementExecutionInterceptors);
this.configurator = builder.configurator;
Expand Down Expand Up @@ -1251,6 +1262,12 @@ static Boolean parseEnableExtendedTracing(String uri) {
return value != null ? Boolean.valueOf(value) : DEFAULT_ENABLE_EXTENDED_TRACING;
}

@VisibleForTesting
static Boolean parseEnableApiTracing(String uri) {
String value = parseUriProperty(uri, ENABLE_API_TRACING_PROPERTY_NAME);
return value != null ? Boolean.valueOf(value) : DEFAULT_ENABLE_API_TRACING;
}

@VisibleForTesting
static String parseUriProperty(String uri, String property) {
Pattern pattern = Pattern.compile(String.format("(?is)(?:;|\\?)%s=(.*?)(?:;|$)", property));
Expand Down Expand Up @@ -1558,6 +1575,10 @@ Boolean isEnableExtendedTracing() {
return this.enableExtendedTracing;
}

Boolean isEnableApiTracing() {
return this.enableApiTracing;
}

/** Interceptors that should be executed after each statement */
List<StatementExecutionInterceptor> getStatementExecutionInterceptors() {
return statementExecutionInterceptors;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ static class SpannerPoolKey {
private final boolean useVirtualGrpcTransportThreads;
private final OpenTelemetry openTelemetry;
private final Boolean enableExtendedTracing;
private final Boolean enableApiTracing;

@VisibleForTesting
static SpannerPoolKey of(ConnectionOptions options) {
Expand Down Expand Up @@ -188,6 +189,7 @@ private SpannerPoolKey(ConnectionOptions options) throws IOException {
this.useVirtualGrpcTransportThreads = options.isUseVirtualGrpcTransportThreads();
this.openTelemetry = options.getOpenTelemetry();
this.enableExtendedTracing = options.isEnableExtendedTracing();
this.enableApiTracing = options.isEnableApiTracing();
}

@Override
Expand All @@ -208,7 +210,8 @@ public boolean equals(Object o) {
&& Objects.equals(
this.useVirtualGrpcTransportThreads, other.useVirtualGrpcTransportThreads)
&& Objects.equals(this.openTelemetry, other.openTelemetry)
&& Objects.equals(this.enableExtendedTracing, other.enableExtendedTracing);
&& Objects.equals(this.enableExtendedTracing, other.enableExtendedTracing)
&& Objects.equals(this.enableApiTracing, other.enableApiTracing);
}

@Override
Expand All @@ -225,7 +228,8 @@ public int hashCode() {
this.routeToLeader,
this.useVirtualGrpcTransportThreads,
this.openTelemetry,
this.enableExtendedTracing);
this.enableExtendedTracing,
this.enableApiTracing);
}
}

Expand Down Expand Up @@ -364,6 +368,9 @@ Spanner createSpanner(SpannerPoolKey key, ConnectionOptions options) {
if (key.enableExtendedTracing != null) {
builder.setEnableExtendedTracing(key.enableExtendedTracing);
}
if (key.enableApiTracing != null) {
builder.setEnableApiTracing(key.enableApiTracing);
}
if (key.numChannels != null) {
builder.setNumChannels(key.numChannels);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1165,4 +1165,29 @@ public void testMaxCommitDelay() {
.build()
.getMaxCommitDelay());
}

@Test
public void testEnableApiTracing() {
assertNull(
ConnectionOptions.newBuilder()
.setUri(
"cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database")
.setCredentials(NoCredentials.getInstance())
.build()
.isEnableApiTracing());
assertTrue(
ConnectionOptions.newBuilder()
.setUri(
"cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?enableApiTracing=true")
.setCredentials(NoCredentials.getInstance())
.build()
.isEnableApiTracing());
assertFalse(
ConnectionOptions.newBuilder()
.setUri(
"cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?enableApiTracing=false")
.setCredentials(NoCredentials.getInstance())
.build()
.isEnableApiTracing());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,54 @@ public void testSpannerPoolKeyEquality() {
assertNotEquals(key4, key5);
}

@Test
public void testEnableApiTracing() {
SpannerPoolKey keyWithoutApiTracingConfig =
SpannerPoolKey.of(
ConnectionOptions.newBuilder()
.setUri("cloudspanner:/projects/p/instances/i/databases/d")
.setCredentials(NoCredentials.getInstance())
.build());
SpannerPoolKey keyWithApiTracingEnabled =
SpannerPoolKey.of(
ConnectionOptions.newBuilder()
.setUri("cloudspanner:/projects/p/instances/i/databases/d?enableApiTracing=true")
.setCredentials(NoCredentials.getInstance())
.build());
SpannerPoolKey keyWithApiTracingDisabled =
SpannerPoolKey.of(
ConnectionOptions.newBuilder()
.setUri("cloudspanner:/projects/p/instances/i/databases/d?enableApiTracing=false")
.setCredentials(NoCredentials.getInstance())
.build());

assertNotEquals(keyWithoutApiTracingConfig, keyWithApiTracingEnabled);
assertNotEquals(keyWithoutApiTracingConfig, keyWithApiTracingDisabled);
assertNotEquals(keyWithApiTracingEnabled, keyWithApiTracingDisabled);

assertEquals(
keyWithApiTracingEnabled,
SpannerPoolKey.of(
ConnectionOptions.newBuilder()
.setUri("cloudspanner:/projects/p/instances/i/databases/d?enableApiTracing=true")
.setCredentials(NoCredentials.getInstance())
.build()));
assertEquals(
keyWithApiTracingDisabled,
SpannerPoolKey.of(
ConnectionOptions.newBuilder()
.setUri("cloudspanner:/projects/p/instances/i/databases/d?enableApiTracing=false")
.setCredentials(NoCredentials.getInstance())
.build()));
assertEquals(
keyWithoutApiTracingConfig,
SpannerPoolKey.of(
ConnectionOptions.newBuilder()
.setUri("cloudspanner:/projects/p/instances/i/databases/d")
.setCredentials(NoCredentials.getInstance())
.build()));
}

@Test
public void testOpenTelemetry() {
SpannerPool pool = createSubjectAndMocks();
Expand Down
Loading