Skip to content

Commit dfc302d

Browse files
authored
Merge pull request #135 from SaiRepos/master
Added DebugClientInterceptor
2 parents 542f584 + 4d40e67 commit dfc302d

File tree

2 files changed

+197
-0
lines changed

2 files changed

+197
-0
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright (c) 2019, Salesforce.com, Inc.
3+
* All rights reserved.
4+
* Licensed under the BSD 3-Clause license.
5+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
8+
package com.salesforce.grpc.contrib.interceptor;
9+
10+
import java.util.Arrays;
11+
import java.util.EnumSet;
12+
13+
import org.slf4j.Logger;
14+
import org.slf4j.LoggerFactory;
15+
16+
import io.grpc.CallOptions;
17+
import io.grpc.Channel;
18+
import io.grpc.ClientCall;
19+
import io.grpc.ClientInterceptor;
20+
import io.grpc.ForwardingClientCall;
21+
import io.grpc.ForwardingClientCallListener;
22+
import io.grpc.Metadata;
23+
import io.grpc.MethodDescriptor;
24+
import io.grpc.Status;
25+
26+
/**
27+
* {@code DebugClientInterceptor} intercepts the both outbound requests and inbound response to
28+
* log the method name,status,headers and message as per given logging level.
29+
*
30+
*/
31+
public class DebugClientInterceptor implements ClientInterceptor {
32+
private final Logger logger = LoggerFactory.getLogger(DebugClientInterceptor.class);
33+
private static final String REQUEST = "Request";
34+
private static final String RESPONSE = "Response";
35+
36+
public enum Level {
37+
STATUS, HEADERS, MESSAGE
38+
}
39+
40+
private EnumSet<Level> levels = EnumSet.of(Level.STATUS);
41+
42+
public DebugClientInterceptor(Level... levels) {
43+
this.levels = EnumSet.copyOf(Arrays.asList(levels));
44+
}
45+
46+
@Override
47+
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method,
48+
CallOptions callOptions, Channel next) {
49+
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
50+
@Override
51+
public void sendMessage(ReqT message) {
52+
logMessage(REQUEST, message);
53+
super.sendMessage(message);
54+
}
55+
56+
@Override
57+
public void start(Listener<RespT> responseListener, Metadata headers) {
58+
logMethod(method);
59+
logHeaders(REQUEST, headers);
60+
super.start(
61+
new ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT>(responseListener) {
62+
63+
@Override
64+
public void onClose(Status status, Metadata trailers) {
65+
logStatus(status, method);
66+
super.onClose(status, trailers);
67+
}
68+
69+
@Override
70+
public void onHeaders(Metadata headers) {
71+
logHeaders(RESPONSE, headers);
72+
super.onHeaders(headers);
73+
}
74+
75+
@Override
76+
public void onMessage(RespT message) {
77+
logMessage(RESPONSE, message);
78+
super.onMessage(message);
79+
}
80+
}, headers);
81+
}
82+
};
83+
}
84+
85+
private <ReqT, RespT> void logMethod(MethodDescriptor<ReqT, RespT> method) {
86+
if (levels.contains(Level.STATUS)) {
87+
log(String.format("%s path : %s", REQUEST, method.getFullMethodName()));
88+
}
89+
}
90+
91+
private <ReqT, RespT> void logStatus(Status status, MethodDescriptor<ReqT, RespT> method) {
92+
if (levels.contains(Level.STATUS)) {
93+
log(String.format("%s status: %s %s for path : %s", RESPONSE, status.getCode().value(), status.getCode(),
94+
method.getFullMethodName()));
95+
}
96+
}
97+
98+
private void logHeaders(String type, Metadata headers) {
99+
if (levels.contains(Level.HEADERS)) {
100+
log(String.format("%s headers : %s", type, headers));
101+
}
102+
}
103+
104+
private <RespT> void logMessage(String type, RespT message) {
105+
if (levels.contains(Level.MESSAGE)) {
106+
log(String.format("%s message : %s", type, message));
107+
}
108+
}
109+
110+
protected void log(String logmessage) {
111+
logger.debug(logmessage);
112+
}
113+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (c) 2019, Salesforce.com, Inc.
3+
* All rights reserved.
4+
* Licensed under the BSD 3-Clause license.
5+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
8+
package com.salesforce.grpc.contrib.interceptor;
9+
10+
import static org.assertj.core.api.Assertions.assertThat;
11+
12+
import java.util.LinkedList;
13+
14+
import org.junit.Rule;
15+
import org.junit.Test;
16+
17+
import com.salesforce.grpc.contrib.GreeterGrpc;
18+
import com.salesforce.grpc.contrib.HelloRequest;
19+
import com.salesforce.grpc.contrib.HelloResponse;
20+
import com.salesforce.grpc.contrib.interceptor.DebugClientInterceptor.Level;
21+
22+
import io.grpc.ForwardingServerCall.SimpleForwardingServerCall;
23+
import io.grpc.Metadata;
24+
import io.grpc.ServerCall;
25+
import io.grpc.ServerCall.Listener;
26+
import io.grpc.ServerCallHandler;
27+
import io.grpc.ServerInterceptor;
28+
import io.grpc.ServerInterceptors;
29+
import io.grpc.stub.MetadataUtils;
30+
import io.grpc.stub.StreamObserver;
31+
import io.grpc.testing.GrpcServerRule;
32+
33+
public class DebugClientInterceptorTest {
34+
35+
@Rule
36+
public final GrpcServerRule serverRule = new GrpcServerRule().directExecutor();
37+
38+
private GreeterGrpc.GreeterImplBase svc = new GreeterGrpc.GreeterImplBase() {
39+
@Override
40+
public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
41+
responseObserver.onNext(HelloResponse.newBuilder().setMessage("Hello " + request.getName()).build());
42+
responseObserver.onCompleted();
43+
}
44+
};
45+
46+
@Test
47+
public void clientStopwatchWorks() {
48+
LinkedList<String> logs = new LinkedList<String>();
49+
Metadata requestHeaders = new Metadata();
50+
requestHeaders.put(Metadata.Key.of("request_header", Metadata.ASCII_STRING_MARSHALLER), "request_header_value");
51+
//Setup
52+
serverRule.getServiceRegistry().addService(ServerInterceptors.intercept(svc, new ServerInterceptor() {
53+
@Override
54+
public <ReqT, RespT> Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers,
55+
ServerCallHandler<ReqT, RespT> next) {
56+
return next.startCall(new SimpleForwardingServerCall<ReqT, RespT>(call) {
57+
@Override
58+
public void sendHeaders(Metadata responseHeaders) {
59+
responseHeaders.put(Metadata.Key.of("response_header", Metadata.ASCII_STRING_MARSHALLER), "response_header_value");
60+
super.sendHeaders(responseHeaders);
61+
}
62+
}, headers);
63+
}
64+
}));
65+
GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc
66+
.newBlockingStub(serverRule.getChannel())
67+
.withInterceptors(new DebugClientInterceptor(Level.STATUS, Level.HEADERS, Level.MESSAGE) {
68+
@Override
69+
protected void log(String message) {
70+
logs.add(message);
71+
}
72+
73+
}, MetadataUtils.newAttachHeadersInterceptor(requestHeaders));
74+
75+
stub.sayHello(HelloRequest.newBuilder().setName("World").build());
76+
assertThat(logs.poll()).contains("SayHello"); //request method name
77+
assertThat(logs.poll()).contains(requestHeaders.toString()); //request header value
78+
assertThat(logs.poll()).contains("World"); //request message
79+
assertThat(logs.poll()).contains("response_header_value"); //response header
80+
assertThat(logs.poll()).contains("Hello World"); //response message
81+
assertThat(logs.poll()).contains("0 OK"); //response status
82+
}
83+
84+
}

0 commit comments

Comments
 (0)