Skip to content

Commit d84aae4

Browse files
committed
feat: Adding TraceUtil interface and its implementation to enable Tracing controls via DatastoreOptions (#1431)
* Adding EnabledTraceUtil, DisabledTraceUtil and TraceUtilTest * Annotating DatastoreOpenTelemetryOptions to be transient as they're not serializable * Adding google-auth-library-credentials dependency due to https://github.com/googleapis/java-datastore/actions/runs/8944472794/job/24571458116?pr=1431
1 parent d478009 commit d84aae4

File tree

10 files changed

+938
-0
lines changed

10 files changed

+938
-0
lines changed

google-cloud-datastore/pom.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
</parent>
1717
<properties>
1818
<site.installationModule>google-cloud-datastore</site.installationModule>
19+
<opentelemetry.version>1.37.0</opentelemetry.version>
1920
</properties>
2021
<dependencies>
2122
<dependency>
@@ -38,6 +39,10 @@
3839
<groupId>com.google.cloud.datastore</groupId>
3940
<artifactId>datastore-v1-proto-client</artifactId>
4041
</dependency>
42+
<dependency>
43+
<groupId>com.google.auth</groupId>
44+
<artifactId>google-auth-library-credentials</artifactId>
45+
</dependency>
4146
<dependency>
4247
<groupId>io.grpc</groupId>
4348
<artifactId>grpc-api</artifactId>
@@ -111,6 +116,19 @@
111116
<artifactId>jsr305</artifactId>
112117
</dependency>
113118

119+
<!-- OpenTelemetry -->
120+
<dependency>
121+
<groupId>io.opentelemetry</groupId>
122+
<artifactId>opentelemetry-api</artifactId>
123+
<version>${opentelemetry.version}</version>
124+
</dependency>
125+
<dependency>
126+
<groupId>io.opentelemetry</groupId>
127+
<artifactId>opentelemetry-context</artifactId>
128+
<version>${opentelemetry.version}</version>
129+
</dependency>
130+
<!-- END OpenTelemetry -->
131+
114132
<!-- Test dependencies -->
115133
<dependency>
116134
<groupId>${project.groupId}</groupId>
@@ -160,6 +178,12 @@
160178
<version>1.4.3</version>
161179
<scope>test</scope>
162180
</dependency>
181+
<dependency>
182+
<groupId>io.opentelemetry</groupId>
183+
<artifactId>opentelemetry-sdk</artifactId>
184+
<version>${opentelemetry.version}</version>
185+
<scope>test</scope>
186+
</dependency>
163187
</dependencies>
164188

165189
<build>
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.datastore;
18+
19+
import io.opentelemetry.api.OpenTelemetry;
20+
import javax.annotation.Nonnull;
21+
import javax.annotation.Nullable;
22+
23+
public class DatastoreOpenTelemetryOptions {
24+
private final boolean enabled;
25+
private final @Nullable OpenTelemetry openTelemetry;
26+
27+
DatastoreOpenTelemetryOptions(Builder builder) {
28+
this.enabled = builder.enabled;
29+
this.openTelemetry = builder.openTelemetry;
30+
}
31+
32+
public boolean isEnabled() {
33+
return enabled;
34+
}
35+
36+
@Nullable
37+
public OpenTelemetry getOpenTelemetry() {
38+
return openTelemetry;
39+
}
40+
41+
@Nonnull
42+
public DatastoreOpenTelemetryOptions.Builder toBuilder() {
43+
return new DatastoreOpenTelemetryOptions.Builder(this);
44+
}
45+
46+
@Nonnull
47+
public static DatastoreOpenTelemetryOptions.Builder newBuilder() {
48+
return new DatastoreOpenTelemetryOptions.Builder();
49+
}
50+
51+
public static class Builder {
52+
53+
private boolean enabled;
54+
55+
@Nullable private OpenTelemetry openTelemetry;
56+
57+
private Builder() {
58+
enabled = false;
59+
openTelemetry = null;
60+
}
61+
62+
private Builder(DatastoreOpenTelemetryOptions options) {
63+
this.enabled = options.enabled;
64+
this.openTelemetry = options.openTelemetry;
65+
}
66+
67+
@Nonnull
68+
public DatastoreOpenTelemetryOptions build() {
69+
return new DatastoreOpenTelemetryOptions(this);
70+
}
71+
72+
/**
73+
* Sets whether tracing should be enabled.
74+
*
75+
* @param enabled Whether tracing should be enabled.
76+
*/
77+
@Nonnull
78+
public DatastoreOpenTelemetryOptions.Builder setTracingEnabled(boolean enabled) {
79+
this.enabled = enabled;
80+
return this;
81+
}
82+
83+
/**
84+
* Sets the {@link OpenTelemetry} to use with this Datastore instance. If telemetry collection
85+
* is enabled, but an `OpenTelemetry` is not provided, the Datastore SDK will attempt to use the
86+
* `GlobalOpenTelemetry`.
87+
*
88+
* @param openTelemetry The OpenTelemetry that should be used by this Datastore instance.
89+
*/
90+
@Nonnull
91+
public DatastoreOpenTelemetryOptions.Builder setOpenTelemetry(
92+
@Nonnull OpenTelemetry openTelemetry) {
93+
this.openTelemetry = openTelemetry;
94+
return this;
95+
}
96+
}
97+
}

google-cloud-datastore/src/main/java/com/google/cloud/datastore/DatastoreOptions.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static com.google.cloud.datastore.Validator.validateNamespace;
2020

21+
import com.google.api.core.BetaApi;
2122
import com.google.cloud.ServiceDefaults;
2223
import com.google.cloud.ServiceOptions;
2324
import com.google.cloud.ServiceRpc;
@@ -31,6 +32,8 @@
3132
import java.lang.reflect.Method;
3233
import java.util.Objects;
3334
import java.util.Set;
35+
import javax.annotation.Nonnull;
36+
import javax.annotation.Nullable;
3437

3538
public class DatastoreOptions extends ServiceOptions<Datastore, DatastoreOptions> {
3639

@@ -43,6 +46,9 @@ public class DatastoreOptions extends ServiceOptions<Datastore, DatastoreOptions
4346
private final String namespace;
4447
private final String databaseId;
4548

49+
private final transient @Nonnull DatastoreOpenTelemetryOptions openTelemetryOptions;
50+
private final transient @Nonnull com.google.cloud.datastore.telemetry.TraceUtil traceUtil;
51+
4652
public static class DefaultDatastoreFactory implements DatastoreFactory {
4753

4854
private static final DatastoreFactory INSTANCE = new DefaultDatastoreFactory();
@@ -63,17 +69,31 @@ public ServiceRpc create(DatastoreOptions options) {
6369
}
6470
}
6571

72+
@Nonnull
73+
com.google.cloud.datastore.telemetry.TraceUtil getTraceUtil() {
74+
return traceUtil;
75+
}
76+
77+
@BetaApi
78+
@Nonnull
79+
public DatastoreOpenTelemetryOptions getOpenTelemetryOptions() {
80+
return openTelemetryOptions;
81+
}
82+
6683
public static class Builder extends ServiceOptions.Builder<Datastore, DatastoreOptions, Builder> {
6784

6885
private String namespace;
6986
private String databaseId;
7087

88+
@Nullable private DatastoreOpenTelemetryOptions openTelemetryOptions = null;
89+
7190
private Builder() {}
7291

7392
private Builder(DatastoreOptions options) {
7493
super(options);
7594
namespace = options.namespace;
7695
databaseId = options.databaseId;
96+
this.openTelemetryOptions = options.openTelemetryOptions;
7797
}
7898

7999
@Override
@@ -100,10 +120,30 @@ public Builder setDatabaseId(String databaseId) {
100120
this.databaseId = databaseId;
101121
return this;
102122
}
123+
124+
/**
125+
* Sets the {@link DatastoreOpenTelemetryOptions} to be used for this Firestore instance.
126+
*
127+
* @param openTelemetryOptions The `DatastoreOpenTelemetryOptions` to use.
128+
*/
129+
@BetaApi
130+
@Nonnull
131+
public Builder setOpenTelemetryOptions(
132+
@Nonnull DatastoreOpenTelemetryOptions openTelemetryOptions) {
133+
this.openTelemetryOptions = openTelemetryOptions;
134+
return this;
135+
}
103136
}
104137

105138
private DatastoreOptions(Builder builder) {
106139
super(DatastoreFactory.class, DatastoreRpcFactory.class, builder, new DatastoreDefaults());
140+
141+
this.openTelemetryOptions =
142+
builder.openTelemetryOptions != null
143+
? builder.openTelemetryOptions
144+
: DatastoreOpenTelemetryOptions.newBuilder().build();
145+
this.traceUtil = com.google.cloud.datastore.telemetry.TraceUtil.getInstance(this);
146+
107147
namespace = MoreObjects.firstNonNull(builder.namespace, defaultNamespace());
108148
databaseId = MoreObjects.firstNonNull(builder.databaseId, DEFAULT_DATABASE_ID);
109149
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.datastore.telemetry;
18+
19+
import com.google.api.core.ApiFunction;
20+
import com.google.api.core.ApiFuture;
21+
import com.google.api.core.InternalApi;
22+
import io.grpc.ManagedChannelBuilder;
23+
import java.util.Map;
24+
import javax.annotation.Nonnull;
25+
import javax.annotation.Nullable;
26+
27+
/**
28+
* Tracing utility implementation, used to stub out tracing instrumentation when tracing is
29+
* disabled.
30+
*/
31+
@InternalApi
32+
public class DisabledTraceUtil implements TraceUtil {
33+
34+
static class Span implements TraceUtil.Span {
35+
@Override
36+
public void end() {}
37+
38+
@Override
39+
public void end(Throwable error) {}
40+
41+
@Override
42+
public <T> void endAtFuture(ApiFuture<T> futureValue) {}
43+
44+
@Override
45+
public TraceUtil.Span addEvent(String name) {
46+
return this;
47+
}
48+
49+
@Override
50+
public TraceUtil.Span addEvent(String name, Map<String, Object> attributes) {
51+
return this;
52+
}
53+
54+
@Override
55+
public TraceUtil.Span setAttribute(String key, int value) {
56+
return this;
57+
}
58+
59+
@Override
60+
public TraceUtil.Span setAttribute(String key, String value) {
61+
return this;
62+
}
63+
64+
@Override
65+
public Scope makeCurrent() {
66+
return new Scope();
67+
}
68+
}
69+
70+
static class Context implements TraceUtil.Context {
71+
@Override
72+
public Scope makeCurrent() {
73+
return new Scope();
74+
}
75+
}
76+
77+
static class Scope implements TraceUtil.Scope {
78+
@Override
79+
public void close() {}
80+
}
81+
82+
@Nullable
83+
@Override
84+
public ApiFunction<ManagedChannelBuilder, ManagedChannelBuilder> getChannelConfigurator() {
85+
return null;
86+
}
87+
88+
@Override
89+
public Span startSpan(String spanName) {
90+
return new Span();
91+
}
92+
93+
@Override
94+
public TraceUtil.Span startSpan(String spanName, TraceUtil.Context parent) {
95+
return new Span();
96+
}
97+
98+
@Nonnull
99+
@Override
100+
public TraceUtil.Span currentSpan() {
101+
return new Span();
102+
}
103+
104+
@Nonnull
105+
@Override
106+
public TraceUtil.Context currentContext() {
107+
return new Context();
108+
}
109+
}

0 commit comments

Comments
 (0)