分布式日志输出:重写GRPC interceptor

因为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);
            }

        };
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值