因为system没有完善log的输出,平时排查线上问题API的request和response太麻烦了,又不想自己加个AOP,就想重写grpc的interceptor试试,主要是为了输出log.
这个项目只有com.fasterxml.jackson工具包,就用ObjectMapper来format request和response。
ObjectUtils.getDisplayString()和toString()差不多的,但是我这个项目接收的response会存在没有toString方法的情况,我还是用ObjectUtils.getDisplayString()避免一些error的情况。
@Log4j2
@GrpcGlobalClientInterceptor
@GrpcGlobalServerInterceptor
public class LogGrpcInterceptor implements ClientInterceptor, ServerInterceptor {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final String TRACE_ID = "traceId";
// 链路追踪参数traceId
private static final Metadata.Key<String> TRACE = Metadata.Key.of(TRACE_ID, Metadata.ASCII_STRING_MARSHALLER);
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
val uuid = UUID.randomUUID();
val methodName = method.getFullMethodName();
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(
next.newCall(method, callOptions)) {
@Override
public void sendMessage(ReqT message) {
try {
log.info("CLIENT GRPC start - [{}] , method: [{}] , request: \n{{}}", uuid, methodName, OBJECT_MAPPER.writeValueAsString(ObjectUtils.getDisplayString(message)));
} catch (JsonProcessingException e) {
log.error("CLIENT GRPC-FORMAT start - [{}] , method: [{}] ", uuid, methodName);
}
super.sendMessage(message);
}
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
val start = Instant.now();
// 客户端传递链路追中数据,将数据放到headers中
if (ObjectUtils.isEmpty(headers.get(TRACE))) {
headers.put(TRACE, uuid.toString());
}
Listener<RespT> listener = new ForwardingClientCallListener<RespT>() {
@Override
protected Listener<RespT> delegate() {
return responseListener;
}
@Override
public void onMessage(RespT message) {
try {
log.info("CLIENT GRPC end - [{}] , method: [{}] , response: \n{ {} }", uuid, methodName, OBJECT_MAPPER.writeValueAsString(ObjectUtils.getDisplayString(message)));
} catch (JsonProcessingException e) {
log.error("CLIENT GRPC-FORMAT end - [{}] , method: [{}] ", uuid, methodName);
}
super.onMessage(message);
}
@Override
public void onClose(Status status, Metadata trailers) {
val now = Instant.now();
super.onClose(status, trailers);
log.info("GRPC end - [{}] {} - end: {}, {}: {}, desc: {}, msg: \"{}\", duration: {}ms"
, uuid
, methodName
, now.atOffset(ZoneOffset.ofHours(8))
, status.isOk() ? "OK" : "Error"
, status.getCode().name()
, status.getDescription()
, (status.isOk() || status.getCause() == null) ? "" : status.getCause().getMessage()
, now.toEpochMilli() - start.toEpochMilli()
);
}
};
super.start(listener, headers);
}
};
}
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall,
Metadata headers, ServerCallHandler<ReqT, RespT> serverCallHandler) {
// 服务端从headers中获取到链路追踪参数
String traceId = headers.get(TRACE);
val methodName = serverCall.getMethodDescriptor().getFullMethodName();
ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT> listener = new ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT>(serverCall) {
@Override
public void sendMessage(RespT message) {
try {
log.info("SERVER GRPC end - [{}] , method: [{}] , response: \n{ {} }", traceId, methodName, OBJECT_MAPPER.writeValueAsString(ObjectUtils.getDisplayString(message)));
} catch (JsonProcessingException e) {
log.error("SERVER GRPC-FORMAT end - [{}] , method: [{}] ", traceId, methodName);
}
super.sendMessage(message);
}
@Override
public void sendHeaders(Metadata responseHeaders) {
super.sendHeaders(responseHeaders);
}
@Override
public void close(Status status, Metadata trailers) {
super.close(status, trailers);
}
};
return new ForwardingServerCallListener.SimpleForwardingServerCallListener<>(serverCallHandler.startCall(listener, headers)) {
@Override
public void onMessage(ReqT message) {
try {
log.info("SERVER GRPC start - [{}] , method: [{}] , request: \n{{}}", traceId, methodName, OBJECT_MAPPER.writeValueAsString(ObjectUtils.getDisplayString(message)));
} catch (JsonProcessingException e) {
log.error("SERVER GRPC-FORMAT start - [{}] , method: [{}] ", traceId, methodName);
}
super.onMessage(message);
}
};
}
}