Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fcf3a0e

Browse files
committed
Add logging interceptor and error augmentation interceptor
1 parent bc647b1 commit fcf3a0e

File tree

3 files changed

+194
-50
lines changed

3 files changed

+194
-50
lines changed

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

Lines changed: 46 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@
2323
import com.google.api.gax.core.GaxProperties;
2424
import com.google.api.gax.grpc.GaxGrpcProperties;
2525
import com.google.api.gax.grpc.GrpcCallContext;
26-
import com.google.api.gax.grpc.GrpcTransportChannel;
2726
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
2827
import com.google.api.gax.longrunning.OperationFuture;
2928
import com.google.api.gax.rpc.ApiClientHeaderProvider;
30-
import com.google.api.gax.rpc.FixedTransportChannelProvider;
3129
import com.google.api.gax.rpc.HeaderProvider;
3230
import com.google.api.gax.rpc.ServerStream;
3331
import com.google.api.gax.rpc.StatusCode;
@@ -52,6 +50,7 @@
5250
import com.google.common.base.MoreObjects;
5351
import com.google.common.collect.ImmutableSet;
5452
import com.google.longrunning.GetOperationRequest;
53+
import com.google.longrunning.Operation;
5554
import com.google.protobuf.Empty;
5655
import com.google.protobuf.FieldMask;
5756
import com.google.spanner.admin.database.v1.CreateDatabaseMetadata;
@@ -83,10 +82,10 @@
8382
import com.google.spanner.v1.CreateSessionRequest;
8483
import com.google.spanner.v1.DeleteSessionRequest;
8584
import com.google.spanner.v1.ExecuteSqlRequest;
85+
import com.google.spanner.v1.PartialResultSet;
8686
import com.google.spanner.v1.PartitionQueryRequest;
8787
import com.google.spanner.v1.PartitionReadRequest;
8888
import com.google.spanner.v1.PartitionResponse;
89-
import com.google.spanner.v1.PartialResultSet;
9089
import com.google.spanner.v1.ReadRequest;
9190
import com.google.spanner.v1.RollbackRequest;
9291
import com.google.spanner.v1.Session;
@@ -100,8 +99,6 @@
10099
import java.util.concurrent.Future;
101100
import javax.annotation.Nullable;
102101

103-
import com.google.longrunning.Operation;
104-
105102
/** Implementation of Cloud Spanner remote calls using Gapic libraries. */
106103
public class GapicSpannerRpc implements SpannerRpc {
107104

@@ -145,9 +142,7 @@ public GapicSpannerRpc(SpannerOptions options) throws IOException {
145142
mergedHeaderProvider.getHeaders(),
146143
internalHeaderProviderBuilder.getResourceHeaderKey());
147144

148-
// TODO(pongad): make RPC logging work (formerly LoggingInterceptor)
149145
// TODO(pongad): add watchdog
150-
// TODO(pongad): make error augmentation work (formerly SpannerErrorInterceptor)
151146

152147
// TODO(hzyi): make this channelProvider configurable through SpannerOptions
153148
TransportChannelProvider channelProvider =
@@ -156,60 +151,61 @@ public GapicSpannerRpc(SpannerOptions options) throws IOException {
156151
.setEndpoint(options.getEndpoint())
157152
.setMaxInboundMessageSize(MAX_MESSAGE_SIZE)
158153
.setPoolSize(options.getNumChannels())
154+
.setInterceptorProvider(new SpannerInterceptorProvider())
159155
.build();
160156

161157
CredentialsProvider credentialsProvider =
162158
GrpcTransportOptions.setUpCredentialsProvider(options);
163-
159+
164160
// Disabling retry for now because spanner handles retry in SpannerImpl.
165161
// We will finally want to improve gax but for smooth transitioning we
166162
// preserve the retry in SpannerImpl
167163
try {
168164
// TODO: bump the version of gax and remove this try-catch block
169165
// applyToAllUnaryMethods does not throw exception in the latest version
170166
this.stub =
171-
GrpcSpannerStub.create(
172-
SpannerStubSettings.newBuilder()
173-
.setTransportChannelProvider(channelProvider)
174-
.setCredentialsProvider(credentialsProvider)
175-
.applyToAllUnaryMethods(
176-
new ApiFunction<UnaryCallSettings.Builder<?, ?>, Void>() {
177-
@Override
178-
public Void apply(UnaryCallSettings.Builder<?,?> builder) {
179-
builder.setRetryableCodes(ImmutableSet.<StatusCode.Code>of());
180-
return null;
181-
}
182-
})
183-
.build());
184-
185-
this.instanceStub =
186-
GrpcInstanceAdminStub.create(
187-
InstanceAdminStubSettings.newBuilder()
188-
.setTransportChannelProvider(channelProvider)
189-
.setCredentialsProvider(credentialsProvider)
190-
.applyToAllUnaryMethods(
191-
new ApiFunction<UnaryCallSettings.Builder<?, ?>, Void>() {
192-
@Override
193-
public Void apply(UnaryCallSettings.Builder<?,?> builder) {
194-
builder.setRetryableCodes(ImmutableSet.<StatusCode.Code>of());
195-
return null;
196-
}
197-
})
198-
.build());
199-
this.databaseStub =
200-
GrpcDatabaseAdminStub.create(
201-
DatabaseAdminStubSettings.newBuilder()
202-
.setTransportChannelProvider(channelProvider)
203-
.setCredentialsProvider(credentialsProvider)
204-
.applyToAllUnaryMethods(
205-
new ApiFunction<UnaryCallSettings.Builder<?, ?>, Void>() {
206-
@Override
207-
public Void apply(UnaryCallSettings.Builder<?,?> builder) {
208-
builder.setRetryableCodes(ImmutableSet.<StatusCode.Code>of());
209-
return null;
210-
}
211-
})
212-
.build());
167+
GrpcSpannerStub.create(
168+
SpannerStubSettings.newBuilder()
169+
.setTransportChannelProvider(channelProvider)
170+
.setCredentialsProvider(credentialsProvider)
171+
.applyToAllUnaryMethods(
172+
new ApiFunction<UnaryCallSettings.Builder<?, ?>, Void>() {
173+
@Override
174+
public Void apply(UnaryCallSettings.Builder<?, ?> builder) {
175+
builder.setRetryableCodes(ImmutableSet.<StatusCode.Code>of());
176+
return null;
177+
}
178+
})
179+
.build());
180+
181+
this.instanceStub =
182+
GrpcInstanceAdminStub.create(
183+
InstanceAdminStubSettings.newBuilder()
184+
.setTransportChannelProvider(channelProvider)
185+
.setCredentialsProvider(credentialsProvider)
186+
.applyToAllUnaryMethods(
187+
new ApiFunction<UnaryCallSettings.Builder<?, ?>, Void>() {
188+
@Override
189+
public Void apply(UnaryCallSettings.Builder<?, ?> builder) {
190+
builder.setRetryableCodes(ImmutableSet.<StatusCode.Code>of());
191+
return null;
192+
}
193+
})
194+
.build());
195+
this.databaseStub =
196+
GrpcDatabaseAdminStub.create(
197+
DatabaseAdminStubSettings.newBuilder()
198+
.setTransportChannelProvider(channelProvider)
199+
.setCredentialsProvider(credentialsProvider)
200+
.applyToAllUnaryMethods(
201+
new ApiFunction<UnaryCallSettings.Builder<?, ?>, Void>() {
202+
@Override
203+
public Void apply(UnaryCallSettings.Builder<?, ?> builder) {
204+
builder.setRetryableCodes(ImmutableSet.<StatusCode.Code>of());
205+
return null;
206+
}
207+
})
208+
.build());
213209
} catch (Exception e) {
214210
throw SpannerExceptionFactory.newSpannerException(e);
215211
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright 2018 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+
package com.google.cloud.spanner.spi.v1;
17+
18+
import io.grpc.CallOptions;
19+
import io.grpc.Channel;
20+
import io.grpc.ClientCall;
21+
import io.grpc.ClientInterceptor;
22+
import io.grpc.ForwardingClientCall;
23+
import io.grpc.ForwardingClientCallListener;
24+
import io.grpc.Metadata;
25+
import io.grpc.MethodDescriptor;
26+
import io.grpc.Status;
27+
import java.util.logging.Level;
28+
import java.util.logging.Logger;
29+
import javax.annotation.Nullable;
30+
31+
/** Adds logging to rpc calls */
32+
class LoggingInterceptor implements ClientInterceptor {
33+
34+
private final Logger logger;
35+
private final Level level;
36+
37+
LoggingInterceptor(Logger logger, Level level) {
38+
this.logger = logger;
39+
this.level = level;
40+
}
41+
42+
private class CallLogger {
43+
44+
private final MethodDescriptor<?, ?> method;
45+
46+
CallLogger(MethodDescriptor<?, ?> method) {
47+
this.method = method;
48+
}
49+
50+
void log(String message) {
51+
logger.log(
52+
level,
53+
"{0}[{1}]: {2}",
54+
new Object[] {
55+
method.getFullMethodName(), Integer.toHexString(System.identityHashCode(this)), message
56+
});
57+
}
58+
59+
void logfmt(String message, Object... params) {
60+
log(String.format(message, params));
61+
}
62+
}
63+
64+
@Override
65+
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
66+
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
67+
if (!logger.isLoggable(level)) {
68+
return next.newCall(method, callOptions);
69+
}
70+
71+
final CallLogger callLogger = new CallLogger(method);
72+
callLogger.log("Start");
73+
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(
74+
next.newCall(method, callOptions)) {
75+
@Override
76+
public void start(Listener<RespT> responseListener, Metadata headers) {
77+
super.start(
78+
new ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT>(
79+
responseListener) {
80+
@Override
81+
public void onMessage(RespT message) {
82+
callLogger.logfmt("Received:\n%s", message);
83+
super.onMessage(message);
84+
}
85+
86+
@Override
87+
public void onClose(Status status, Metadata trailers) {
88+
callLogger.logfmt("Closed with status %s and trailers %s", status, trailers);
89+
super.onClose(status, trailers);
90+
}
91+
},
92+
headers);
93+
}
94+
95+
@Override
96+
public void sendMessage(ReqT message) {
97+
callLogger.logfmt("Send:\n%s", message);
98+
super.sendMessage(message);
99+
}
100+
101+
@Override
102+
public void cancel(@Nullable String message, @Nullable Throwable cause) {
103+
callLogger.logfmt("Cancelled with message %s", message);
104+
super.cancel(message, cause);
105+
}
106+
};
107+
}
108+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2018 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+
package com.google.cloud.spanner.spi.v1;
17+
18+
import com.google.api.gax.grpc.GrpcInterceptorProvider;
19+
import com.google.common.collect.ImmutableList;
20+
import io.grpc.ClientInterceptor;
21+
import java.util.List;
22+
import java.util.logging.Level;
23+
import java.util.logging.Logger;
24+
25+
/**
26+
* For internal use only.
27+
*/
28+
class SpannerInterceptorProvider implements GrpcInterceptorProvider {
29+
30+
private static final List<ClientInterceptor> clientInterceptors =
31+
ImmutableList.of(
32+
new SpannerErrorInterceptor(),
33+
new LoggingInterceptor(Logger.getLogger(GrpcSpannerRpc.class.getName()), Level.FINER));
34+
35+
@Override
36+
public List<ClientInterceptor> getInterceptors() {
37+
return clientInterceptors;
38+
}
39+
40+
}

0 commit comments

Comments
 (0)