Skip to content

Commit 244d6a8

Browse files
authored
feat: Open telemetry implementation (#2770)
This PR adds support for [OpenTelemetry](https://opentelemetry.io/) Instrumentation for Traces and Metrics. Add dependency for [OpenTelemetrySDK](https://opentelemetry.io/docs/instrumentation/java/manual/#initialize-the-sdk) and required [exporters](https://opentelemetry.io/docs/instrumentation/java/exporters/). Create OpenTelemetry object with required MeterProvider and TracerProvider exporter . Inject OpenTelemetry object via SpannerOptions or register as Global ` OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) .setTracerProvider(tracerProvider) .setMeterProvider(sdkMeterProvider) .build; SpannerOptions options = SpannerOptions.newBuilder().setOpenTelemetry(openTelemetry).build(); ` By default, OpenTelemetry traces are not enabled. To enable OpenTelemetry traces , call `SpannerOptions.enableOpenTelemetryTraces()` in startup of your application. Enabling OpenTelemetry traces will disable OpenCensus traces. Both OpenCensus and OpenTelemetry traces can not be enabled at the same time.
1 parent e2b7ae6 commit 244d6a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2719
-489
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ nosetests.xml
2222
.settings
2323
.DS_Store
2424
.classpath
25+
.tool-versions
2526

2627
# Built documentation
2728
docs/

google-cloud-spanner/clirr-ignored-differences.xml

+6-1
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,6 @@
426426
<className>com/google/cloud/spanner/connection/Connection</className>
427427
<method>void rollbackToSavepoint(java.lang.String)</method>
428428
</difference>
429-
430429
<!-- Delay start transaction -->
431430
<difference>
432431
<differenceType>7012</differenceType>
@@ -540,6 +539,12 @@
540539
<className>com/google/cloud/spanner/Dialect</className>
541540
<method>java.lang.String getDefaultSchema()</method>
542541
</difference>
542+
<difference>
543+
<differenceType>7005</differenceType>
544+
<className>com/google/cloud/spanner/PartitionedDmlTransaction</className>
545+
<method>void setSpan(io.opencensus.trace.Span)</method>
546+
<to>void setSpan(com.google.cloud.spanner.ISpan)</to>
547+
</difference>
543548

544549
<!-- Added DirectedReadOptions -->
545550
<difference>

google-cloud-spanner/pom.xml

+29-3
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,14 @@
247247
<artifactId>opencensus-impl</artifactId>
248248
<scope>test</scope>
249249
</dependency>
250+
<dependency>
251+
<groupId>io.opentelemetry</groupId>
252+
<artifactId>opentelemetry-api</artifactId>
253+
</dependency>
254+
<dependency>
255+
<groupId>io.opentelemetry</groupId>
256+
<artifactId>opentelemetry-context</artifactId>
257+
</dependency>
250258
<dependency>
251259
<groupId>com.google.auth</groupId>
252260
<artifactId>google-auth-library-oauth2-http</artifactId>
@@ -393,7 +401,6 @@
393401
<version>2.2</version>
394402
<scope>test</scope>
395403
</dependency>
396-
397404
<!-- Benchmarking dependencies -->
398405
<dependency>
399406
<groupId>org.openjdk.jmh</groupId>
@@ -407,9 +414,28 @@
407414
<version>1.37</version>
408415
<scope>test</scope>
409416
</dependency>
410-
417+
<!-- OpenTelemetry test dependencies -->
418+
<dependency>
419+
<groupId>io.opentelemetry</groupId>
420+
<artifactId>opentelemetry-sdk</artifactId>
421+
<scope>test</scope>
422+
</dependency>
423+
<dependency>
424+
<groupId>io.opentelemetry</groupId>
425+
<artifactId>opentelemetry-sdk-metrics</artifactId>
426+
<scope>test</scope>
427+
</dependency>
428+
<dependency>
429+
<groupId>io.opentelemetry</groupId>
430+
<artifactId>opentelemetry-sdk-trace</artifactId>
431+
<scope>test</scope>
432+
</dependency>
433+
<dependency>
434+
<groupId>io.opentelemetry</groupId>
435+
<artifactId>opentelemetry-sdk-testing</artifactId>
436+
<scope>test</scope>
437+
</dependency>
411438
</dependencies>
412-
413439
<profiles>
414440
<profile>
415441
<id>java9</id>

google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractReadContext.java

+21-9
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import com.google.cloud.spanner.spi.v1.SpannerRpc;
4040
import com.google.common.annotations.VisibleForTesting;
4141
import com.google.common.base.Preconditions;
42+
import com.google.common.collect.ImmutableMap;
4243
import com.google.common.util.concurrent.MoreExecutors;
4344
import com.google.protobuf.ByteString;
4445
import com.google.spanner.v1.BeginTransactionRequest;
@@ -53,8 +54,6 @@
5354
import com.google.spanner.v1.Transaction;
5455
import com.google.spanner.v1.TransactionOptions;
5556
import com.google.spanner.v1.TransactionSelector;
56-
import io.opencensus.trace.Span;
57-
import io.opencensus.trace.Tracing;
5857
import java.util.Map;
5958
import java.util.concurrent.atomic.AtomicLong;
6059
import javax.annotation.Nullable;
@@ -70,7 +69,8 @@ abstract class AbstractReadContext
7069
abstract static class Builder<B extends Builder<?, T>, T extends AbstractReadContext> {
7170
private SessionImpl session;
7271
private SpannerRpc rpc;
73-
private Span span = Tracing.getTracer().getCurrentSpan();
72+
private ISpan span;
73+
private TraceWrapper tracer;
7474
private int defaultPrefetchChunks = SpannerOptions.Builder.DEFAULT_PREFETCH_CHUNKS;
7575
private QueryOptions defaultQueryOptions = SpannerOptions.Builder.DEFAULT_QUERY_OPTIONS;
7676
private DirectedReadOptions defaultDirectedReadOption;
@@ -94,11 +94,16 @@ B setRpc(SpannerRpc rpc) {
9494
return self();
9595
}
9696

97-
B setSpan(Span span) {
97+
B setSpan(ISpan span) {
9898
this.span = span;
9999
return self();
100100
}
101101

102+
B setTracer(TraceWrapper tracer) {
103+
this.tracer = tracer;
104+
return self();
105+
}
106+
102107
B setDefaultPrefetchChunks(int defaultPrefetchChunks) {
103108
this.defaultPrefetchChunks = defaultPrefetchChunks;
104109
return self();
@@ -389,9 +394,12 @@ void initTransaction() {
389394
}
390395
transactionId = transaction.getId();
391396
span.addAnnotation(
392-
"Transaction Creation Done", TraceUtil.getTransactionAnnotations(transaction));
397+
"Transaction Creation Done",
398+
ImmutableMap.of(
399+
"Id", transaction.getId().toStringUtf8(), "Timestamp", timestamp.toString()));
400+
393401
} catch (SpannerException e) {
394-
span.addAnnotation("Transaction Creation Failed", TraceUtil.getExceptionAnnotations(e));
402+
span.addAnnotation("Transaction Creation Failed", e);
395403
throw e;
396404
}
397405
}
@@ -402,7 +410,8 @@ void initTransaction() {
402410
final SessionImpl session;
403411
final SpannerRpc rpc;
404412
final ExecutorProvider executorProvider;
405-
Span span;
413+
ISpan span;
414+
TraceWrapper tracer;
406415
private final int defaultPrefetchChunks;
407416
private final QueryOptions defaultQueryOptions;
408417

@@ -435,10 +444,11 @@ void initTransaction() {
435444
this.span = builder.span;
436445
this.executorProvider = builder.executorProvider;
437446
this.clock = builder.clock;
447+
this.tracer = builder.tracer;
438448
}
439449

440450
@Override
441-
public void setSpan(Span span) {
451+
public void setSpan(ISpan span) {
442452
this.span = span;
443453
}
444454

@@ -692,6 +702,7 @@ ResultSet executeQueryInternalWithOptions(
692702
MAX_BUFFERED_CHUNKS,
693703
SpannerImpl.QUERY,
694704
span,
705+
tracer,
695706
rpc.getExecuteQueryRetrySettings(),
696707
rpc.getExecuteQueryRetryableCodes()) {
697708
@Override
@@ -752,7 +763,7 @@ public final void invalidate() {
752763

753764
@Override
754765
public void close() {
755-
span.end(TraceUtil.END_SPAN_OPTIONS);
766+
span.end();
756767
synchronized (lock) {
757768
isClosed = true;
758769
}
@@ -837,6 +848,7 @@ ResultSet readInternalWithOptions(
837848
MAX_BUFFERED_CHUNKS,
838849
SpannerImpl.READ,
839850
span,
851+
tracer,
840852
rpc.getReadRetrySettings(),
841853
rpc.getReadRetryableCodes()) {
842854
@Override

google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java

+17-29
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import com.google.common.annotations.VisibleForTesting;
3838
import com.google.common.base.Preconditions;
3939
import com.google.common.collect.AbstractIterator;
40-
import com.google.common.collect.ImmutableMap;
4140
import com.google.common.collect.Lists;
4241
import com.google.common.io.CharSource;
4342
import com.google.common.util.concurrent.Uninterruptibles;
@@ -53,11 +52,6 @@
5352
import com.google.spanner.v1.Transaction;
5453
import com.google.spanner.v1.TypeCode;
5554
import io.grpc.Context;
56-
import io.opencensus.common.Scope;
57-
import io.opencensus.trace.AttributeValue;
58-
import io.opencensus.trace.Span;
59-
import io.opencensus.trace.Tracer;
60-
import io.opencensus.trace.Tracing;
6155
import java.io.IOException;
6256
import java.io.Serializable;
6357
import java.math.BigDecimal;
@@ -87,7 +81,6 @@
8781

8882
/** Implementation of {@link ResultSet}. */
8983
abstract class AbstractResultSet<R> extends AbstractStructReader implements ResultSet {
90-
private static final Tracer tracer = Tracing.getTracer();
9184
private static final com.google.protobuf.Value NULL_VALUE =
9285
com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build();
9386

@@ -1206,7 +1199,8 @@ abstract static class ResumableStreamIterator extends AbstractIterator<PartialRe
12061199
private final BackOff backOff;
12071200
private final LinkedList<PartialResultSet> buffer = new LinkedList<>();
12081201
private final int maxBufferSize;
1209-
private final Span span;
1202+
private final ISpan span;
1203+
private final TraceWrapper tracer;
12101204
private CloseableIterator<PartialResultSet> stream;
12111205
private ByteString resumeToken;
12121206
private boolean finished;
@@ -1220,12 +1214,14 @@ abstract static class ResumableStreamIterator extends AbstractIterator<PartialRe
12201214
protected ResumableStreamIterator(
12211215
int maxBufferSize,
12221216
String streamName,
1223-
Span parent,
1217+
ISpan parent,
1218+
TraceWrapper tracer,
12241219
RetrySettings streamingRetrySettings,
12251220
Set<Code> retryableCodes) {
12261221
checkArgument(maxBufferSize >= 0);
12271222
this.maxBufferSize = maxBufferSize;
1228-
this.span = tracer.spanBuilderWithExplicitParent(streamName, parent).startSpan();
1223+
this.tracer = tracer;
1224+
this.span = tracer.spanBuilderWithExplicitParent(streamName, parent);
12291225
this.streamingRetrySettings = Preconditions.checkNotNull(streamingRetrySettings);
12301226
this.retryableCodes = Preconditions.checkNotNull(retryableCodes);
12311227
this.backOff = newBackOff();
@@ -1281,11 +1277,7 @@ private static long nextBackOffMillis(BackOff backoff) throws SpannerException {
12811277
}
12821278

12831279
private void backoffSleep(Context context, long backoffMillis) throws SpannerException {
1284-
tracer
1285-
.getCurrentSpan()
1286-
.addAnnotation(
1287-
"Backing off",
1288-
ImmutableMap.of("Delay", AttributeValue.longAttributeValue(backoffMillis)));
1280+
tracer.getCurrentSpan().addAnnotation("Backing off", "Delay", backoffMillis);
12891281
final CountDownLatch latch = new CountDownLatch(1);
12901282
final Context.CancellationListener listener =
12911283
ignored -> {
@@ -1325,7 +1317,7 @@ public void execute(Runnable command) {
13251317
public void close(@Nullable String message) {
13261318
if (stream != null) {
13271319
stream.close(message);
1328-
span.end(TraceUtil.END_SPAN_OPTIONS);
1320+
span.end();
13291321
stream = null;
13301322
}
13311323
}
@@ -1343,11 +1335,9 @@ protected PartialResultSet computeNext() {
13431335
if (stream == null) {
13441336
span.addAnnotation(
13451337
"Starting/Resuming stream",
1346-
ImmutableMap.of(
1347-
"ResumeToken",
1348-
AttributeValue.stringAttributeValue(
1349-
resumeToken == null ? "null" : resumeToken.toStringUtf8())));
1350-
try (Scope s = tracer.withSpan(span)) {
1338+
"ResumeToken",
1339+
resumeToken == null ? "null" : resumeToken.toStringUtf8());
1340+
try (IScope scope = tracer.withSpan(span)) {
13511341
// When start a new stream set the Span as current to make the gRPC Span a child of
13521342
// this Span.
13531343
stream = checkNotNull(startStream(resumeToken));
@@ -1387,17 +1377,15 @@ protected PartialResultSet computeNext() {
13871377
}
13881378
} catch (SpannerException spannerException) {
13891379
if (safeToRetry && isRetryable(spannerException)) {
1390-
span.addAnnotation(
1391-
"Stream broken. Safe to retry",
1392-
TraceUtil.getExceptionAnnotations(spannerException));
1380+
span.addAnnotation("Stream broken. Safe to retry", spannerException);
13931381
logger.log(Level.FINE, "Retryable exception, will sleep and retry", spannerException);
13941382
// Truncate any items in the buffer before the last retry token.
13951383
while (!buffer.isEmpty() && buffer.getLast().getResumeToken().isEmpty()) {
13961384
buffer.removeLast();
13971385
}
13981386
assert buffer.isEmpty() || buffer.getLast().getResumeToken().equals(resumeToken);
13991387
stream = null;
1400-
try (Scope s = tracer.withSpan(span)) {
1388+
try (IScope s = tracer.withSpan(span)) {
14011389
long delay = spannerException.getRetryDelayInMillis();
14021390
if (delay != -1) {
14031391
backoffSleep(context, delay);
@@ -1408,12 +1396,12 @@ protected PartialResultSet computeNext() {
14081396

14091397
continue;
14101398
}
1411-
span.addAnnotation("Stream broken. Not safe to retry");
1412-
TraceUtil.setWithFailure(span, spannerException);
1399+
span.addAnnotation("Stream broken. Not safe to retry", spannerException);
1400+
span.setStatus(spannerException);
14131401
throw spannerException;
14141402
} catch (RuntimeException e) {
1415-
span.addAnnotation("Stream broken. Not safe to retry");
1416-
TraceUtil.setWithFailure(span, e);
1403+
span.addAnnotation("Stream broken. Not safe to retry", e);
1404+
span.setStatus(e);
14171405
throw e;
14181406
}
14191407
}

google-cloud-spanner/src/main/java/com/google/cloud/spanner/AsyncTransactionManagerImpl.java

+3-7
Original file line numberDiff line numberDiff line change
@@ -28,31 +28,27 @@
2828
import com.google.common.base.MoreObjects;
2929
import com.google.common.base.Preconditions;
3030
import com.google.common.util.concurrent.MoreExecutors;
31-
import io.opencensus.trace.Span;
32-
import io.opencensus.trace.Tracer;
33-
import io.opencensus.trace.Tracing;
3431

3532
/** Implementation of {@link AsyncTransactionManager}. */
3633
final class AsyncTransactionManagerImpl
3734
implements CommittableAsyncTransactionManager, SessionTransaction {
38-
private static final Tracer tracer = Tracing.getTracer();
3935

4036
private final SessionImpl session;
41-
private Span span;
37+
private ISpan span;
4238
private final Options options;
4339

4440
private TransactionRunnerImpl.TransactionContextImpl txn;
4541
private TransactionState txnState;
4642
private final SettableApiFuture<CommitResponse> commitResponse = SettableApiFuture.create();
4743

48-
AsyncTransactionManagerImpl(SessionImpl session, Span span, TransactionOption... options) {
44+
AsyncTransactionManagerImpl(SessionImpl session, ISpan span, TransactionOption... options) {
4945
this.session = session;
5046
this.span = span;
5147
this.options = Options.fromTransactionOptions(options);
5248
}
5349

5450
@Override
55-
public void setSpan(Span span) {
51+
public void setSpan(ISpan span) {
5652
this.span = span;
5753
}
5854

0 commit comments

Comments
 (0)